redis和DB数据一致性解决方案

问题出现原因
  • 并发时候无法保证读写的先后顺序,如果删掉了缓存还没来得及写库,另外一个县城就多来读取,发现缓存为空就去读取数据库并且写入缓存,这时候缓存中就是脏数据
  • 如果先写库,在删除缓存前,写库的线程宕机,没有删除掉缓存,则也会出现不一致的情况
  • 如果redis集群,在注册模式中,写主库,读从库,也会出现redis复制存在的一些延迟操作,也可能导致数据不一致
解决方案
双删除+超时
  • 写库前后都加上redis.del(key)操作,并且舍得合了的超时时间,这样最差的情况就是在超时时间之内存在不太一致,当然这种情况极其少见,可能的原因就是服务器宕机,此种情况可以满足绝大多数需求
  • 这种策略要考虑redis的和数据库注册同步的耗时,所以第二次删除前最好先等待一段时间,等待同步完成,然后在删除,这样缺点也会增加线程占用时间。
通过读取binlog的方式,异步淘汰缓存

这里写图片描述

  • 好处在于业务上的侵入性低,将缓存和数据库的不一致时间尽量缩小。
  • binlog介绍:mysql的binlog日志作用在于记录mysql内部的增删改查等对mysql有更新操作的内容的记录,对数据的select已经show不会被binlog记录,主要用于数据库的主从复制,以及增量恢复。
  • binlog日志模式:
    • STATEMENT模式(SBR):每条修改数据库的sql都会记录到binlog中,有点事并不需要记录每条sql和每一行数据的变化,有点在于减少binlog日志,缺点是某些情况下master-slave数据不一致比如,sleep()函数,last_insert_id()
    • ROW模式(RBR):不记录每条sql的上下文信息,仅需要记录那条数据被修改了,修改成什么样,不会出现某些特定的情况下的存储过程或者function或者targger的调用和出发无法被复制的问题,但是会产生大量的日志
    • MIXED模式(MBR)以上两种模式的混合使用,一般复制使用STATEMENT模式保持binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,mysql会根据执行的sql语句选择日志保持方式
mysql的UDF
  • 这种方法思路是通过数据库中的Targger调用自定义的函数库来触发对redis的操作,但是这个有一定学习成本,需要基于mysql的APi进行开发使用的C++语言,阿里早期的解决方案
binlog具体实施方案
  • 通过使用open-replicator解析binlog
  • 使用canal进行同步—阿里框架
canal介绍(http://www.cnblogs.com/duanxz/p/5062833.html)
  • mysql主从负责工作原理

img

  • 负责分为三步
  1. master将改变记录到二进制日志binary log 中, 可以通过mysql命令 show binlog events查看
  2. slave将master的binary log events 拷贝到他的中继日志,用来中转数据
  3. slave重做中继日志中的事件,将改变反映他自己的数据
  • canal工作原理

img

  1. canal是模式mysql slave的交互协议,伪装ziji shi mysql slave,向master发送dump协议
  2. mysql master 收到dump请求,开始推送binary log给slave(这里的slave就是canal)
  3. canal解析binary log对象
canal官网

猜你喜欢

转载自blog.csdn.net/liaojiamin0102/article/details/93616498