Using Generation Code to do concurrency safe write-aside cache


#1

We want to use Aerospike as a write-aside cache. We need to be careful not to store data that is stale due to concurrent changes. What is the best way to set a single value into a key and assert the key has not changed since you last read it? We are using the .NET client.

I can imagine a possible implementation looks something like, where each line is atomic operation:

  • “Touch” the key to increment and retrieve a new generation code
  • Modify/persist data in source (an RDBMS)
  • Store source data in cache IFF current generation code matches value from step 1

Is this the right approach? If so, how do I do that in the .NET client?

Thanks.


#2

Hi,

Can you please define what you mean by a write-aside cache? Is this similar to a write-behind cache?

The use-case of “read then write if the data hasn’t changed since it’s been read” is typically implemented using a Check-And-Set operation (CAS), very similar to what you mentioned. This involves:

  • Reading the Record
  • Modifying the Record in the application
  • Writing the modified data with a generation equal to the generation initially read and a WritePolicy of EXPECT_GEN_EQUAL.

Sample code would be:

Key key = new Key("test", "users", username);
Record record = client.get(null, key);

// Set the write policy to fail the put if the generation has changed.
WritePolicy wPolicy = new WritePolicy();
wPolicy.generationPolicy = GenerationPolicy.EXPECT_GEN_EQUAL;
wPolicy.generation = record.generation;

Bin bin1 = new Bin("username", username);
Bin bin2 = new Bin("password", password);

client.put(wPolicy, key, bin1, bin2);

Note that the put will throw an AerospikeException with an error code of 3 (Generation error) if the data has changed between when it was read and when the put is executed. So proper exception handling is a must.

Please let me know if this doesn’t match your use-case.

Kind regards,

Tim


#3

What would happen in the scenario that you have cross data center replication, the record doesn’t exist on both the clusters and both regions write with generation 0.

Due to the xdr replication lag both writes would not throw an error, correct?

How do we handle that scenario