跳转至

Redis-缓存更新的几种模式

Cache Aside:旁路缓存

13705-n4h28bgek4f.png

1. 先更新Mysql数据库,再更新Redis缓存:

  • 这种做法最大的问题就是两个并发的写操作导致脏数据:
  • 如果用户1更新完Mysql数据库内容之后就在准备更新Redis缓存中的数据的时候网络延迟卡住了,ps:Redis数据库在另一台服务器上
  • 这时候,用户2在用户1更新完Mysql数据库的准备更新Redis数据的时候,突然强势插入修改了同样的一条数据,并且不卡顺便更新了Redis数据库中的数据
  • 过了零点xx秒后,用户1更新Redis数据库的命令也到了,那么这时Redis数据库中就又被修改成了用户1的更新的数据
  • 但是这会有一个问题,数据库保存的是最新的数据用户2修改的数据,但是Redis数据库中保存的是用户1的数据 80577-ylkmfjmjlj.png

2. 先删除缓存,再更新数据库:

  • 这种方式也会脏数据:
  • 如果用户1再更新之前先删除Redis中的缓存,删除Redis中的缓存之后就在准备更新Mysql数据库之际卡了
  • 这是突然杀入一个用户2的访问数据(读取操作),由于用户1数据删除了这条数据,所以用户2并没有命中Redis数据库中的缓存信息,所以用户2转而访问Mysql找到响应的数据之后回填到Redis数据库中
  • 这时候Redis数据库中保存的是用户2回填的数据,但是这时候用户1刚更新完毕Mysql
  • 就导致了数据库中是用户1的数据,但是Redis中是用户2回填的数据 93725-gtv1zm23qbb.png

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

  • 这种方式出现错误的情况很小但是也会是有的
  • 用户1是个查询操作在Redis中没有命中缓存进而向Mysql中取数据,取出数据就在准备回填到Redis数据库中的时候卡了.....卡了......
  • 用户2这时是一个更新操作对这条数据,更新完了之后一步到位顺便删除了Redis中的缓存信息任务就处理完毕了
  • 但是这时候用户1才反应过来把自己在Redis中没查到在Mysql查到的数据回填到了Redis中,
  • 这时就出问题了,用户1回填的是用户1查询到的数据, 但是数据库中的数据在用户1准备回填的时候已经被修改了,这时候Redis中保存的是旧的用户1查询时的数据,Mysql中保存的却是用户2更新后的数据 75655-ml15nlxu6gq.png
  • 这种并发出错的概率太低了,必须要满足读缓存时无法命中,并且这时又来一个并发操作,实际上数据库读比写快得多,而且还有锁,而读操作必须在写操作之前进入到数据库操作,而且又要晚于写操作更新缓存,这些条件很难同时达成,但是为了保险,我们应该还是需要为缓存设置过期时间

Write-through:通写

  • 具体读写操作交给缓存层完成, 立即更新数据库 22210-g7rihpippp.png

Write-behind caching:写入缓存

  • 具体读写操作交给应用完成, 定时异步更新数据库 17235-g4o7qbpyq9f.png