我想用Cassandra来存放一个柜台.例如,查看给定页面的次数.柜台永远不会减少.计数器的值不需要精确,但随着时间的推移应该是准确的.
我的第一个想法是将值存储为列,只读取当前计数,将其递增1,然后将其重新放入.但是,如果另一个操作也试图递增计数器,我认为最终值只是一个有最新的时间戳.
另一个想法是将每个页面加载存储为CF中的新列.然后我可以运行get_count()
该键并获得列数.阅读文档,似乎根本不是一个非常有效的操作.
我是否错误地接近了这个问题?
[更新]看起来计数器支持将准备好在0.8的黄金时段!
我绝对不会使用get_count,因为这是每次读"计数器"时都会运行的O(n)操作.更糟糕的是它只是O(n),它可能跨越多个节点,这会引入网络延迟.最后,为什么当你关心的只是一个数字时占用所有磁盘空间?
就目前而言,我根本不会使用Cassandra作为计数器.他们正在研究这项功能,但尚未准备好迎接黄金时段.
https://issues.apache.org/jira/browse/CASSANDRA-1072
你平时有几个选择.
1)(错误)将您的计数存储在一个记录中,并且您的应用程序中只有一个线程负责计数器管理.
2)(更好)将计数器拆分为n个分片,并且有n个线程将每个分片作为单独的计数器进行管理.您可以随机化每次应用程序使用的线程,以实现跨这些线程的无状态负载平衡.只需确保每个线程只负责一个分片.
3a)(最佳)使用一个单独的工具,它是事务性的(也称为RDBMS)或支持原子增量操作(memcached,redis).
[Update.2]我会避免使用分布式锁(请参阅memcached和zookeeper互斥锁),因为如果实施不当,这对节点故障或网络分区非常不容忍.
计数器已被添加到Cassandra 0.8
使用incr方法将列的值增加1.
[default@app] incr counterCF [ascii('a')][ascii('x')]; Value incremented. [default@app] incr counterCF [ascii('a')][ascii('x')]; Value incremented.
请在此处描述:http://www.jointhegrid.com/highperfcassandra/? p = 79
或者它可以以编程方式完成
CounterColumn counter = new CounterColumn(); ColumnParent cp = new ColumnParent("page_counts_by_minute"); counter.setName(ByteBufferUtil.bytes(bucketByMinute.format(r.date))); counter.setValue(1); c.add(ByteBufferUtil.bytes( bucketByDay.format(r.date)+"-"+r.url) , cp, counter, ConsistencyLevel.ONE);
这里描述:http://www.jointhegrid.com/highperfcassandra/? cat = 7