目录
一、问题描述
在读取缓存时,都是先从缓存中读取。缓存有直接返回,缓存无则从数据中读取更新值缓存。
如果要更新数据库和缓存时,那么先更新数据库还是先更新缓存?
二、方案讨论
1、先删除缓存,然后更新数据库
假设有两个请求线程1和线程2
(1)线程1 先清除缓存,还没来得及更新数据库
(2)线程2 读 redis,发现没数据,读数据的内容,然后更新缓存
(3)线程1 更新数据库的内容
这种情况下,就会缓存中的数据是老数据,而数据库的数据是新数据。会产生数据不一致的问题
2、先更新数据库,然后删除缓存
有两个请求线程1和线程2
(1)线程1 先更新数据库
(2)线程2 读 redis,发现有数据,直接返回
(3)线程1 删除缓存
这种情况下,只有当前线程读取的数据是老数据。接下里来的其他读请求都会读到新数据。不会像方案1中的所有接下里的线程读到的都是老数据。
但是这种情况下,仍然会有问题。见下图
此时缓存中时老数据,数据库中是新数据。但是这种情况出现的概率极小。
因为实际上数据库的写操作会比读操作慢得多,而且还要锁表,读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存,所有的这些条件都具备的概率基本并不大。但是如果对一致性要求高,就不可行了
3、更新数据库,删除缓存,缓存设置过期时间
这个方法在2的基础上加了过期时间。更降低了脏数据出现的机率。即使出现脏数据了,到过期时间后,就会被删除。
4、先数据库,然后更新缓存
这种方式的问题如下
5、先更新缓存,然后更新数据库
6、更新数据库,并使用定时任务更新缓存
7、强一致性、分布式锁。
如果要求强一致性,就需要将数据库的更新和redis的更新当成一个串行操作。这种情况下,如果性能低的化,那还不如不用缓存
如还有其他意见,欢迎交流