乐趣区

关于redis:聊聊如何利用redis实现多级缓存同步

前言

前阵子加入业务部门的技术计划评审,故事的背景是这样:业务部门上线一个专为公司高管应用的零碎。这个零碎技术架构形如下图

按理来说这个零碎因为受众很小,能够说基本上没并发,业务也没很简单,但就是这么一个零碎,间断 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

退出移动版