How to implement atomic read-change-write?


I have a consul stand-alone installation, which I use as kv store, for, among other things, ansible inventories.

When a process modifies an inventory (a value in the KV store) I want to make sure that between the read and the write there is no other writes. That is that the process is modifying the latest version of the value. I specifically want to avoid a situation when process read something, then another process reads the same, the first process writes changes, and now the second process works with the stale version of the data an may overwrite the first process changes without knowing it.

This is what I’m planning to implement to resolve that:

  • Process that intends read and write data creates a session with some reasonable TTL (say 10s)
  • Process runs a transaction in that session on the KV with the verb lock. Repeat until stop getting “lock is already held”
  • Read the data. Does not have to use a transaction or session for that
  • Modify the data and write it. Does not have to use a transaction or session for that
  • Run the transaction on the KV with the verb unlock and delete the session

Will this achieve what I want, or did I miss something? I understand that a stand-alone consul is not base practice, because it’s a single point of failure, I’m willing to take that risk.

Hi @AndrewSav,

You can also achieve this by using Consul’s check-and-set (cas) function when updating keys. The following blog post provides a great explanation on how to use this functionality.