Redis之缓存双写

目录

Redis之缓存双写

一、双检加锁策略

二、更新策略

1、先更新数据库,再更新缓存

2、先更新缓存,再更新数据库

3、先删除缓存,再更新数据库

4、先更新数据库,再删除缓存

三:canal消息中间件

1、mysql配置

2、canal服务端

3、canal客户端


Redis之缓存双写

同步写策略:写数据库后也同步写redis缓存,缓存和数据库中的数据一致;

异步写策略:数据库变动之后,在业务上容许出现一定时间后才作用于redis,比如仓库、物流系统。

一、双检加锁策略

多个线程同时去查询数据库的这条数据,可以在第一个查询数据的请求上使用一个互斥锁来锁住

它。其他的线程走到这一步拿不到锁就开始等待,等第一个线程查询到了数据,然后做缓存。后面

的线程进来发现已经有缓存了,就直接走缓存。

public User fandUserById(Integer id){
        User user = null;
        String key = CACHE_KEY_UESR + id;
        //先从redis里面查询,如果有直接返回结果,如果没有再去查询mysql
        user = (User)redisTemplate.opsForValue().get(key);
        if (user == null){
            //进来就先加锁,保证一个请求操作,让外面的redis等待一下,避免击穿mysql
            synchronized (UserService.class){
                //3二次查redis还是null,可以去查mysql了(mysql默认有数据)
                user = (User)redisTemplate.opsForValue().get(key);
                if (user == null){
                    //4查询mysql拿数据
                    user = userMapper.selectUserById(key);
                    if (user == null){
                        return null;
                    }else {
                        //mysql里面有数据的,需要回写redis,完成数据一致性的同步工作
                        redisTemplate.opsForValue().setIfAbsent(key,user,7L, TimeUnit.DAYS);
                    }
                }
            }
        }
        return user;
    }

二、更新策略

1、先更新数据库,再更新缓存

问题1、mysql更新成功,redis更新失败

问题2、多线程环境下,A、B两个线程有快有慢,有前有后有并行,A先更新数据库,然后B更新数据库,B更新redis,最后A在更新redis,最终结果,mysql和redis数据不一致。

2、先更新缓存,再更新数据库

不推荐,业务上一般把mysql作为底单数据库,保证最后解释

问题:多线程环境下,A、B两个线程有快有慢,有前有后有并行,A先更新redis,然后B更新redis,B更新数据库,最后A在更新数据库,最终结果,mysql和redis数据不一致。

3、先删除缓存,再更新数据库

问题:多线程环境下,A、B两个线程有快有慢,有前有后有并行,A先删除缓存,然后A更新数据库但由于网络延迟A还没有更新完数据库,B查数据发现缓存中没有,然后去数据库查找,并将结果返回给redis,最后A更新数据库完成,结果数据库是最新数据,redis还是老数据,导致数据不一致。

解决方法:延时双删策略

在先删除缓存,在更新数据库,更新完数据库之后在删除缓存。

4、先更新数据库,再删除缓存

问题:假如缓存删除失败或者来不及删除,导致请求再次访问redis时缓存命中,读取到的是缓存旧值。

如何保证数据的最终一致性?使用消息中间件

(1)更新数据库数据

(2)数据库会将操作信息写入binlog日志当中

(3)订阅程序提取出所需要的数据以及key

(4)  另起一段非业务代码,获得该信息

(5)尝试删除缓存操作,发现删除失败

(6)将这些信息发送至消息队列

(7)重新从消息队列中获得该数据,重试操作。

问:如果数据库有增删改操作,立刻同步到redis怎么做

使用阿里巴巴的canal消息中间件。

三:canal消息中间件

canal地址:https://github.com/alibaba/canal?tab=readme-ov-file

canal:译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅

和消费。

基于日志增量订阅和消费的业务包括

  • 数据库镜像
  • 数据库实时备份
  • 索引构建和实时维护(拆分异构索引、倒排索引等)
  • 业务 cache 刷新
  • 带业务逻辑的增量数据处理

canal 工作原理

  • canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
  • MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
  • canal 解析 binary log 对象(原始为 byte 流)

canal 使用方法

准备好mysql和redis数据库

1、mysql配置

1、查看版本

select version();

2、查看MySQL是否启用了二

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值