You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Cassandra JDBC驱动读取记录时数据丢失的原因咨询

问题原因分析

这个现象的核心是Cassandra的写入路径机制和非精准分区查询的可见性逻辑共同导致的,即使单节点集群也会出现,具体原因如下:

1. Cassandra写入的异步持久化特性

Cassandra的写入流程是:

  • 先将数据写入内存中的memtable,只要memtable写入成功,就会向客户端返回写入成功
  • 之后memtable会异步批量刷写到磁盘上的SSTable,这个过程不是立即触发的(默认当memtable达到一定大小或定时触发)

在memtable还没刷写到SSTable之前,只有通过精准匹配分区键的查询(比如SELECT * FROM productInfo WHERE productId = ?)才能读取到这部分数据;而像SELECT *全表扫描、SELECT * WHERE timestamp > ?这类非精准分区的范围/过滤查询,是通过遍历磁盘上的SSTable来获取数据的,不会主动扫描memtable中的未持久化数据(或者说,这类查询的扫描范围在启动时就固定为已存在的SSTable,不会包含查询过程中写入的memtable数据)。

2. 分区键设计放大了可见性问题

你的表中每个productID都是唯一分区键,意味着10000条记录对应10000个独立分区。当读写并行时:

  • 写应用持续向不同分区写入数据,大量新数据分散在各个分区的memtable中
  • 读应用的初始全表扫描需要遍历所有10000个分区,但此时很多分区的新数据还在memtable里,没被刷写到SSTable,因此这部分数据不会被初始扫描捕获
  • 后续你用timestamp > lastNotedTimestamp做增量查询,而那些没被初始扫描到的记录,其timestamp可能小于初始扫描得到的lastNotedTimestamp(因为是并行写入,这些记录的写入时间早于初始扫描完成时间),导致后续查询永远不会再读取到它们,最终表现为“随机丢失记录”

3. 写入完成后无丢数的原因

当所有写入操作完成后,Cassandra会将所有memtable异步刷写到SSTable(你也可以手动执行nodetool flush testkeyspace productInfo强制刷写)。此时全表扫描或范围查询可以遍历到所有SSTable中的数据,自然能返回全部记录,不会出现丢数。

补充验证点

你可以做个简单测试验证这个逻辑:

  • 在读写并行时,当发现丢记录后,立即执行nodetool flush testkeyspace productInfo
  • 再执行查询,之前丢失的记录会出现在结果集中

内容的提问来源于stack exchange,提问作者Mohamed Kamarudeen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:05:26