cool breeze cool breeze - 1 month ago 18
Scala Question

Increment and get value of counter

Is there a way to increment a counter and then get the value back in a single call?

Or is the only way to make 2 calls?

Answer

This is not a phantom limitation but a Cassandra API one, there is nothing in CQL that allows you to retrieve and update the value in the same API call, and there's a very very good reason for that.

When you update the value of a counter the CQL looks like this:

UPDATE keyspace.table SET counter = counter + 1 WHERE a = b;

However, this masks away the true distributed locking complexity Cassandra must undergo to perform a seemingly simple increment. This is because it's really hard to make sure that every count is updating the latest value and that multiple increments of the same counter will wind up with the same value.

So you need a guarantee of the write being acknowledged by enough replicas after which you can perform a safe read, and this is making it sound really easy. In reality there's an incremental merge/compare-and-set process that goes on in a single counter increment, better detailed here.

The read operation is simply:

SELECT * FROM keyspace.table WHERE a = b;

If you think you are saving much network wise or complexity wise by doing this, you probably aren't unless the volume of read/writes is immense. In short, it's a happy thought but I wouldn't bother.

for {
  inc <- database.table.update.where(_.a = b).modify(_.counter increment 1).future()
  value <- database.table.select(_.counter).where(_.a = b).one()
} yield value