Cassandra 3.11.2单节点删除SSTable后数据仍存在的问题求助
解答:删除SSTable后仍能查询到Cassandra数据的原因及排查步骤
我来帮你拆解这个问题——你遇到的情况其实是Cassandra的存储机制特性导致的,不是系统bug。下面一步步分析原因和排查方法:
核心原因:Cassandra的内存缓存与文件句柄机制
你执行nodetool flush后,MemTable确实会被刷写到磁盘变成SSTable,但这并不意味着内存里的缓存会立即清空,而且操作系统的文件句柄机制也会让Cassandra在你删除文件后仍能访问到数据。具体来说:
- 缓存未失效
默认情况下Cassandra的key_cache是开启的,如果你的表还配置了row_cache,查询过的数据会被缓存在内存中。即使磁盘上的SSTable被删除,Cassandra会直接从缓存返回数据,直到缓存过期或被主动清空。 - 文件句柄未释放
当Cassandra进程打开SSTable文件后,你用rm *.db删除文件,操作系统只是把文件标记为"待删除",但只要Cassandra还持有该文件的句柄,进程依然可以读取文件内容。只有当Cassandra进程重启,或者文件句柄被主动释放(比如执行nodetool refresh),这些文件才会真正被系统回收。
分步排查验证
步骤1:检查缓存状态并手动清空
先确认缓存配置,再清空缓存验证:
- 查看表的缓存配置:
看输出里是否有DESCRIBE TABLE test.test;row_cache_enabled: true或者key_cache_enabled: true的配置。 - 强制刷盘并清空缓存:
之后再查询数据,如果数据还在,那大概率是文件句柄的问题。nodetool flush test test # 确保所有MemTable都刷到磁盘 nodetool clearcache # 清空key cache和row cache
步骤2:验证Cassandra是否仍持有已删除文件的句柄
用lsof命令检查Cassandra进程是否还在访问已被标记删除的SSTable文件:
# 先获取Cassandra进程ID CASS_PID=$(ps aux | grep cassandra | grep -v grep | awk '{print $2}') # 查看进程持有的已删除文件 lsof -p $CASS_PID | grep deleted
如果输出里有你删除的.db文件,说明Cassandra还在通过文件句柄读取这些"已删除"的内容。
步骤3:重启Cassandra进程验证
这是最直接的验证方式——重启Cassandra后,进程会重新加载磁盘上的SSTable,此时如果数据真的被删除,查询结果应该为空:
service cassandra restart # 或者用你实际的启动命令,比如前台启动看日志: # /opt/cassandra/bin/cassandra -f
重启后再查询test.test表,正常情况下就看不到之前的数据了。
步骤4:检查是否遗漏了其他SSTable文件
有时候你可能只删除了部分SSTable文件,比如压缩生成的分层文件、或者位于子目录里的文件。可以用以下命令遍历整个表的数据目录:
find /var/lib/cassandra/data/test/test -name "*.db"
(路径替换成你实际的Cassandra数据目录)如果还有剩余的.db文件,那这些就是数据的来源。
额外建议:正确删除Cassandra数据的方式
不要直接用rm删除SSTable文件,这会导致不可预测的问题。正确的操作方式是:
- 如果要删除整个表:执行
DROP TABLE test.test;,Cassandra会自动清理所有相关文件和缓存。 - 如果要清空表内所有数据:执行
TRUNCATE TABLE test.test;或者nodetool truncate test test,这些操作会让Cassandra按照自身的存储逻辑处理数据清理。
内容的提问来源于stack exchange,提问作者Vishal Sharma
相关产品推荐
相关产品推荐

