参考文章 https://blog.csdn.net/simba_1986/article/details/77823309
缓存与数据库的一致性
缓存适用于读多写少的场景,并且能极大地提升性能和效率;但是让缓存的数据与数据库保持一致是一个难题
保持一致的策略
- 当数据更新时,先更新缓存,如果缓存更新成功,再更新数据库
- 适用场景有限,且实现起来较为复杂(如果数据库操作失败,要进行补偿措施,对缓存数据进行还原)
- 当数据更新时,先删除缓存,如果缓存删除成功,再更新数据库
- 适用所有的场景,且实现起来简单,是最常用的
存在的问题
不考虑策略1,以下将深入探究策略2
在高并发的情况下,假设请求1(更新操作)先删除缓存,再更新数据库,如果请求2(读操作)在缓存删除与数据库更新之间进行了读取数据,就会读入旧数据到缓存,待数据库更新后,此时旧数据缓存与数据库发生不一致的现象
该问题的核心是,请求1的操作不能被其他请求打断,并且请求1与其他请求之间要保持有序(串行执行)。遇到这种情况,可以采用队列的方式去解决(为了保证串行执行,工作线程只能有1个),当出现更新请求时,直接将其丢进队列,等待异步执行;当出现读请求时,先读缓存,成功则返回,如果缓存不存在,再去判断队列头部是否是同一条记录的更新请求,如果是,为了不打断其操作,将读请求也丢进队列,然后同步等待缓存更新完成;如果不是,说明该更新请求早已完成,直接读数据库并缓存即可,不要入队列。
优化
- 队列可以创建多个,运用Hash法将不同记录的请求散列到不同的队列,可以负载均衡,并行执行,也可以避免堵塞
- 在分布式场景下,队列最好共享
- 进入队列的读请求可以采用超时等待,一旦超时,直接读数据库并返回,避免长时间的不响应