(Transfer) Concurrency Recommendations to Replace Traditional Transactions

CRUD is the function of most frameworks. What if there are two concurrent requests to modify the same data? Or what about inserting duplicate data that should be unique? Or insert and modify with other auxiliary actions such as saving to another table such as editing the audit log.

You will first think of "transactions". Transactions do allow a group of operations to be executed reliably and safely, either all of them, or none at all. What if there are two concurrent transactions happening at the same time? Use the transaction isolation level, which is defined in ACID, and is done in relational database internals.

However, if you use isolation levels such as serializable (and repeatable read), your system will be slow, depending on different relational databases, and concurrent transactions may require application code coding to specify several retries, This is complicated, and other less stringent isolation levels can lead to lost updates or phantom reads.

Even if you set the appropriate isolation level correctly, you can correctly handle transaction failure error conditions with code, but isolation does not solve all concurrency problems, such as application-level data constraints, that is, a complex business Logical constraints or rules are difficult to implement by using database table key constraints; simply using database technology cannot solve the problem of repeated insertion; it cannot solve application-level concurrency problems; it cannot solve data concurrency and other problems. Maybe you try to solve these problems by acquiring database locks, but locks are terrible, locks have write locks, read locks and exclusive locks, how to avoid deadlocks? Not every programmer has experience working with locks.

The double submission problem is a classic problem, which shows that not all problems can be solved by the database alone. The solution for many people to double submit is to use a token to represent each request and store it in the database, using the unique key constraint of the database. , in this way, duplicate records cannot be inserted. This kind of problem is more complicated using API, because you have to generate appropriate tokens according to the user of the API. Also, although you use database unique constraints, you have to check in the application code, because two rows with different keys but the same value may still be inserted.

Most of the concurrency is running on a single machine, which can use the concurrency feature of the language to ensure serialization of execution, double repetition is impossible, but when you deploy the application on more than a few machines, the concurrency problem becomes difficult. The following is a solution

to using concurrency
instead of transactions: 1. Similar to Hazelcast, which provides distributed locks, the entire cluster follows lock semantics like a single machine, but there are not many applicable scenarios.

2. Use a message queue – push all requests into a message queue, the queue will be processed by a single asynchronous worker, but may not be suitable for business scenarios that need to be returned to the user immediately.

3. Using Akka and its cluster can ensure that an actor (which can be regarded as a service) only processes one message at a time, but because akka completely changes the usage paradigm, it is difficult to use and trace debugging, and it is related to the characteristics of the language platform.

4. Use database application-level locks, such as relational database Postgre provides advisory locks, MySQL also has similar get_lock, using relational databases as distributedLock mechanism, the lock is managed by the application, and the table library does not need to do anything. As long as the request is the entityType, entityId fields request a lock, it is guaranteed that no other application thread can execute the specified piece of code in the application only when the database lock is obtained. It is used to replace language synchronization locks with database locks, and then use Spring's @Before AOP methods to intercept service methods.

5. Use CRDT. It is an idempotent data structure, and regardless of the order of operations on it, the final result is the same state. But completely idempotent operations are rarely encountered in practice.

6. Use "insert-only" append-only models. Databases like Datomic use this model internally, you can use this model in any database, only new appends, no deletes and updates, each time a new version is used number to insert a new record. In this way, the uniqueness of the version number ensures that there will be no duplicate records. You will not lose data, which is equivalent to getting a revision log for free (banq note: it is actually the EventSourcing event flow log).

The above methods are all about how to serialize requests without losing performance, including various lock mechanism queues and non-blocking. I/O.

Reprinted from: http://www.jdon.com/48003

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326978261&siteId=291194637