Reputation: 5391
What is the best approach to read an updated counter value in Cassandra? Let's say from my application I need to update a counter and then use its updated value. So I have two queries, the first updates the counter and the next reads it. As far as I understand there is no guarantee that the read query will get the updated counter due to the replication of the data. So as far as I can see there are two approaches:
Update the counter with consistency level ALL and then read it. I am not sure what the performance implications of this operation will be though?
Read the counter value before updating it, then update it. Then increment the read value by 1 and use it. Right now I do not see any problems with this approach?
Or there might be some other approach and some other factors I am not taking into consideration?
Anyway I would be glad to find out what the best practice is?
Upvotes: 1
Views: 1574
Reputation: 6559
As @doanduyhai explain, both of your approaches are prone to errors when concurrent clients increase the counter at the same time. This is a problem on our design, we use a counters table to be used as keys for the other tables, so we need unique ids. Yes, we know we may use UUID for unique ids, but we want to keep keys sort and easy to read on clients. Our solution:
v1 = read counter A.
-increase counter A.
v2 = read again counter A.
If v2 == v1+1, then the process is alone or is the first, use the counter and forget.
if not, is a signal of several processes contending, so:
sleep for a random period (so every process sleep a different amount of time and don't contend forever) and try again the complete loop.
Upvotes: 1
Reputation: 8812
As far as I understand there is no guarantee that the read query will get the updated counter due to the replication of the data.
The issue is more about distributed design of counter. See the below timeline
Initial counter value = 0
If client A reads back counter value before t2, it will see counter = 5
If client A reads back counter value after t2, it will see counter = 8 (+5 +3)
You just cannot now if, at the time your read back the counter value, someone else has updated it or not. Using lightweight transaction (LWT) to make counter update linearizable isn't an option because counters table do not support LWT.
Maybe you should describe your use-case so that we could devise an appropriate approach. What do you want to do with counters ? What are the types of query you expect to create to read your counters ?
Upvotes: 1