Ways to Mitigate Concurrency

The underlying problem is multiple processes working on the same resource, so the mitigation methods look at how to limit exposure. Let’s first look at general concepts and then look more specifically at databases, which usually are at the heart of concurrency issues.

Two simple generic methods, resource locks and atomic operations, are generally good enough to use in most situations. Locking deals directly with concurrency by preventing simultaneous process flows. Atomic operations move operations closer to the resources and enforce serialization at the resource level.

Locking the resources so no one else can run them makes sense if the workflow is not supposed to run concurrently. In the withdrawal example, you wouldn’t want the same person to make multiple concurrent operations. The following flowchart illustrates how locks work. You start by having the process acquire a lock. If it fails, another process is already using the resource and it must wait for that process to finish. If the lock acquiring succeeds, you process the request. After you finish, you release the lock.

The process seems straightforward, but there are a few problems with this kind of resource locking. The locking process itself must be atomic and not subject to concurrency issues. You don’t want to lock up the whole table, so you have to make sure the lock only affects a small area of the application. There also needs to be a fail-safe in case the process fails to unlock a resource or the program crashes before the locks are released.

Locking creates bottlenecks in applications, and so it’s not recommended if you need high throughput, if the process affects a large part of the resouces, or processing takes a long time. You want the lock to be in place over a small area for a short period of time. Otherwise, you should modify the application logic or use atomic operations instead.

Atomic operations address concurrency by moving operations closer to the resource and in a manner that prevents other processes from manipulating data in between operations. Some operations are truly atomic. They tend to be simple functions that run serially in the resource layer, such as INSERT in SQL and INCR in Redis. When this command is running, another one won’t run against the same table during that time.

Some operations can be grouped and performed as an atomic operation, such as MULTI in Redis. Several commands are grouped together and executed as a block without allowing other operations while they’re running. Other operations are optimistic locks, such as TRANSACTION in SQL and WATCH EXEC in Redis. They tend to be used for more complex tasks and involve executing the operations as a sequence. If no errors occur and no other process has modified the same resources during the execution of the sequence, then all the operations will be run and committed. If something goes wrong, the rollback restores state to what it was before the transaction started.

Atomic operations modify the resource serially by not allowing other operations to access the resource during that time. At a close level they can and sometimes are implemented with lock mechanisms. Only the locking processing and unlocking happen in a short timespan and inside the operation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.225.55.151