文章首发于:clawhub.club


最近在做自己的项目《旅行记账》app的时候,正好使用到缓存,碰巧的很,也在一个群里,有人在讨论这个数据库、缓存双写一致性方案,就查了查资料,结果就采用了用的比较多的Cache-Aside-pattern方案。

  • 失效
    应用程序先从cache中取数据,没有得到(数据带失效时间),则从数据库中取数据,成功后,放入缓存。
  • 命中
    应用程序从cache中取数据,取到数据后返回。
  • 更新
    先将数据更新到数据库中,成功后,再将缓存数据清除。

这个套路有个问题:在并发操作的时候,假设缓存刚刚失效。有个线程A,从库中获取到旧的值,并刷缓存;线程B更新值,并清除缓存。这种情况,肯定会出现脏读。

但是数据库的读操作比写操作快的多,即A线程大多数情况下比B线程先操作结束,即先程序写缓存在大多数情况下肯定是优先于B线程删除缓存,最终,缓存中没有数据,其他线程缓存脏读的几率很小。

还有个问题:更新操作,删除缓存那一步失败了,怎么处理,肯定不能等着下一波更新或者缓存超时,应该引入重试机制:如果缓存删除失败,将key放入队列,由专门的线程处理重试。