Several ways to synchronize MySQL data to Redis cache

1 Mysql checks the data, and then synchronously writes it to Redis

  1. Disadvantage 1: It will cause delays to the interface, because synchronous writing to redis itself has a delay, and retrying is required. If redis writing fails, retrying is required, which will take more time.

  1. Disadvantage 2: No decoupling, if redis crashes, the thread will be directly stuck

  1. Disadvantage 3: If the database is artificially created, it cannot be synchronized unless the corresponding Redis is artificially deleted, but there is also a time difference in the process of deleting Redis

2 After Mysql checks the data, send MQ to synchronize Redis in the consumer thread

  1. Disadvantage 1: There are more layers of MQ, that is, there will be a high probability of causing synchronization delay problems.

  1. Disadvantage 2: To prevent the availability of MQ

  1. Disadvantage 3: If the database is man-made, it cannot be synchronized

  1. Advantage 1: The problem of delayed return of the interface can be greatly reduced

  1. Advantage 2: MQ itself has a retry mechanism, no need to manually write retry code

  1. Advantage 3: Decoupling, completely separate query Mysql and synchronous Redis, without interfering with each other

3 Subscribe to the Binlog file of Mysql (can be done with the help of Canal)

  1. CanalServer will pretend to be a MysqlServer slave library to subscribe to the Binlog file of the MysqlServer main library

  1. When Canal starts, it will configure the corresponding message MQ (RabbitMQ, RocketMQ, Kafka). When it detects a change in the Binlog file, it will convert the changed sql statement into json format and send it to MQ as the message content

  1. In the project, as long as you monitor the corresponding MQ, you can get the content of the Binlog changes. There are clear operation types (CURD) and corresponding data in the Json data. Synchronize the corresponding data to redis

  1. Disadvantage 1: The entire operation process of canal subscribing to Binlog is single-threaded, so in the case of ultra-high concurrency, the performance may not be very good. Of course, multiple canals and multiple consumers can be deployed, but attention should be paid to the problem of repeated consumption of messages, and idempotence checks must be done

  1. Advantage 1: Even if the database is changed artificially, it will be monitored and synchronized

  1. Advantage 2: Asynchronous and synchronous, there will be no extra delay for interface return

4 Delayed double deletion

  1. Before executing the modified sql, delete the redis data first

  1. Execute update sql

  1. delay for a while

  1. Delete redis data again

// 延迟双删伪代码
deleteRedisCache(key);   // 删除redis缓存
updateMysqlSql(obj);        // 更新mysql
Thread.sleep(100);           // 延迟一段时间
deleteRedisCache(key);   // 再次删除该key的缓存

Disadvantages: The delay time is not easy to control, how long the delay is, it is difficult to evaluate

Extension: If you don't use delayed double delete, just delete the cache, and then change the mysql data. What's the problem with only these two steps?

5. Single request, single thread is no problem, but there will be problems under high concurrency and multi-threading

6. If the Thread1 thread wants to update the data, then the Thread1 thread cleans up the redis

7. At this time, Thread2 thread comes, but Thread1 has not finished updating mysql

8. Thread2 query redis must be null, at this time Thread2 will check mysql, and then write the found data to the cache

9. Since Thread1 has not had time to modify the mysql data, the data detected by Thread2 at this time is [old data], and Thread2 writes the old data into Redis again

10. At this time, the Thread3 thread comes, and if there is data found by querying Redis, it directly takes the cached data. At this time [Thread3 finds out the old data], it directly returns with the old data, and this is the problem.

11. The second deletion of delayed double delete is to prevent Thread2 from writing the old data again. With delayed double delete, Thread3 will still get null when querying Redis, and it will get the latest data from mysql

12. So the normal delay time should be the entire time from Thread2 checking the cache to getting the mysql data, and then saving it to redis, as the delay time of Thread1, but the time of this process of Thread2 will be affected by many factors, so it is difficult determine how long it will be

5 Delayed double write

// 延迟双写伪代码
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存

the aforementioned code defects;

  1. Under high concurrency, two threads execute the above code at the same time, and modify mysql, and the modified content is unreasonable, which may cause data inconsistency between Redis and Mysql

  1. After the T1 thread executes updateMysqlSql, the row lock is released. At this time, the T2 thread executes updateMysqlSql and addRedis, and finally T1 executes addRedis. This situation will cause the database to be changed to the data of the T2 thread, but Redis is the data of the T1 thread.

优化
// 完美延迟双写伪代码
开启事务
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存
提交事务

Correction of the above code:

  1. Put the two lines of code into one transaction, and T2 can start executing only when T1 finishes executing Mysql and Redis, which can ensure data consistency. It is recommended to use distributed locks

  1. Disadvantages of double writing: Mysql and Redis are single-threaded. Not good in terms of performance, so it is not recommended to use

6 Summary

It is recommended to use the Canal method for asynchronous synchronization. Followed by the MQ method

Guess you like

Origin blog.csdn.net/qq_37284798/article/details/129518953
Recommended