How to implement optimistic locking with Aerospike and Project Reactor ?
1. Introduction
Optimistic locking is general pattern commonly used to maintain data consistency.
In this post I will describe how to implement optimistic locking with No-SQL storage, that has reactive client.
2. Aerospike generation
meta-data
In traditional RDBMS to implement optimistic locking one would have to introduce additional version
or timestamp
column.
In case of Aerospike, required data is available by default: each record has generation
meta-data. So, in order to fail, when record is updated/deleted concurrently, one would need only enable GenerationPolicy.EXPECT_GEN_EQUAL
:
ClientPolicy clientPolicy = new ClientPolicy();
clientPolicy.writePolicyDefault.generationPolicy = GenerationPolicy.EXPECT_GEN_EQUAL;
Having above config in place ensures that update/delete will be executed successfully, if expected generation is equal to server generation, otherwise, update/delete will fail.
3. Reactor retryWhen
operation
Project Reactor is a fourth-generation Reactive library for building non-blocking applications on the JVM based on the Reactive Streams Specification.
In the context of our goal, we will use retryWhen operation:
4. Implementation
Now let’s put everything together and write method that performs createOrUpdate
operation on Data
instance:
public Mono<Data> createOrUpdate(Data data) {
return Mono.defer(() -> doCreateOrUpdate(data))
.retryWhen(Retries.optimisticLockException(retryProperties)
.doOnRetry(context -> log.warn("Retrying optimistic failure for data", data, context.exception()))
);
}
private Mono<Data> doCreateOrUpdate(Data data) {
return repository.findDataByKey(data.getKey())
.map(existingData -> data.withGeneration(existingData.getGeneration()))
.flatMap(existingData -> repository.createOrUpdate(existingData).map(Functions.constant(existingData)));
}
5. Conclusion
Implementing optimistic locking with Aerospike and Reactor is pretty straight-forward. Since all tools are already in place, all that needs to be done - put everything together.