作者:弍大爺 | 来源:互联网 | 2023-10-13 12:27
update之后,写MySql,再写入Redis,替旧数据(可在MySql端定义CRUD触发器,触发后写数据到Redis,也可Redis端解析binlog)
设定超时时间,redis自动删除数据。第二次删除前最好休眠时间,比如500毫秒,又增加写耗时。
一、Redis不会自己同步变更,要告诉。机制(不仅限于):
1. Redis过期去DB取,不立刻更新,顺带重新set redis(称作“Cache Aside”)。不一致时间可设置有效期,如10min。没设置不灵。
2. 通过代码更新DB。然后马上del掉redis数据。下次取数据时,恢复上一条方式。Cache Aside变体。好处一致性比较好,一般情况,不一致时间1s以下,绝大部分足够。极少不一致
Cache Aside,“Cache”在DB访问的主流程上帮个忙
1和2的做法常规上被称为“Cache“。而且因为1有更新不及时的问题,2有极端情况下数据会不一致的问题,所以常规Cache代码会把1+2组合起来,要求Redis里的数据必须有过期时间,并且不能太长,这样即便是不一致也能混过去。同时如果是主动对数据进行更新,Cache的数据更新也会比较及时。
并且2并不一定总是行得通。比如OLTP的服务在前面是Cache+DB的模式,而数据是由后台管理系统来更新的,总是不会触碰OLTP服务,更不会动Cache。这时将Redis看作是存储也算是一种方案,就是3:
3. 定时读db塞给Redis(Redis数据总不过期)。如定时任务,不一致时长是执行间隔;如果是队列不一致时间取决于产生和消费延迟。常用队列(或等价物)有Redis(怎么还是Redis),Kafka,AMQ,RMQ,binglog,log文件,阿里的canal等。
Cache当作“存储”来用,访问者只看得到Cache
这种做法还有一种变体Write Through,直接写DB,DB把数据更新到Cache,读Cache
Write Through + Cache当存储
以上方式无论如何都会有一段时间Redis和DB会不一致。实践上,这个不一致时间短则几十ms,长可以到几十分钟。这种程度的一致性对于很多业务场景都已经足够了。很多时候,用户无法区分自己读取的是Redis还是DB,只能读取到其中的一个。这时数据看起来直觉上是没问题的就可以接受了。只要不出现,用户先看见了数据是A,然后看到数据是B,之后一刷新,又看到A的尴尬场景就行了。(这也可以部份解释为啥用经常使用共享式的Cache而不是本地Cache方案)。
文档编辑,电商秒杀的扣库存,银行转账等,以上做法不够。解决办法不要用Redis。为啥银行一系统升级就要停服务,也有CAP,C强,A弱,不至于完全牺牲掉分布式协议一致性做
二、缓存更新失败
先更新数据库,再更新 Redis(失败)
1、不做任何操作,等Redis过期后
2、记录操作,异步处理,比对,不一致再更新
三、缓存删除失败
1、重试,删除动作放MQ中,MQ消费者再去删除。入侵业务逻辑
2、完全异步,监听 binlog 变化来删除缓存。 阿里canal监听 binlog
四、一致性协议
1、SAGA或者TCC, 代码补偿一致性
2、2PC, 3PC – 现实当中有XA协议。性能表现不佳,运维也麻烦,我比较少见到实际这么干的。
3、基于Paxos或者Raft的分布式锁,对Redis和DB双写,除非客户端和服务器访问分布式锁,也有一点点不一致。
实施、运维复杂度,Redis + DB场景没人这么干。多数据中心数据一致性维护的系统中。
一致性窘境:不一致时,很多做法。线性一致性、顺序一致性等。都在“不一致”和“强一致”折衷。
访问Cache,数据不是最新,要和DB去Sync,Sync中DB不能改。还不如不Cache。
https://www.zhihu.com/question/319817091