当前位置: 首页 > 科技观察

缓存和数据库不一致怎么办?

时间:2023-03-19 16:43:42 科技观察

缓存和数据库的操作时机,不管是《Cache Aside Pattern》中的方案还是《究竟先操作缓存,还是数据库?》中的方案,都会遇到缓存和数据库不一致的问题。今天就来聊聊这个问题。1.数据库主从不一致首先回顾一下,没有缓存的时候,数据库主从不一致的问题。如上图,出现的场景是先写后读:主库发出写请求(主从还没有同步),然后从库发出读请求,olddataisread***,主从同步完成的结果为:active在同步完成前会读取olddata。可以看出主从不一致的影响时间很短,主从同步完成后才会读取新的数据。二、缓存与数据库的不一致再看一下,引入缓存后,缓存与数据库的不一致。如上图,场景也在发生,先写后读:(1+2)先一个写请求,清除缓存,写入数据库(3+4+5)然后马上一个读请求,readcache,cachemiss,readfromlibrary,把数据放入writecache以便后续读可以cachehit(主从同步未完成,旧数据放入cache)(6)***,结果主从同步完成的方式是:旧数据放入缓存,即使主从同步完成,还是会从缓存中读取旧数据。可以看出,加入缓存后,产生的不一致会影响很长时间,最终达不到一致性。3、问题分析可见,这里所说的缓存和数据库数据不一致,根本上是数据库主从不一致造成的。主库发生写操作后,在从库的binlog同步时间间隔内,读请求可能会导致旧数据被缓存。如果不能彻底解决主从不一致,引入缓存后,在binlog同步区间内,旧数据不可避免。但是,有没有办法让即使引入缓存,不一致性也不会比“不缓存”更糟呢?这是一个更现实的优化目标。思路转化为:从库同步完成后,如果缓存中有旧数据,要及时淘汰旧数据。4.不一致性优化如上图所述,并发读写导致脏数据读入缓存后:(6)主从同步(7)通过工具订阅从库的binlog,这里我们可以最准确的知道从库的数据同步完成时画外音:这张图的订阅工具是DTS,可以是cannal,也可以自己订阅分析binlog(8)从执行write操作后library,再次delete到cache,消除这段时间可能写cache如此这般的旧数据,至少可以保证引入cache后,主从不一致不会比不引入更糟缓存。画外音:即使引入了缓存,也只有一小段时间可以读取旧数据。5、结束题:如何彻底避免主从同步时间差和数据一致性?答:详见《数据库主从不一致,怎么解?》。问:这个解决方案只能优化。在并发读写的情况下,存在缓存和数据库一致性的问题。如果缓存和数据库操作两次,原子性被破坏(比如数据库修改成功,缓存清除失败,导致数据不一致),如何优化数据一致性?答:详见《究竟先操作缓存,还是数据库?》。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文