5

我需要在 Cassandra 中计算一堆“东西”。我需要每隔几秒左右增加约 100-200 个计数器。

但是我需要计算不同的“事物”。

为了不计算两次,我在 CF 中设置了一个键,程序在增加计数器之前读取该键,例如:

result = get cf[key];
if (result == NULL){
    set          cf[key][x] = 1;
    incr counter_cf[key][x];
}

但是,此读取操作会大大降低集群的速度。我试图减少读取,使用几列,例如:

result = get cf[key];

if (result[key1]){
    set          cf[key1][x] = 1;
    incr counter_cf[key1][x];
}

if (result[key2]){
    set          cf[key2][x] = 1;
    incr counter_cf[key2][x];
}

//etc....

然后我将读取从 200+ 减少到大约 5-6,但它仍然减慢了集群的速度。

我不需要精确计数,但我不能使用位掩码,也不能使用布隆过滤器,因为会有 1M+++ 计数器,有些可能超过 4 000 000 000。

我知道 Hyper_Log_Log 计数,但我也看不到将它与那么多计数器 (1M+++) 一起使用的简单方法。

目前我正在考虑将 Tokyo Cabinet 用作外部键/值存储,但如果该解决方案有效,将不会像 Cassandra 那样具有可扩展性。

4

1 回答 1

4

当不同值的数量很大时,使用 Cassandra 进行不同计数并不理想。任何时候你需要先读再写,你应该问问自己 Cassandra 是否是正确的选择。

如果不同项目的数量较少,您可以将它们存储为列键并进行计数。计数不是免费的,Cassandra 仍然必须组装行以计算列数,但如果不同值的数量在数千个数量级,它可能会没问题。我假设你已经考虑过这个选项并且它对你来说是不可行的,我只是想我会提到它。

人们通常这样做的方式是将 HLL 或 Bloom 过滤器放在内存中,然后定期将它们刷新到 Cassandra。即不在 Cassandra 中进行实际操作,只是将其用于持久性。这是一个复杂的系统,但是有一种简单的方法可以计算不同的值,特别是如果你有大量的计数器。

即使你切换到其他东西,例如你可以对值进行位操作的东西,你仍然需要防止竞争条件。我建议你只是硬着头皮把所有的数都记在心里。通过键对处理节点上的增量操作进行分片,并将整个计数器状态(增量和不同)保存在这些节点的内存中。定期将状态刷新到 Cassandra,并在执行时确认增量操作。当一个节点对它在内存中没有的键进行增量操作时,它会从 Cassandra 加载该状态(如果数据库中没有任何内容,则创建一个新状态)。如果一个节点崩溃,操作还没有被确认并将被重新传递(你需要在节点前面有一个好的消息队列来处理这个问题)。

于 2013-03-13T08:19:48.190 回答