双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致
读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间
写操作:延迟双删
先删除缓存,再操作数据库
正常情况:
会出现脏数据情况:
先操作数据库,再删除缓存
正常情况
脏数据情况:
如上图所示,无论是先删除Redis缓存数据在删除数据库数据,还是先删除数据库数据再来删除Redis缓存数据,都是有可能会出现数据不一致的问题。
所以为了解决上面的问题,我们采用了延时双删的操作。
为什么需要延时删除?
因为假设数据库是主从数据库,主数据库同步到从节点需要时间,这个延时也有可能会出现问题,这个同步时间我们也无法预测,延时双删极大的控制了脏数据的风险,但也只是控制了一部分,也有可能会有脏数据的风险,不是绝对的强一致性。
保证强一致性方案
使用分布式锁实现,在写数据和读数据的时候都进行加锁操作,保证强一致性,不过效率不高。
我们优化一下,保证相对一致性的同时,提高性能,采用读写锁。
读多写少
共享锁:读锁readLock,加锁之后,其他线程可以共享读操作
排他锁:独占锁writeLock也叫,加锁之后,阻塞其他线程读写操作
允许短暂不一致性方案
异步通知保证数据的最终一致性
基于Canal的异步通知:
二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但不包括数据查询(SELECT、SHOW)语句。