http://rockthecode.io/blog/highly-available-counters-using-cassandra/
This is the simplest counter to implement, especially for people coming from the RDBMS world. Acquire a lock on the counter, increment the counter and release the lock. In distributed systems, lockscan be implemented using an external coordinator, like Zookeeper.
1 lock.acquire();
2 try {
3 counter.increment(5);
4 } finally {
5 lock.release();
6 }
- Locking involves coordination and coordination is expensive
- If the counter is a hotspot, there will be high lock contention
- In distributed systems, messages may be redelivered. The solution will not handle duplicate messages and is not idempotent
LINEARIZABLE COUNTERS
This involves implementing a CAS (compare-and-swap) operation on a counter. This can be achieved using Zookeeper or Paxos based consensus in Cassandra.
1 int retries = 5;
2 while(retries > 0) {
3 int currentValue = counter.getValue();
4 if (!counter.compareAndSwap(currentValue, currentValue + 5)) {
5 try {
6 Thread.sleep(500); // You want to ideally use an exponential backoff algorithm here
7 } catch (InterruptedException e) {}
8 retries--;
9 } else {
10 break;
11 }
12 }
- High contention
- Not very scalable
- Non-idempotent
- May exhaust retries if the counter is a hotspot
CASSANDRA COUNTERS USING CRDTS
In this example, we will see how we can implement a CRDT based counter using Cassandra. We will show how we can model a counter using a CmRDT (operation-based) and a CvRDT (state-based). We’ll then model these using CQL.