2

I have a microservice to wrap the access to a MongoDB (DaaS). It is implemented with Spring Data Reactive Repository (ReactiveMongoRepository).

I have deployed within a docker image, running on Kubernetes (in Google Cloud). I have configured the orchestrator to keep a minimum of 2 pods of my microservice (and a maximum of 4).

In other microservice, I have implemented a batch process with multithreading, where I call my daas, with the following sequence:

  1. findById
  2. Modify some fields (including increments of counters)
  3. save

Here is the relevant code:

public Mono<Element> updateElement(String id) {
    return this.daasClient.findById(id)
        .map(elem -> modify(elem))
        .flatMap(elem -> this.daasClient.save(elem));
}

When there are lots of operations, each pod runs some of then (including the previuos code), so I have seen that the access to the resource (Mongo) is not thread safe, so the resut is not as expected.

I guess, 2 pods run the findById simultaneously, so the update is not to the "real" document, so, the last in invoking the save method overrides the changes of the other.

Anybody know how I could do to avoid this, i.e., to implement this operation in thread-safe (pod-safe) way?

Thanks

Martin Tarjányi
  • 8,863
  • 2
  • 31
  • 49
Alberthoven
  • 2,798
  • 1
  • 24
  • 29
  • If I understand correctly what you need is a transaction. Mongo and its reactive client seems to have support for it. I suggest to check that out. – Martin Tarjányi Feb 09 '21 at 08:26
  • Yes, it seems to me. I am reading about that, although I'm not sure if it could solve my problem, because still I have more than one instance of the application running at time. – Alberthoven Feb 09 '21 at 12:11
  • This is a hard problem to solve. One soulution could be to have a smart load balancer which forwards odd IDs to one instance and even IDs to another. Other solution would be to implement Optimistic locking - a technique that reliably determines if a record has been updated by another process between the time it was initially loaded into memory and the time a save is attempted. – NikolaB Feb 09 '21 at 16:31
  • Thaks for the tips.I will research about Optimistic locking, but I am not sure if that is possible for reactive repositories. – Alberthoven Feb 10 '21 at 17:11
  • Have this same exact issue currently. How did you end up solving it? – Macindows Jun 10 '21 at 19:20
  • 1
    @Macindows What we have done is, on the one hand, use Spring Data version management (field annotated with @Version) to avoid updating an obsolete document and, on the other, implement a duplicate control mechanism with a Redis DB. When we start processing a record, we "block" it by inserting it into Redis, so if another thread (pod) tries to access it, when consulting Redis, it finds that it is blocked and does not try to process it. – Alberthoven Jun 14 '21 at 08:02
  • @Alberthoven Having another db is not an option for us, but thanks for your inputs. – Macindows Jun 14 '21 at 08:26

0 Answers0