Problem analysis

In our daily development, the most frequently used scenarios for caching are as shown in the following figure, which may simply cache data to reduce database pressure and shorten interface response time.

Data inconsistencies in high concurrency writes

With high concurrent reads and writes, the order in which the steps of a request are executed is not controllable. Suppose there is A request A at this time, and B is performing the write process. Request A needs to change some data to 1, and request B needs to change some data to 2. Data inconsistency will occur when the following operations are performed:

1. Request USER A to perform 1.1 deleting the Cache.

2. Request USER A to perform operation 1.2 Updating the Database and change the value to 1.

3. Request USER B to perform 1.1 Deleting cache.

4. Request B to perform operation 1.2 Update the database and change the value to 2

5. Assume that the network latency of the server where request B resides is low and request B updates the cache first. In this case, the value corresponding to the key in the cache is 2.

6. Request A to update the cache, overwrite the data updated by B in the cache, and change the value corresponding to key to 1.

In this case, the database contains B’s modified data with a value of 2, while the data in the cache is 1. In this way, when the cache expires, the user will read dirty data, which is inconsistent with the database.

Data inconsistencies in high concurrency reads and writes

With high concurrent reads and writes, the order in which the steps of a request are executed is not controllable. Suppose that A request A is performing A write process, changing the original value from 1 to 2, and request B is performing A read process. The following operations will cause data inconsistency:

1. In write request A, perform 1.1 to delete the cache key. The value is original value 1.

2. Read request B performs 2.1 and finds no data in the cache. Then, B performs 2.2 to read the database.

3. Write request A Performs 1.2 to update the database and change data from 1 to 2.

4. In write request A, perform 1.3 to update the cache, and the value of the data key in the cache is 2.

5. In read request B, perform 2.3 to update the cache, and set the read old data 1 to the cache. In this case, the value of the key in the cache is 1.

Therefore, if the network latency of the server where read request B resides is high and the operation 2.3 is performed later than that of write request A, the cache of read request B is updated after the cache of write request A is updated, and the data in the cache is inconsistent with that in the database.

The solution

To ensure data consistency, there are many solutions on the Internet, such as:

1. Delete the cache and then update the database.

2. Update the database before deleting the cache.

3. Delete the cache first, update the database, and then asynchronously delay deleting the cache again.

However, there are all kinds of problems in these schemes. The space here is limited, and only three schemes that are relatively correct at present are given. These schemes also have their own limitations.

Scheme 1. Serialize write requests

Write requests

1. Obtain the distributed lock before the write request is updated. After obtaining the distributed lock, the database can update the data.

2. Refresh the cache after the update. If the refresh fails, put the database into a memory queue and retry.

Read requests

When the read request finds that there is no data in the cache, it directly reads the database and finishes the update cache.

conclusion

This technical solution serializes write requests to ensure data consistency, but results in low throughput. Fit in with the bank related business, because for bank project, guarantee the data consistency is more important than availability, like to save money deposit machine, take the money, in order to ensure the safety of the account, is will allow the user to execute after the operation, wait for a while to get feedback, this paragraph of time the ATM is not available.

Solution 2. Update the database and asynchronously delete the cache. If the deletion fails, try again

1. Update the database first

2. Asynchronously delete the cache (if the database is read/write separated, then the deletion of the cache needs to be delayed. Otherwise, other read requests may read the old data from the library and set it to the cache before the updated data is received.)

3. If the cache fails to be deleted, put the deleted key into the memory queue or message queue and retry asynchronously

Divergent thinking

After updating the database, why don’t we just update it instead of deleting the cache?

This is because if the cache is updated directly, it is difficult to guarantee that the cache will be updated after the request to update the database in a high concurrency scenario. If the cache is deleted, the database can be read next time and the cache can be updated to ensure consistency.

Scenario 3. Business items update the database, and other items subscribe to binlog updates

2. The Cannal project reads the binlog of the database, parses it and sends a message to Kafka.

After receiving the message from Kafka about updating the database operation, update the cache. If the update cache fails, create an asynchronous thread to retry or send the operation to the message queue for subsequent processing.

Conclusion:

However, in this scheme, the old value is still in the cache after updating the database. The cache must be updated after updating the item consumption message, and the latest value is in the cache. Therefore, there is a delay between the completion of the update operation and the effect of the update.

The last

We understand other technical solutions, welcome to join the group to discuss!

What is the delayed double deletion policy?

The delayed double deletion policy is to delete the cache first, update the database, and then delete the cache after a short period of asynchronous synchronization (depending on the primary/secondary synchronization time of MySQL).

It takes a while for the slave database to receive updates after the master database is updated.

If a write request is made to update the primary database and the cache is deleted immediately for the second time, the MySQL database does not receive the update from the primary database and the data is still old, then the read request is directly read from the primary database. The data set to the cache is old data, which causes data inconsistency. Therefore, this is the original intention of the delayed dual-delete policy.

Reference links:

www.cnblogs.com/-wenli/p/11…

www.cnblogs.com/rjzheng/p/9…

Dry Goods content review:

How to ensure the consistency between cache and database in high concurrency scenario?

How do you clean expired keys?

How does MySQL solve the illusion problem?

How to execute a MySQL update statement?

What is your understanding of MySQL locks?

What is your understanding of Redis persistence?

What do you think of synchronized locks?

Talk about your understanding of HashMap.