Design Pattern for Write Heavy Application - getAndLock?


#1

I am trying to come up with an elegant solution using couchbase that I think getAndLock is a good use case for.

I have a user record that exists. We have many application servers that all may need to access this user record update various properties and save it. This could happen in a highly concurrent, multi-server, multi-threaded environment.

The fetch/modify/update are all VERY short lived. Would using getAndLock() be a good use case for this? I would prefer to NOT have to worry about merging changes. The ideal is simply to not let another server/thread access the User by key if it is already being processed.

What is the behavior in the SDK when you issue a getAndLock() when the record is already locked? Does it block or return immediately with some type of predictable exception? The API doesn’t really give much clarification here.

Are there any major performance issues with a getAndLock design pattern?

Thanks!


#2

You would be better off looking at the CAS based operations. In the 2.0 Java client, this would be a replace() operation using a CAS argument. This is “optimistic concurrency”, and in the case of a collision you’d backoff and retry.

The intent of getAndLock() is more for situations where you need cooperative, exclusive access to a graph of items. Take for instance a situation where A references B which references C and D. Then say based on a visit to D, you want to update B and C. Then you’ll want to ‘lock’ the graph, then CAS to unlock the items in reverse order.

It’s a good tool, but make sure you have good test coverage if you need it. Where possible, it’s probably better to just use a CAS operation or consolidate all of the data to a single document. It’s not always possible, of course, which is why getAndLock() is available.


#3

@gmina, in addition, the CAS path is very smooth on the new SDK, because it is automatically populated into the Document when you load it.

so you can 1) run a get() to fetch the Document 2) modify its content 3) do a replace with the same document and the CAS value will be taken into account automatically. You can then build retry logic based on the CASMismatchException that will either error your observable in async cases or thrown in sync ones.