Hello everyone, I’m glacier ~~

Recently, my friends have been asking me: after the introduction of cache in the system, when writing data to the database, should I write the database first or the cache first? What’s the difference between write-first database and write-first cache? Today, we are going to talk about this topic.

In essence, either write to the database or write to the cache first, the purpose is to ensure that the database and the cached data are consistent, which is often referred to as data consistency.

With the rapid development of the Internet, the current era has already entered the DT era from the IT era. The Internet system architecture has changed from the original single architecture to the distributed and micro-service architecture mode. From the perspective of data volume, the amount of data stored in each system is getting larger and larger, and the performance of data query is getting lower and lower. At this point, we need to continue to optimize, a commonly used optimization means is the introduction of cache. With the introduction of caching, do we update the database first or the cache first when we insert data into the database?

General use of caching

Caching, in essence, is an intermediate cache layer introduced to better coordinate two components that have vastly different speeds. For example, if you need to read data into the CPU for computation, the CPU’s computation speed is very fast, but the disk IO processing is many orders of magnitude slower than the CPU, each time the data is read from the disk, the CPU may be long and frequently waiting for the disk IO. At this point, we can use memory to smooth out the speed difference between CPU and disk.

In terms of the use of cache, it is generally followed the following process to use cache.



We can also represent it as the following sequence diagram.

In the above example, we simply put the data in the cache, and set an expiration time for the cache at most. After the expiration, the cache will be cleared, and subsequent requests will get the data from the database and write the data to the cache because they can’t get the data in the cache.

But in subsequent data updates, do you update the database and then update the cache or delete the cache? Or delete the cache first and then update the database?

Cache update policy

In theory, setting an expiration date for a cache is a sign of ultimate consistency. In this scheme, you can set the expiration time for the data stored in the cache, all write operations are subject to the database, and the cache operations just do their best. That is, if the database write succeeds and the cache update fails, then as soon as the expiration time is reached, subsequent read requests will naturally read the new value from the database and then backfill the cache. This is also the most commonly used way in general.

Update the database first and then the cache

In fact, many experienced partners are very opposed to this scheme. Why? Let’s analyze it.

First, there are thread-safety issues with this scenario.

For example, if both thread A and thread B perform an update operation on the data, the following order of execution might occur.

(1) Thread A has updated the database (2) Thread B has updated the database (3) Thread B has updated the cache (4) Thread A has updated the cache

At this time will appear inconsistent data in the database and cache the data, it is because the thread A first update the database, probably because the network anomalies, such as thread B to update the database and update the cache, when A thread B after updating the cache, thread A just update the cache, this leads to the database data isn’t consistent with the cached data.

Second, there are business scenarios where this approach does not apply.

First of all, a business scenario is a scenario in which the database writes more and reads less. In this scenario, the strategy of updating the database first and then updating the cache will lead to frequent updates before the cache is read, which greatly wastes the performance of the server.

Another business scenario is that the data in the database is not written directly to the cache, but requires a lot of complex operations to write the results of the operations to the cache. If the strategy of updating the database first and then updating the cache is used in this scenario, server resources will also be wasted.

Delete the cache before updating the database

The solution of deleting the cache before updating the database also has thread-safety issues. For example, thread A updates the cache while thread B reads the cached data. The following order of execution may occur.

(1) Thread A deletes the cache (2) Thread B queries the cache and finds that there is no desired data in the cache (3) Thread B queries the old data in the database (4) Thread B writes the old data to the cache (5) Thread A writes the new data to the database

At this point, there is a discrepancy between the data in the database and the data in the cache. If the cache deletion fails, there will also be inconsistencies between the database data and the cache data.

Update the database before deleting the cache

First of all, there is A very small chance that the database data and the cached data will be inconsistent. For example, thread A will perform the query and thread B will perform the update, in the following order.

(1) The cache just expired (2) Request A to query the database and get the old value in the database (3) Request B to write the new value into the database (4) Request B to delete the cache (5) Request A to write the old value found into the cache

If the above sequence occurs, it will result in inconsistencies between the data in the database and the data in the cache.

However, the strategy of updating the database first and then deleting the cache has a very low probability of inconsistencies between the database and the cached data because :(3) writes to the database in less time than reads to the database in step (2) so that step (4) may be executed before step (5). However, the read operation of the database tends to be much faster than the write operation, so step (3) takes less time than step (2), which is a difficult scenario.

If the cache deletion fails, there will also be inconsistencies between the database data and the cache data.

So, it seems that none of the three options is safe, so what can we do? Ultimately, you need to introduce a retry mechanism.

It is recommended to use

In a real production environment, it is recommended to update the database before deleting the cache. So, how do we solve the problem of this strategy?

There are two schemes, one is to deal with the operation of failed retry in the program logic; In addition, with the help of Alibaba’s open source Canal.

Manually failed and retried

The process is as follows: (1) Update the database data; (2) Failure to delete cached data (3) Send the key that needs to be deleted to the message queue (4) Construct the message by yourself, get the key that needs to be deleted (5) Continue to retry the deletion operation until success

One disadvantage of this approach is that it causes a lot of intrusion into line of business code.

Synchronize database data

Let’s start with a diagram that addresses the overall architectural inconsistency between database data and cached data.

The process is shown as follows: (1) update database data (2) the database writes the change information of data table data into the binlog log (3) the subscriber obtains the required data and (4) process the specific business logic in the program logic, receiving the request to subscribe to the binlog and initiate the request to delete the cache. (5) Try to delete the cache operation and find that the deletion failed (6) Send the information to the message queue (7) Get the data from the message queue again and retry the operation.

Well, that’s it for today, I’m Glacier, see you next time ~~