如何保证缓存(Redis)与数据库(MySQL)的一致性
2023-12-15 21:58:14 9 举报
AI智能生成
如何保证缓存(Redis)与数据库(MySQL)的一致性
作者其他创作
大纲/内容
说明
对于热点数据(经常被查询,但不经常被修改的数据),我们可以将其放入redis缓存中,以增加查询效率,但需要保证从redis中读取的数据与数据库中存储的数据最终是一致的。
前言
客户端对数据库中的数据主要有两类操作
读(SELECT)
Cache Hit
直接从缓存返回数据
Cache Miss
从数据库将数据读入缓存
写(DML)
执行顺序:先更新缓存还是先更新数据库?
更新缓存策略:当缓存中的内容变化时,是选择修改缓存(Update),还是直接淘汰缓存(Delete)?
正文
淘汰Cache还是更新Cache?
淘汰Cache
优点:操作简单,无论更新操作是否复杂,直接将缓存中的旧值淘汰
缺点:淘汰Cache后,下一次查询无法在Cache中查到,会有一次Cache Miss,这时需要重新读取数据库
更新Cache
优点:命中率高,直接更新缓存,不会有Cache Miss的情况
缺点:更新Cache消耗较大
执行顺序问题:先淘汰缓存还是先更新数据库?数据库是单节点
情景一:更新数据库与淘汰缓存需要先后执行,如果在执行过程中后一步执行失败,哪种方案对业务的影响最小?
先淘汰缓存,再更新数据库
第一步淘汰缓存成功
第二步更新数据库失败
第二步更新数据库失败
再次查询缓存,最多会有一次Cache Miss
先更新数据库,再淘汰缓存
第一步更新数据库成功
第二步淘汰缓存失败
第二步淘汰缓存失败
数据库中是新数据,缓存中是旧数据,即数据不一致
情景二:假设没有操作会执行失败,但执行前一个操作后无法立即完成下一个操作,在并发较大的情况下,可能会导致数据不一致。此时,哪种方案对业务的影响最小?
先淘汰缓存,再更新数据库
正常情况
A线程进行写操作,先淘汰缓存,再更新数据库
B线程进行读操作,发现缓存中没有想要的数据,从数据库中读取更新后的新数据
并发量较大的情况
A线程进行写操作,先成功淘汰缓存,但由于网络或其它原因,还未更新数据库或正在更新
B线程进行读操作,发现缓存中没有想要的数据,从数据库中读取数据,
但此时A线程还未完成更新操作,所以读取到的是旧数据,并且B线程将旧数据放入缓存。
但此时A线程还未完成更新操作,所以读取到的是旧数据,并且B线程将旧数据放入缓存。
此时是没有问题的,因为数据库中的数据还未完成更新,
所以数据库与缓存此时存储的都是旧值,数据没有不一致
所以数据库与缓存此时存储的都是旧值,数据没有不一致
在B线程将旧数据读入缓存后,A线程终于将数据更新完成
此时是有问题的,数据库中是更新后的新数据,缓存中是更新前的旧数据,数据不一致。
如果在缓存中没有对该值设置过期时间,旧数据将一直保存在缓存中,数据将一直不一致,直到之后再次对该值进行修改时才会在缓存中淘汰该值
如果在缓存中没有对该值设置过期时间,旧数据将一直保存在缓存中,数据将一直不一致,直到之后再次对该值进行修改时才会在缓存中淘汰该值
并发量较大的情况下,采用异步更新缓存的策略
A线程进行写操作,先成功淘汰缓存,但由于网络或其它原因,还未更新数据库或正在更新
B线程进行读操作,发现缓存中没有想要的数据,从数据库中读取数据,
但B线程只是从数据库中读取想要的数据,并不将这个数据放入缓存中,所以并不会导致缓存与数据库的不一致
但B线程只是从数据库中读取想要的数据,并不将这个数据放入缓存中,所以并不会导致缓存与数据库的不一致
A线程更新数据库后,通过订阅binlog来异步更新缓存
先更新数据库,再淘汰缓存
正常情况
A线程进行写操作,更新数据库,淘汰缓存
B线程进行读操作,从数据库中读取新的数据
并发较大的情况
情形1
A线程进行写操作,更新数据库,还未淘汰缓存
B线程从缓存中可以读取到旧数据,此时数据不一致
A线程完成淘汰缓存操作
其它线程进行读操作,从数据库中读入最新数据,此时数据一致
情形2
A线程进行写操作,更新数据库,但更新较慢,缓存也未淘汰
B线程进行读操作,读取了缓存中的旧数据
情形3
A线程进行读操作,缓存中没有相应的数据,将从数据库中读数据到缓存
B线程执行写操作,更新数据库,淘汰缓存
B线程写操作完成后,A线程才将数据库的数据读入缓存
结语
单节点下两种方案对比
先淘汰Cache,再更新数据库
采用同步更新缓存的策略,可能会导致数据长时间不一致,
如果用延迟双删来优化,还需要考虑究竟需要延时多长时间的问题——读的效率较高,但数据的一致性需要靠其它手段来保证
如果用延迟双删来优化,还需要考虑究竟需要延时多长时间的问题——读的效率较高,但数据的一致性需要靠其它手段来保证
采用异步更新缓存的策略,不会导致数据不一致
但在数据库更新完成之前,都需要到数据库层面去读取数据,读的效率不太好——保证了数据的一致性,适用于对一致性要求高的业务
但在数据库更新完成之前,都需要到数据库层面去读取数据,读的效率不太好——保证了数据的一致性,适用于对一致性要求高的业务
先更新数据库,再淘汰Cache
无论是同步/异步更新缓存,都不会导致数据的最终不一致,在更新数据库期间,Cache中的旧数据会被读取,可能会有一段时间的数据不一致,但读的效率很好——保证了数据读取的效率,如果业务对一致性要求不是很高,这种方案最合适
0 条评论
下一页