我需要在卡桑德拉计算一堆“东西”。 我需要每隔几秒左右增加约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,但它仍然会减慢群集的速度。
我不需要精确计数,但我不能使用位掩码,也不能使用bloom-filters, 因为将有1M +++计数器,有些可能会超过4 000 000 000。
我知道Hyper_Log_Log计数,但我看不到简单的方法将它用于那么多计数器(1M +++)。
目前我正在考虑将Tokyo Cabinet用作外部键/值存储, 但是这个解决方案,如果有效,将不会像Cassandra一样可扩展。
答案 0 :(得分:3)
当不同值的数量很大时,使用Cassandra进行不同的计数并不理想。任何时候你需要在写作之前进行阅读,你应该问问自己Cassandra是否是正确的选择。
如果不同项目的数量较小,您可以将它们存储为列键并进行计数。计数不是免费的,Cassandra仍然需要汇总行来计算列数,但是如果不同值的数量大约为数千,那么它可能就可以了。我假设你已经考虑过这个选项并且对你不可行,我以为我会提到它。
人们通常这样做的方法是将HLL或Bloom过滤器放在内存中,然后定期将它们刷新到Cassandra。即没有在Cassandra中进行实际操作,只是将其用于持久性。这是一个复杂的系统,但有很简单的方法来计算不同的值,特别是如果你有大量的计数器。
即使您切换到其他内容,例如您可以对值进行位操作,您仍需要防范竞争条件。我建议你只需咬紧牙关并在记忆中完成所有计数。通过密钥对处理节点上的增量操作进行分片,并将整个计数器状态(增量和不同)保留在这些节点的内存中。定期将状态刷新到Cassandra并在执行时执行增量操作。当一个节点获得一个它在内存中没有的键的增量操作时,它会从Cassandra加载该状态(或者如果数据库中没有任何内容,则创建一个新状态)。如果某个节点崩溃,则操作尚未被激活并将被重新传送(您需要在节点前面有一个好的消息队列来处理这个问题)。由于您对增量操作进行了分片,因此可以确保计数器状态仅被一个节点触及。