我使用Cassandra来存储交易信息。根据可用的查询,我设计我的CF如下:
CREATE trades (trading_book text,
trading_date timestamp,
OTHER TRADING INFO ...,
PRIMARY KEY (trading_book, trading_date));
我想以下列方式删除指定日期的所有数据:
DELETE FROM交易WHERE trading_book ='A_BOOK'AND trading_date = '2015年1月1日'
大约有100万笔交易,删除需要2分钟才能完成。然后在删除完成后立即再次在2015-01-01上插入交易数据(约100万笔交易)。
当插入完成并重新读取数据时,即使查询超时设置为600秒,我也收到错误:
ReadTimeout: code=1200 [Coordinator node timed out waiting for replica nodes' responses] message="Operation timed out - received only 0 responses." info={'received_responses': 0, 'required_responses': 1, 'consistency': 'ONE'} info={'received_responses': None, 'required_responses': None, 'consistency': 'Not Set'}
现在看起来CF中的数据不一致,即协调员可以识别分区,但分区上没有数据?
我的访问模式有什么问题吗?如何解决这个问题?
任何提示都将受到高度赞赏!谢谢。
答案 0 :(得分:4)
您正在为该日期的每一列创建逻辑删除(通过执行删除操作),然后在顶部创建新记录。所以现在每次读取必须首先读取原始列,然后是逻辑删除,然后是新记录。如果你做了一个跟踪,你会看到墓碑读取正在杀死你。这种模式对于Cassandra来说是有问题的,所以你应该尝试找到一种不同的(不可变的)方法来做到这一点。另一种方法是简单地覆盖数据,在这种情况下,没有可以协调的墓碑。但是你仍然需要处理两个版本。
答案 1 :(得分:2)
除了rs_atl的回复(其中有关于墓碑的指甲),这里有一些信息可供您理解/解决问题:
因为sstables是不可变的,而不是删除Cassandra中的记录,所以我们插入一个基本上保持空值的新单元格。那是一块墓碑。在gc_grace秒之后,墓碑可用于删除或垃圾收集(可由表配置)。
我们等待的原因是确保c *有时间将墓碑传播到所有副本。如果逻辑删除没有被复制到所有副本(例如在一些边缘情况下具有低CL写入和翻转节点)然后被删除/ gc,则删除的原始数据将恢复生命。这就是为什么我们至少每个GC_Grace运行修复,确保墓碑一致性和防止僵尸数据。
如果您在cqlsh tracing on
中启用跟踪或在yaml或通过nodetool启用概率跟踪,您将能够看到您为特定请求命中了多少个逻辑删除。随着此数字变大,您的阅读效果将会下降,直到您看到您提到的超时时间为止。
nodetool cfstats
还为您提供了表格中有多少个墓碑的宏细节(每片的平均墓碑)。
sstablemetadata
实用程序会显示表格中的墓碑总数。
1)如果您要删除表中的所有内容,truncate table是一种在c *中免费删除数据的方法,因为您可以使整个sstables过期。
2)通过压实去除墓碑。您可以通过减少gc_grace_seconds
和/或增加tombstone ratio进行压缩来更积极地删除逻辑删除,但请确保您正在运行修复,否则您可能会看到僵尸数据。