前言
前阵子加入业务部门的技术计划评审,故事的背景是这样:业务部门上线一个专为公司高管应用的零碎。这个零碎技术架构形如下图
按理来说这个零碎因为受众很小,能够说基本上没并发,业务也没很简单,但就是这么一个零碎,间断 2 次呈现数据库宕机,而导致系统无奈失常运行。因为这几次事变,业务部门负责人组织这次技术计划评审,主题如何防止再次出现相似这种故障?
过后有个比拟资深的技术,他提出当数据库呈现宕机时,能够切换到 redis,redis 外面缓存热点数据,另外一个技术说他同意这个计划,但他提出不须要用到 redis,间接用本地缓存即可。因为 tomcat 是集群部署,就等于本地缓存也具备了集群能力。而如果切换成 redis,redis 也可能会挂景象。
而后那个说用 redis 的技术又说,用本地缓存,如果数据变更,其余集群的本地缓存如何感知数据曾经发生变化,他感觉还是用 redis 靠谱,首先 redis 容量必定是比本地缓存高,而且 redis 也能够部署集群,可用性能够失去保障,利用 redis 集中存储,当数据产生变更,其余集群也能够感知到。
在他们争论不休的状况下,有人提出不然就同时应用,当数据库挂了,切换到 redis,redis 挂了,应用本地缓存。这个计划失去不少人的批准,包含这两个争论不休的技术。但应用这种计划,就得思考多级缓存数据如何同步。
铺垫了那么多,才刚要说明天的主题,多级缓存数据如何进行同步
多级缓存数据同步
1、计划一:应用 MQ 或者 canal 进行同步
计划如下图
如果是应用 MQ 来同步,实现计划大抵如下,数据产生变更,业务零碎发送变更数据到 MQ,其余零碎从 MQ 生产。
如果是应用 canal,实现计划大抵如下,数据产生变更,canal 会接到到变更的 binlog,业务零碎编写 canal tcp 客户端,和 canal 进行交互获取变更数据
2、计划二:利用 redis6 提供的客户端缓存机制
计划如下图
redis6 客户端缓存实现机制原理,官网有具体文档介绍,感兴趣大家能够查看如下链接
https://redis.io/docs/manual/client-side-caching/
这边就讲下如何应用
如何应用 redis6 客户端缓存
前置条件 :redis 服务端版本必须是 >=6。lettuce 版本 >=6 目前 java 的 redis 客户端找了一圈,貌似只有 lettuce 6 反对,其余客户端预计前期会反对
1、我的项目中 pom 引入 lettuce GAV
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.1.8.RELEASE</version>
</dependency>
2、利用 lettuce6 提供的 ClientSideCaching 进行实现
/**
* 客户端缓存同步
*
*/
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、测试
@Override
public void run(ApplicationArguments args) throws Exception {while(true){System.out.println(lettuceRedisTemplate.getClientCacheValue("zhangsan"));
TimeUnit.SECONDS.sleep(1);
}
}
redis 外面的 zhangsan 数据未产生变更时,
控制台输入的数据为
咱们将 redis zhangsan 的明码改成 9999,
看本地缓存是否立马捕捉到
控制台发现明码曾经改成 9999
总结
由示例咱们能够看出 redis6 提供了一个很好的多级缓存同步的实现计划。
咱们再聊下那个技术评审的后续,前面业务部门并没有采纳当 mysql 宕机,应用 redis 作为兜底,也没采纳本地缓存,更没采纳两者联合的计划。
不晓得大家散会的时候,有没有这样的领会,有时候咱们在聊一个货色,前面聊着聊着就发散进来,把方向搞丢了。业务部门他们须要数据库宕机的解决方案吗,看着像是,其实他们更外围的须要,是业务零碎不宕机。
奥卡姆剃刀定律:如无必要,勿增实体。其实不论加 redis 或者本地缓存,额定都减少系统维护老本。因为零碎自身不简单,加了缓存,就要额定思考缓存数据一致性等
前面业务部门的解决形式,是将本人搭建的 mysql,切换成云厂商的 mysql。这样的益处是,云厂商的 mysql 会更稳固,其次当呈现问题,能够找云厂商进行解决,毕竟云厂商的运维能力是比拟强的,花钱买心安
这次事变会让业务部门那么器重,次要是应用方是高管,如果是个别使用者,挂就挂吧,大不了重启,应用对象不一样,应急解决形式就不一样
demo 链接
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-localcache-redis-sync