How to use redis to achieve multi-level cache synchronization
foreword
A while ago, I participated in the technical plan review of the business department. The background of the story is this: the business department launched a system specially used by the company's executives. The technical architecture of this system is as follows
Logically speaking, this system has a small audience, so it can be said that there is basically no concurrency, and the business is not very complicated, but it is such a system, and the database crashed twice in a row, which caused the system to fail to operate normally. Because of these accidents, the person in charge of the business department organized this technical solution review. How can the subject avoid similar failures from happening again?
At that time, there was a relatively senior technology. He suggested that when the database crashes, you can switch to redis, which caches hot data. Another technology said that he agreed with this solution, but he proposed that you don’t need to use redis, and use the local cache directly. That's it. Because tomcat is deployed in a cluster, it means that the local cache also has cluster capabilities. And if you switch to redis, redis may also hang.
Then the one who said to use redis technology also said that with local cache, if the data changes, how do the local caches of other clusters perceive that the data has changed? He thinks it is still reliable to use redis. First of all, the capacity of redis must be higher than that of local cache, and redis Clusters can also be deployed, and availability can be guaranteed. Redis is used for centralized storage. When data changes, other clusters can also perceive it.
When they were arguing endlessly, some people suggested that they should be used at the same time. When the database is down, switch to redis, and if redis is down, use local cache. This plan has been agreed by many people, including these two controversial technologies. But using this scheme, you have to consider how the multi-level cache data is synchronized.
After so much preparation, I just want to talk about today's topic, how to synchronize multi-level cache data
Multi-level cache data synchronization
1. Solution 1: Use MQ or canal for synchronization
The scheme is as shown in the figure below
If MQ is used for synchronization, the implementation plan is roughly as follows. When the data changes, the business system sends the changed data to MQ, and other systems consume from MQ.
If you use canal, the implementation plan is roughly as follows. When the data changes, canal will receive the changed binlog. The business system writes the canal tcp client, and interacts with canal to obtain the changed data
2. Solution 2: Use the client caching mechanism provided by redis6
The scheme is as shown in the figure below
The principle of redis6 client-side caching implementation mechanism is officially introduced in detailed documents. If you are interested, you can check the following link
https://redis.io/docs/manual/client-side-caching/
Here's how to use it
How to use redis6 client cache
Precondition : The redis server version must be >=6. Lettuce version >=6 At present, the redis client of java has been searched, and it seems that only lettuce 6 supports it, and other clients are expected to support it later
1. The pom in the project introduces lettuce GAV
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.1.8.RELEASE</version>
</dependency>
2. Use the ClientSideCaching provided by lettuce6 to implement
/**
* Client cache synchronization
*
*/
public String getClientCacheValue(Map<String,String> clientCache,String key){
StatefulRedisConnection<String, String> connect = redisClient. connect();
// Map<String,String> clientCache = new ConcurrentHashMap<>();
CacheFrontend<String,String> frontend = ClientSideCaching.enable(CacheAccessor.forMap(clientCache),
connect, TrackingArgs. Builder. enabled(). noloop());
return frontend. get(key);
}
3. Test
@Override
public void run(ApplicationArguments args) throws Exception {
while(true){
System.out.println(lettuceRedisTemplate.getClientCacheValue("zhangsan"));
TimeUnit.SECONDS.sleep(1);
}
}
When the zhangsan data in redis has not changed,
The data output by the console is
We changed the password of redis zhangsan to 9999,
See if the local cache can capture it immediately
The console found that the password has been changed to 9999
Summarize
From the example, we can see that redis6 provides a good implementation of multi-level cache synchronization.
Let's talk about the follow-up of the technical review. The business department later did not use redis as a backstop when mysql was down, nor did it use local caching, let alone a combination of the two.
I don’t know if you have such an experience when you are in a meeting. Sometimes we are chatting about something, and then we diverge after chatting, losing our direction. Does the business department need a solution for database downtime? It looks like, in fact, their more core need is not to downtime the business system.
Occam's Razor: Don't multiply entities unnecessarily. In fact, regardless of adding redis or local cache, additional system maintenance costs will be increased. Because the system itself is not complicated, adding a cache requires additional consideration of cache data consistency, etc.
The subsequent processing method of the business department is to switch the mysql built by itself to the mysql of the cloud vendor. The advantage of this is that the mysql of cloud vendors will be more stable. Secondly, when problems arise, you can find cloud vendors to solve them. After all, cloud vendors have relatively strong operation and maintenance capabilities, and you can spend money to buy peace of mind
This accident will make the business department attach great importance to it, mainly because the user is an executive. If it is a general user, just hang it up. At worst, restart it. The users are different, and the emergency handling methods are different.
demo link
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-localcache-redis-sync
0 Comments