使用 Cassandra 进行事件重复数据删除

2024-03-10

我正在寻找使用 Cassandra 消除重复事件的最佳方法。

我有很多客户端接收事件 ID(每秒数千个)。我需要确保每个事件 id 都被处理一次且仅一次,并且具有高可靠性和高可用性。

到目前为止我已经尝试了两种方法:

  1. 使用事件 id 作为分区键,然后执行“INSERT ... IF NOT EXISTS”。如果失败,则该事件是重复的并且可以被删除。这是一个很好的干净方法,但是由于 Paxos,吞吐量不是很大,尤其是在复制因子较高(例如 3)的情况下。它也很脆弱,因为 IF NOT EXISTS 总是需要法定人数才能工作,并且没有办法回退到较低的复制因子如果法定人数不可用,则保持一致性。因此,几个关闭的节点将完全阻止某些事件 ID 的处理。

  2. 允许客户端在同一事件 ID 上发生冲突,然后使用聚类列检测冲突。因此,使用事件 id 作为分区键进行插入,并使用客户端生成的 timeuuid 作为集群列。然后,客户端将等待一段时间(以防其他客户端插入相同的分区键),然后读取限制为 1 的事件 id,以返回最旧的聚集行。如果它读回的 timeuuid 与它插入的内容相匹配,那么它就是“获胜者”并处理该事件。如果 timeuuid 不匹配,则它是重复的,可以删除。

碰撞(面包师算法)方法比使用 IF NOT EXISTS 具有更好的吞吐量和可用性,但它更复杂并且风险更大。例如,如果客户端上的系统时钟出现故障,则重复事件将看起来像非重复事件。我的所有客户端和 Cass 节点都使用 NTP,但这在同步时钟方面并不总是完美的。

有人对使用哪种方法有建议吗?还有其他方法可以做到这一点吗?

另请注意,我的集群将设置三个数据中心,DC 之间的延迟约为 100 毫秒。

Thanks.


IF NOT EXISTS 的扩展性不如现有的 Cassandra(因为协调速度很慢,但您知道这一点),但可能是“官方的、正确的”方法。还有另外两种“有效”的方法:

1)使用外部锁定系统(zookeeper、memcached CAS等),它允许您处理cassandra外部的协调。

2)使用一个丑陋的反向时间戳技巧,以便第一个写入获胜。不要使用客户端提供的与实际挂起时间相对应的时间戳,而是使用 MAX_LONG - (挂起时间) = 时间戳。这样,第一次写入具有最高的“时间戳”,并且将优先于后续写入。这种方法是有效的,尽管它对 DTCS 之类的东西(如果你正在做时间序列并且想要使用 DTCS,不要使用这种方法,DTCS 会非常混乱)和一般删除(如果你真的想要删除具有真实墓碑的行,您还必须使用人工时间戳写入该墓碑。

值得注意的是,有人尝试解决 cassandra 的“最后写入总是获胜”的性质 - 例如,CASSANDRA-6412(我曾在某个时候工作过,并且可能会在下个月或所以)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Cassandra 进行事件重复数据删除 的相关文章

随机推荐