缓存数据一致性是什么?常用的方式有哪些?
缓存数据一致性是什么?常用的方式有哪些?
提示
题眼: 必知必会,至少三种以上。另外,缓存一致性不等于一致性。
缓存数据一致性指的是在使用缓存系统时,保证缓存数据与后端数据的一致性。当后端数据发生变化时,缓存数据也应该相应地进行更新,以确保用户获取到的数据是最新的。
常用的方式有以下几种:
1. 单写。只写数据库,等缓存自动过期。
2. 双写。写缓存,写数据库。
3. 读时更新,写时删除。
4. 延时双删。
5. 永不过期,异步更新
6. 监听数据库binlog,更新缓存
7. 返回缓存有效时间,由业务方决定。
重要
参考答案:
(参考高并发场景训练)
我们使用缓存的时候,一般都是缓存下面挂着一个数据库,当我们修改数据库里的数据时,同时也要更新缓存里的数据,如果两边都能保证数据相同,就是缓存是否一致。我用过的缓存一致性方案有三种。
第一种是最常用的“读时更新,写时删除”。这种方法最简单,当我们读一条数据的时候,我们就把这个数据加载进缓存,设置一个过期时间,之后的请求都可以走缓存,不再走数据库。当我们更新一条数据的时候,只修改数据库数据,然后把缓存数据删除,这样下次读操作的时候会把最新的数据加载进缓存。这种方法实现起来比较简单,不容易出错。缺点是, 如果删除数据失败,或者某个人同时设置了一个旧的数据进缓存,可能存在一个数据不一致的情况。而且,先删除,还是后删除都不太好解决这类问题,可以采用延时双删除的策略。
延时双删的话,思路也很简单,它时再“读时更新,写时删除”的基础上,在写数据库后,先删除一下数据,然后过个半秒钟,再删除一次,这样子可以保证下次再读数据时,能读到最新的数据。
上面两种方法会删除数据,这个行为风险很大,存在缓存击穿的可能,因此对于一些热点数据,多数情况下,会选择异步更新的方案。也就是,我们把缓存的数据设置为永不过期,然后写一个定时脚本,去更新数据。这样子可以避免缓存过期出现击穿的问题,而且更可控,可以通过手动触发的方式来更新缓存。但是缺点的话,因为脚本是定时执行的,可能会导致一段时间内,数据不一致的现象。
最后一种方式的话,我们在开发过程中用的也很多,但是实现起来比较复杂。它不再是写一个定时脚本来更新缓存,而是监听MySQL的binlog来更新缓存。我们公司用的是阿里云,它的话可以直接配置Canel配合Kafka,监听MySQL的binlog,然后再Go服务里起一个协程消费数据,它这个日志会写清楚,对某一张表具体做了什么操作,更新或者新增,然后对应的更新相关的缓存就行了。但这里也有一个问题,比如某个表的缓存再多个地方都有使用,那么它就要一个一个更新,这样子还是会出现短暂不一致。如果开协程的话,会导致Go服务的协程数量猛增,然后服务的负载变动很高,所以使用的时候最好是按照缓存使用的场景,优先更新最常用的,然后再更新其他的。
