Nic*_*ick 5 cassandra distinct-values
我需要计算 Cassandra 中的一堆“东西”。我需要每隔几秒左右增加约 100-200 个计数器。
但是我需要计算不同的“事物”。
为了不计算两次,我在 CF 中设置了一个键,该程序在增加计数器之前读取,例如:
result = get cf[key];
if (result == NULL){
set cf[key][x] = 1;
incr counter_cf[key][x];
}
Run Code Online (Sandbox Code Playgroud)
但是,此读取操作会大大降低集群速度。我尝试使用几列减少读取,例如:
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....
Run Code Online (Sandbox Code Playgroud)
然后我将读取次数从 200+ 减少到大约 5-6,但它仍然减慢了集群的速度。
我不需要精确计数,但我不能使用位掩码,也不能使用布隆过滤器,因为会有 1M+++ 计数器,有些可能会超过 4 000 000 000。
我知道 Hyper_Log_Log 计数,但我也没有看到将它与这么多计数器(1M+++)一起使用的简单方法。
目前我正在考虑使用 Tokyo Cabinet 作为外部键/值存储,但是这个解决方案,如果有效,将不会像 Cassandra 那样具有可扩展性。
当不同值的数量很大时,使用 Cassandra 进行不同计数并不理想。任何时候您需要在写入之前进行读取,您都应该问自己 Cassandra 是否是正确的选择。
如果不同项目的数量较小,您可以将它们存储为列键并进行计数。计数不是免费的,Cassandra 仍然必须组合行来计算列数,但如果不同值的数量约为数千,则可能没问题。我假设您已经考虑过这个选项,并且它对您来说不可行,我只是想提一下。
人们通常的做法是将 HLL 或 Bloom 过滤器放在内存中,然后定期将它们刷新到 Cassandra。即不在 Cassandra 中进行实际操作,只是将其用于持久性。这是一个复杂的系统,但有一种简单的方法可以计算不同的值,特别是如果您有大量计数器的话。
即使您切换到其他内容,例如可以对值进行位运算的内容,您仍然需要防止竞争条件。我建议你咬紧牙关,在记忆中完成所有的计数。按键对处理节点上的增量操作进行分片,并将整个计数器状态(增量和不同)保留在这些节点上的内存中。定期将状态刷新到 Cassandra,并在执行时确认增量操作。当节点获得内存中没有的键的增量操作时,它会从 Cassandra 加载该状态(或者如果数据库中没有任何内容,则创建一个新状态)。如果节点崩溃,则操作尚未被确认并将被重新传递(您需要在节点前面有一个良好的消息队列来处理此问题)。由于您对增量操作进行了分片,因此您可以确保计数器状态仅被一个节点触及。
归档时间: |
|
查看次数: |
2860 次 |
最近记录: |