共计 1209 个字符,预计需要花费 4 分钟才能阅读完成。
数据库和缓存一致性个别分为两类,最终一致性和强一致性。
最终一致性
名词解释:db 更新后通过一段时间后要求能拜访到更新后的数据,是最终一致性。
实用场景:对于实时性要求不是很高的业务。
计划一:
读取:先从缓存读取,读取不到则读取 db,而后写入缓存。
写入 / 更新 / 删除:先写 db,再写入 / 更新 / 删除缓存。
可能遇到的问题:T0 时刻申请 A 读取的时候缓存为空,从 db 读取数据,T1 时刻申请 B 更新了 DB 和缓存,T2 时刻更新了缓存,T3 时刻申请 A 将老数据写入缓存,此时缓存数据为脏数据。
计划二
读取:先从缓存读取,读取不到则读取 db,而后写入缓存。
写入 / 更新 / 删除:先写入 / 更新 / 删除缓存,再更新 db。
可能遇到的问题:T0 时刻申请 A 读取的时候缓存为空,从 db 读取数据,T1 时刻申请 B 删除了缓存,T2 时刻申请 A 将老数据写入缓存,T3 时刻申请 B 更新了缓存,此时缓存数据为脏数据。
对于计划一二,既然先更新缓存和数据库都不行,那是否给更新 db 和缓存的整体操作中加上锁呢,确实能够,然而这样读取也须要加锁,会影响性能,除非是一致性要求很高的场景,不然不倡议这样应用。
计划三:
读取 :从缓存读取,读取不到则返回空。
写入 / 更新 / 删除:更新 db 再更新缓存,仍然会有不同申请造成的并发问题,除非把更新 db 和缓存的整个操作加锁,不过会有性能问题,而且若更新 db 胜利,更新缓存失败,会有脏数据。
计划四:
读取:从缓存读取,读取不到则返回空。
写入 / 更新 / 删除:先更新 db,异步音讯更新缓存,音讯里加上数据更新工夫作为版本号,消费者加锁生产音讯,缓存数据也存储工夫戳,依据工夫戳判断是否须要进行更新,若缓存为空则间接写入。
可能遇到的问题:
1. 若先更新再删除,消费者先生产到了删除申请,再生产到更新申请,则缓存为脏数据。
2. 工夫戳精度不够示意版本号。
3. 更新 db 胜利,发送音讯失败。
解决方案:
1. 加上 isDel 字段,删除操作视为更新操作,只是将 isDel 字段置为 true。待缓存主动过期删除。
2. 须要依据业务场景选取字段,或者在 db 加上版本号。
3. 发送音讯失败记录音讯到本地音讯表,定时工作轮询重发。
强一致性:
名词解释 :对于关系型数据库,要求更新过的数据能被后续的拜访都能看到,是强一致性。
实用场景:对于实时性要求比拟高的业务。
计划一:
读取 :先从缓存读取,读取不到则读取 db,而后写入缓存。
写入 / 更新 / 删除 :先写入 / 更新 /db,再删除缓存。
可能遇到的问题:
1. 如图,查问操作在 db 更新后查问的还是老数据。
2. 和最终一致性的计划一一样,查问操作查问数据时缓存不存在,从 db 写入老缓存缓存,导致缓存存在脏数据。
计划二:
新增 / 批改 / 删除: 将更新 db 和删除缓存整体操作加锁 lock1。
查问:查问时先判断锁 lock1 是否存在,若锁存在则读取 db 并返回数据,锁不存在间接查问缓存,若缓存存在则间接返回后果,缓存不存在同样加锁 lock1,执行查问 db 和更新缓存操作,这样能够保障强一致性。