缓存与数据库双存储,会涉及到双写,只要是双写就一定会有数据一致性的问题,那么你如何解决一致性问题?
1.读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
可能的问题:
大量请求同时过来,都穿过了缓存,去读数据库;
-----------------解决方案:加锁,如redis的互斥锁,所有请求先去获取锁,如果获取锁成功,首先判断是否有缓存,如果没有缓存才去数据库中读取数据并放入缓存中并释放锁,如果有缓存则读取缓存释放锁;如果获取锁失败,重新读取缓存;重复以上过程几次。
2.更新的时候,先更新数据库,然后再删除缓存(不是修改缓存,而是删除缓存,这个涉及到缓存到底会不会被频繁访问到?这是一个 lazy 计算的思想)。
可能的问题:
1.如果删除缓存失败了,则读取的是旧数据;
-----------------解决方案:先删除缓存,再修改数据库。
2.修改数据库还未完成的时候,一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后数据变更的程序完成了数据库的修改,这样就产生了数据不一致问题。
--------------解决方案:将数据库修改和查询数据库并更新缓存放入同一个队列,这个队列串行执行,这样就有了先后顺序,这个方案增加了异步消费和复杂度,同时需要考虑读请求的可用性,在一定时间内如果无法获取则返回旧数据或者进行降级。