如何在没有过时的情况下快速增加cassandra中的计数器

lymnna71  于 2021-06-24  发布在  Storm
关注(0)|答案(3)|浏览(303)

我有个问题。你知道Cassandra是如何更新/增加计数器的吗?
我想使用storm bolt(github上storm contrib repo的cassandracounterbatchingbolt)写入cassandra。但是,我不确定incrementcountercolumn()方法的某些实现是如何工作的。。Cassandra计数器也有局限性(从:http://wiki.apache.org/cassandra/counters)这使得它们对我的场景毫无用处
如果写入意外失败(超时或失去与协调器节点的连接),客户端将不知道是否已执行该操作。重试可能导致Cassandra-2495计数过多。
计数器拆卸本质上受到限制。例如,如果您很快发出“increment,remove,increment”序列,则删除可能会丢失
不管怎样,这是我的设想:
我更新同一个计数器的速度比更新传播到其他cassandra节点的速度快。
例子:
假设我有3个cassandra节点。每个节点上的计数器都是0。
节点1:0,节点2:0,节点3:0
一个增量出现:5->node1:0,node2:0,node3:0
增量从节点2开始–仍然需要传播到节点1和节点3
节点1:0,节点2:5,节点3:0
同时,另一个增量在上一个增量之前到达
正在传播:3->节点1:0、节点2:5、节点3:0
假设3开始于与5开始于不同的节点,我们得到:
节点1:3,节点2:5,节点3:0
现在,如果3作为一个增量而不是一个新值传播到其他节点(对于5也是一样),那么最终节点都将等于8,这就是我想要的。
如果3覆盖了5(因为它有一个更晚的时间戳),这是有问题的-不是我想要的。
你知道Cassandra是如何处理这些更新/增量的吗?
请注意,在写入之前的读取仍然容易受到相同问题的影响,这取决于读取是从哪个副本节点执行的(如果传播距离不远,仲裁仍可能失败)
我也在想,也许把我的暴风雪和Cassandra放在一个缓存里可以解决这个问题,但这是另一个时代的故事。

j9per5c4

j9per5c41#

c*中的计数器有一个复杂的内部表示,可以避免在无引线分布式系统中计算事物的大多数(但不是全部)问题。我喜欢把它们当作碎片计数器。计数器由主机id和版本号标识的若干子计数器组成。接收计数器操作的主机仅递增其自己的子计数器,还递增版本。然后,它将其整个计数器状态复制到其他副本,这些副本将其与它们的状态合并。当计数器被读取时,处理读取操作的节点通过对每个主机的总计数求和来确定计数器值。
在每个节点上,一个计数器增量就像cassandra中的其他东西一样,只是一个写操作。增量写入memtable,本地值在读取时通过合并memtable和sstable中的所有增量来确定。
我希望这个解释能帮助你相信我,当我说你不必担心增加计数器的速度超过Cassandra所能处理的。因为每个节点都有自己的计数器,并且从不复制增量操作,所以不可能像读-修改-写场景那样,计数会因竞争条件而丢失。如果Cassandra接受了这封信,你的信肯定能算数。
但是,你不能保证计数在任何时候都是正确的,除非。如果一个增量被写入一个节点,但紧接着从另一个节点读取了计数器值,则不能保证该增量已被复制,您还必须考虑在网络分区期间会发生什么。这与cassandra中的任何write或多或少是一样的,它的最终一致性,取决于操作使用的一致性级别。
也有可能失去确认。如果你做了一个增量操作,在回复之前就断开了与cassandra的连接,你就不知道你写的东西是否得到了回复。当你恢复连接的时候,你也不知道,因为你不知道在你增加之前的计数是多少。对于选择可用性而不是一致性的系统来说,这是一个固有的问题,您为许多其他好处付出的代价也是如此。
最后,快速删除,增量,删除的问题是真实的,你应该避免。问题是增量操作本质上会恢复列,如果这些操作彼此足够接近,它们可能会得到相同的时间戳。cassandra是严格的last write wins,并根据操作的时间戳确定last。如果两个操作具有相同的时间戳,“较大”的一个操作获胜,这意味着按照严格的字节顺序排序的一个操作获胜。这是真的,但我不会太担心它,除非您对相同的值进行非常快速的写入和删除(这可能是数据模型中的错误)。
以下是Cassandra计数器内部的一个很好的指南:http://www.datastax.com/wp-content/uploads/2011/07/cassandra_sf_counters.pdf

yhuiod9q

yhuiod9q2#

当前版本的计数器并不适合需要保证不过度计数和立即一致性的用例。
有递增和递减操作,它们不会相互冲突,除非丢失突变或重放突变,否则将给出正确的结果。
Cassandra计数器的重写(https://issues.apache.org/jira/browse/cassandra-6504)您可能会感兴趣,它应该解决当前所有的问题,以获得正确的计数。
同时,如果我必须在当前版本的cassandra上实现这一点,并且准确的计数是必不可少的,我可能会将每个增量或减量存储为一列,并对结果进行读取时间聚合,在写回检查点时,这样就不必读回时间的开始来计算后续结果。
这给读端增加了很多负担,尽管它在写路径上非常有效,所以它可能适用于您的用例,也可能不适用于您的用例。

jslywgbw

jslywgbw3#

为了理解更新/增量,即写操作,我建议您浏览cassandra用于通信的协议gossip。在gossip中,每个参与者(节点)都使用元组来维护其状态 σ(K) = (V*N) 哪里 σ(K) 是国家的 KV 价值与 N 作为版本号。
为了维护数据包的单一版本,gossip维护了一种协调机制,即 Precise & Scuttlebutt (当前)。根据 Scuttlebutt Reconciliation ,在更新任何元组之前,它们相互通信以检查谁持有密钥的最高版本(最新值)。持有最高版本的人负责写操作。
更多信息请阅读本文。

相关问题