作者:京东批发 于泷

一、背景

在高并发场景中,为避免大量申请间接拜访数据库,缓解数据库压力,罕用的形式个别会减少缓存层起到缓冲作用,缩小数据库压力。引入缓存,就会波及到缓存与数据库中数据如何放弃一致性问题,本文将对几种缓存与数据库保证数据一致性的应用形式进行剖析。为保障高并发性能,以下剖析场景不思考执行的原子性及加锁等强一致性要求的场景,仅谋求最终一致性。

二、读取过程

• 读缓存

• 如果缓存里没有值,那就读取数据库的值

• 同时把这个值写进缓存中

三、更新过程

更新操作有多种策略,各有优劣,次要针对此场景进行剖析

策略1:先更新db,再删除缓存(罕用的Cache-Aside Pattern旁路缓存)

问题:

1.如果更新db胜利,删缓存失败,将导致数据不统一

2.极其场景,申请A读,B写

1)此时缓存刚好生效 2)A查库失去旧值 3)B更新DB胜利

4)B删除缓存 5)A将查到的旧值更新到缓存中

此场景的产生须要步骤2)查db 始终慢于 3)的更新db,能力导致4)先于5)执行,通常db的查问是要快于写入的,所以此极其场景的产生过于严格,不易产生

策略2:先更新db,再更新缓存

问题:

1.并发更新场景下,更新缓存会导致数据不统一

2.依据读写比,思考是否有必要频繁同步更新缓存,而且,如果结构缓存中数据过于简单,或者数据更新频繁,然而读取并不频繁的状况,还会造成不必要的性能损耗

此种形式不举荐

策略3:先更新缓存,再更新db

同上,不举荐

策略4:先删缓存,再更新db

先删缓存,尽管解决了策略1中,后删缓存如果失败的场景,但也会产生不统一的问题

例如:申请 A 删除缓存,这时申请B来查,就会击穿到数据库,B读取到旧的值后写入缓存,A失常更新db,因为时间差导致数据不统一的状况

策略5:缓存延时双删

该策略兼容了策略1和策略4,解决了先删缓存还是后删缓存的问题,如策略1中,更新db后删缓存失败和策略4中的不统一场景,该策略能够将延时工夫内(比方延时10ms)所造成的缓存脏数据,再次删除。然而,如果延时删缓存失败,策略4中不统一问题还会产生,同时延时的实现,如创立线程,或者引入mq异步,可能会减少零碎复杂度问题。

策略6:变种双删,前置缓存过期工夫

该策略针对策略1中后删缓存失败的场景,前置一层缓存数据过期工夫(具体工夫依据本身零碎自身评估,如可笼罩db读写耗时或一致性容忍度等),更新db后就算删缓存失败,在expire工夫后也能保障缓存中无数据。同时,前置expire失败,或者更新db失败,都不会影响数据统一。

可能解决策略4中的问题:申请 A 删除缓存,这时申请B来查,就会击穿到数据库,B读取到旧的值后写入缓存,A失常更新db,因为时间差导致数据不统一的状况,形容图如下:

本策略中步骤1为expire缓存,不会产生击穿缓存到数据库的状况,数据将间接返回。除非更极其状况,如下图:

expire工夫没有覆盖住更新db的耗时,相似策略1中极其场景,此处不赘述

四、总结

对于每种计划策略,各有利弊,但一致性问题始终存在(文章结尾排除了原子性和锁),只是产生的几率在一点点缓缓变小了,计划的评估不仅要依据本身零碎的业务场景,如读写比、并发量、一致性容忍度,还要思考零碎复杂度,投入产出比等,寻找最合适的计划。