背景:
为了保证数据库和缓存的一致性,我们在更新数据库的同时更新缓存,但会产生以下问题
选择更新缓存还是删除缓存?
更新缓存
假设我们每次更新数据库,都会在缓存中更新数据,那么如果我们对数据库写了100次,那么我们对缓存也会写100次,如果期间没有用户访问,那么就产生了对缓存的很多次无效写
以上会变成:数据库写->缓存写->数据库写->缓存写->(重复)->用户查询
删除缓存
如果我们把更新缓存变成删除缓存会发生什么?首先对数据库写100次,每一次都会删除缓存,只有等用户下一次访问的时候,才会向缓存中更新数据,这就避免了无效写
以上会变成:删除缓存->数据库写->删除缓存->数据库写->(重复)->用户查询->更新缓存
为了减少无效写的次数,我们选择删除缓存,但是我们是先操作数据库,删除缓存呢还是先删除缓存再操作数据库呢?
通过分析下面两个《双写》问题,可以得到答案(图片来自B站heima程序员)
- 先删除缓存,再操作数据库的问题:线程一删除缓存之后,此时线程二前来查询,发现缓存未命中,接着去数据库中找,结果会把数据库中的数据写入缓存,接着线程一更新数据库之后,用户下次读,读到的就是线程二写入缓存中的旧数据(因为查询首先找缓存)
- 先操作数据库,再删除缓存的问题:线程一来查询,发现缓存未命中,结果去数据库查到了数据,但还没来得及写,此时线程二来更新数据库,接着删除缓存,线程一接着再把自己查出的数据写入缓存;当用户下次读的时候,读的也是旧数据
总结
以上两种方案都会有问题,但哪个出现的概率会高一点呢?
那就要比较是写数据库快,还是写缓存快?当然是写缓存快
在左边的例子中,我们删除完缓存向数据库写,这个时间相对较长,那么线程二的行为很容易发生
而在右边的例子中,我们向缓存中写的时间相对短,并且线程二中还要先操作数据库,这个时间长所以线程二出现的概率就更低
所以我们选择先操作数据库,再操作缓存