一 redis缓存双写一致性
1.1 保证mysql和redis一致性的原则
1.给缓存设置过期时间,定期清理缓存并写回缓存,是保证最终一致性的解决方案。使用场景:在数据读多写少的情况下作为缓存来使用。
我们可以对已存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存的操作只是尽最大努力即可。也就是说数据库写成功,缓存更新失败,只要达到过期时间,后面的读请求自然会从数据库中读取最新值,然后回填缓存,达到一致性。一定注意,要以mysql的数据库的写入为准。
总结:目前采用的方案是: 先更新mysql,再删除redis,弊端最小。
1.2 redis保持一致性的流程
1.如果缓存在Redis
中存在,即缓存命中,则直接返回数据
2.如果Redis中没有对应缓存,则需要直接查询数据库,然后存入Redis,最后把数据返回。
通常情况下,我们会为某个缓存设置一个key值,并针对key值设置一个过期时间,如果被查询的数据对应的key过期了,则直接查询数据库,并将查询得到的数据存入Redis,然后重置过期时间,最后将数据返回
1.3 redis和mysql不一致的原因
在Redis的key值未过期的情况下,用户修改了个人信息,我们此时既要操作数据库数据,也要操作Redis数据。现在我们面临了两种选择:
1.先操作Redis
的数据,再操作数据库的数据
2.先操作数据库的数据,再操作Redis
的数据
如论选择哪种方法,最理想的情况下,两个操作要么同时成功,要么同时失败,否则就会出现Redis和数据库数据不一致的情况。
遗憾的是,目前没有什么框架能够保证Redis的数据和数据库的数据的完全一致性。我们只能根据场景和所需要付出的代码来采取一定的措施降低数据不一致出现的概率,在一致性和性能之间取得一个折中。
二 redis缓存双写一致性的几种方案的优缺点
2.1 先更新mysql,后更新redis
不一致性: 线程A更新数据库100后,开始更新redis出现卡顿;线程B进行更新数据库为80,开始更新redis为80,然后线程A开始更新redis为100;此时mysql为80,redis为100,造成redis和mysql二者之间数据不一致。
2.2 先更新mysql,后删除redis
先更新数据库,后删除缓存;假如删除缓存来不及或者失败,导致请求再次访问的是redis的旧数据。危害性就是最小的。
如果业务层要求必须读取一致性的数据,那么我们就需要在更新数据库时,先在redis缓存客户端暂停并发读请求,等数据更新完、缓存值删除后,重新写入redis后,再读数据数据,从而保证数据一致性。
实际真实生产环境中,分布式下很难做到实时一致性,一般都是考虑最终一致性。
2.3 先更新redis, 后更新mysql
不一致性: 线程A先更新redis为100,还没来得及更新mysql为100;线程B开始更新redis为80,更新mysql为80;此时线程A更新mysql数据库为100;这就造成 mysql为100,redis为80,处于不一致状态。
2.4 先删除redis,后更新mysql
1.先删除缓存值再更新数据库,有可能导致请求因缓存缺失而访问数据库,给数据库带来很大的压力打满mysql
2.如果业务应用中读取数据库和写缓存的时间不好估算,那么,延迟双删除的等待时间就不好设置。
3.文字描述:
两个并发操作,线程A进行删除redis数据;线程b发现redis没有数据,则查询mysql数据,然后回写到redis中,此时线程A进行更新mysql数据库;数据库的新值和redis的旧值存在不一致。
总结成表格:
解决办法: 采用延迟双删的策略
时间的判定:
三 先更新mysql,后删除redis的方案架构
3.1 架构图
1.