在实际操作redis的过程中,我们时常会遇到数据不一致的问题,下面我列举几个场景:
主要是针对并发操作下导致的一些线程不安全的问题
1、比如在删除操作的时候,先删除缓存,再删除数据库数据。但是删除数据库的操作还没有执行成功,这时如果存在并发的问题,当另一个线程读取该数据,发现缓存不存在,去数据库查询,查询后将结果缓存到redis中。这时另一个线程的删除数据库的操作执行完成,这是就存在数据库没有数据,缓存还保留着原有旧数据的不一致性问题。
2,还有在执行更新商品库存的操作的时候,商品库存现在是100,更新数据库为99,再更新缓存,但是这是数据库更新成功之后,redis没有更新成功,这时就出现数据库是99,redis中还是100,这种情况也是数据不一致性问题。(针对这种情况可以在更新之前先删除缓存,保存每次更新后的数据都是从数据库查出来的,保证数据一致性)
针对的解决方案:
1,针对第一种操作出现的问题可以使用延时双删策略。
即在删除完redis缓存后的过程中再执行一遍删除操作(不常用,不适用分布式系统)
2,还有一种通用的解决方案:异步更新缓存。(基于订阅binlog的同步机制)
通过rabbitmq中间去实现。需要用到阿里的技术组件canal。
cannal机制:
1、通过cannal模拟mysql slave交互协议,伪装自己为mysql slave,向mysql master 发送dump协议。
2、mysql master收到dump请求,开始推送binarylog给slave,也就是cannal
3、canal解析binarylog对象
4、canal将解析后的对象数据推送给监听的消息中间件
核心:通过消息队列的有序的处理来保证数据的一致性。
以上两种解决方案的优缺点:
使用消息中间件之后,问题更复杂了,难以保证消息不丢失。
就算通过更新数据和删除缓存都没有发生问题,消息的延迟也会带来短暂的不一致性,不过这个延迟相对是说是可以接受的,如果采用第二种方案则先更新数据库,再删除缓存。