在高并发场景下,保证数据库和缓存一致性
更新缓存有4中方案
- 先更新数据库,然后更新缓存
- 先更新缓存,然后更新数据库
- 先更新数据库,然后删除缓存
- 先删除缓存,然后更新数据库
下面我们分别分四种情况的高并发情况下,四种方案可能出现的问题:
先更新数据库,然后更新缓存
进程一、进程二都模拟了一个先更新数据库,后更新缓存的场景。
1、如果进程二更新缓存发生在进程一更新缓存之前(即t3变成了t3`),此时缓存值是v1,数据库值为v2,发生了数据库和缓存不一致的情况。
2、先更新数据库后更新缓存还存在如果该缓存使用率不高,浪费缓存空间的情况。
先更新缓存,然后更新数据库
进程一、进程二分别模拟了一个先更新缓存,后更新数据库的场景。
1、如果进程二更新数据库发生在进程一更新数据库之前(即t3变成了t3`),此时缓存值为v2,数据库值为v1,出现了缓存与数据库不一致的情况。
2、先更新缓存后更新数据库也存在也存在如果key对应缓存使用率不高,浪费缓存空间的情况。
先更新数据库,然后删除缓存
进程一、进程三模拟更新数据库并删除缓存。
进程二模拟首次生成缓存值。
从上面的图可以看出,如果t3->t6时间段有更新数据库并删除缓存,则会出数据库中值为v2,但是缓存中值为v1的情况。这种概率几乎可以忽略不计,因为t3-> t6时间非常短,且更新数据库和删除缓存都必须都发生在这个时间才会导致上述情况。
但是,如果t1或者t5删除缓存失败,则会导致在缓存被删除或失效前读取到的都是旧值。所以这种方案需要确保删除缓存操作的可靠性很高。推荐的做法是,先删除一次,如果删除失败,再写入消息队列,使用消息队列的重试删除,直到删除成功为止。
先删除缓存,后更新数据库
进程一、进程三模拟删除缓存并更新数据库。
进程二模拟首次生成缓存值。
从上图可以看出,如果进程三在t5之前删除缓存,且在t5后更新数据库,则必然发生数据库中存的值与缓存中存的值不一致的情况。
进程一、进程三模拟删除缓存并更新数据库。
进程二模拟首次生成缓存值。
从上图可以看出,如果进程三在t4~t6之间还有写入数据库的操作,也必然发生数据库中存的值与缓存中存的值不一致的情况。