Redis缓存一致性问题
使用缓存来保存热点数据是解决高并发的常用手段之一,通过使用缓存,大大减轻了DB的压力,同时减少了请求响应时间,但是引入缓存之后,随之而来的问题就是当DB数据更新时,缓存中的数据就会与DB数据不一致,这时候就需要对缓存的数据进行更新或者淘汰。当数据库有写入请求时,缓存是应该更新呢还是删除呢?双写的情况下,先操作数据库还是先操作缓存?
下面介绍四种不同的操作顺序和操作方式对缓存一致性的影响。
🚨 更新缓存 Or
删除缓存,如何选择?
更新缓存相对于删除缓存,有两点劣势:
-
如果写入的缓存值,是经过复杂计算才得到的话。 更新缓存频率高的话,就浪费性能。
-
在写多读少的情况下,数据很多时候还没被读取到,又被更新了,这就浪费了性能(实际上,写多读少的场景,也不建议使用缓存)
- 但并不是删除缓存就是最好的选择,在读多写少的场景下,更新缓存相比于删除缓存会更好些。
一、先更新数据库,再更新缓存
这种策略会导致线程安全问题。例如,线程1更新了数据库,线程2也更新数据库,这时候由于某种原因,线程2首先更新了缓存,线程1后续更新。 这样就会导致了缓存脏数据的问题,因为目前数据库中存储的是线程2更新后的数据,而缓存存储的是线程1更新的旧数据。
二、先更新缓存,再更新数据库
使用先更新缓存再更新数据库的策略,在非并发情况下当更新缓存后,如果更新数据库失败,就会导致缓存了脏数据,这种情况下可以通过补偿或者重试机制来解决。而在并发情况下,例如线程1和线程2更新缓存,线程1将缓存的值更新为100、线程2将缓存的值更新为200,此时两个线程还未进行数据库的更新,而此时线程1因为网络延迟等问题更新数据的操作比线程2慢了,所以线程2先完成数据库更新将值修改为200,之后线程1继续进行数据库的更新,将值修改为100,此时就出现了不一致情况,数据库中存储的值的是100,而缓存存储的是200。
😋三、先删除缓存,再更新数据库
该策略可能导致数据不一致的问题。例如,线程1更新数据前先删除缓存,这时候线程2查询该缓存,发现不存在,则去DB中获取,得到旧值放入缓存,然后线程1更新数据库。这时候就出现了缓存与数据库不一致的问题。
👨🚀 解决方案:延时双删
,指在更新完数据库后休眠,待其他线程从DB读完数据并写入缓存后再删除一次缓存。(休眠时间需要大于从DB读取数据并更新完缓存的时间之和
),最后的一次删除缓存操作,可以将其他线程的读操作所造成的旧缓存给删除掉,从而达到避免数据不一致的情况。
四、先更新数据库,再删除缓存
该策略可能会造成比较短暂的数据不一致。在更新完成数据库后,删除缓存前,如果有此时有其他线程访问缓存, 就会造成数据不一致的情形。 例如线程1更新数据库后删除缓存前,线程2访问了缓存,而此时的缓存是旧的,这就造成了缓存不一致的情况,但是这个不一致只是短暂的,当线程1删除缓存完成后,其他线程就会从数据库获取最新值并更新到缓存中。
🏁以上就是对Redis缓存一致性问题的简单介绍,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍