How to implement optimistic locking with Aerospike and Project Reactor ?

1. Introduction

Optimistic locking is general pattern commonly used to maintain data consistency.

OptimisticSketch

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:

retryWhenForMono

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.

Oleksii Zghurskyi