> 文章列表 > Redis缓存数据库双写不一致问题

Redis缓存数据库双写不一致问题

Redis缓存数据库双写不一致问题

目录

    • 说明
    • 一般电商数据类型的分类和对应解决方案
      • 对于用户级别的数据缓存双写不一致解决方案
      • 对于平台级别的数据缓存双写不一致解决方案

说明

  Redis双写不一致,也就是数据在缓存和数据库的一致性问题的讨论在业内是讨论得比较热门的,也是比较有争议性的。
  这种Redis缓存数据库双写不一致的问题,我们一般是要看数据类型、访问频率以及对数据差异的容忍度来决定具体的方案。
 
 

一般电商数据类型的分类和对应解决方案

数据类型在电商平台一般分为两种:
1、用户级别的数据缓存。
2、平台级别的数据缓存(所有用户都会访问到的)。
 

对于用户级别的数据缓存双写不一致解决方案

对于用户级别的数据缓存,这种缓存一般来说访问频率卡在用户级别上,并且不会又太大的并发量,我们可以举个例子来说:
比如用户的余额缓存,这种缓存一般用于显示,在用户进行充值或者支付的时候进行更新,由于只涉及到显示,所以这种缓存有比较好的数据差异的容忍度,一般方案为在收到支付或者是充值消息之后,直接删除缓存即可。直接删除缓存的理由是用户对余额的更新到查询我们可以认为是不会瞬间并发的,会有一个比较长的操作时间间隔,因此基本上不会又脏数据的情况。
但是在这种情况下可能会出现删除缓存失败的情况,此时会出现缓存数据为旧数据的情况,但是一般Redis的SLO可以达到99.99%。也就是这种情况也会小概率事件,如果真的出现因为缓存删除失败而导致的两方数据不一致的情况,由于本身数据特性影响到的也是单个客户,同时缓存本身也会有过期时间因此是可以接收的。

而对于需要保证强一致性,并且并发量较大的用户级别的缓存。我们可以采用延时双删的方案,具体的方案是:
删除缓存–>更新缓存数据–>延时队列再删除一次缓存。还可以加上binlog读取框架如Canal等来进行数据的一致性判断(听朋友说,在阿里不提倡直接依赖binlog框架来保证数据一致性,一般只做兜底判断和一致性判断,同时可以告诫给到人工处理),有了上述的方案的保证之后,还是有可能会出现数据不一致的情况,但是概率会非常小,同时只会影响到单个用户,而且还有人工兜底,我们一般会认为这个方案是可行的。
 

对于平台级别的数据缓存双写不一致解决方案

对于平台级别的数据缓存,一般会把是多级缓存,会把缓存存两份:
过期时间短的作为一级缓存
过期时间较长的作为二级缓存
在发生数据更新的时候,先加分布式锁,然后把缓存删除作为第一步,同时将两级缓存删除必须成功之后才进行实际的数据更新,然后才进行数据库数据更新操作。
在读取的时候先读取一级缓存,如果一级缓存没有读到,加分布式锁进行读取数据库并更新一二级缓存,没有拿到锁的线程读取二级缓存,同样我们可以加上binlog读取框架如Canal等进行数据的一致性判断,进行人工兜底。

但是这个方案也会出现一些问题:
1、由于需要解决缓存击穿的问题,所以分成了两极,并用分布式锁来保证。
2、可能以及缓存删除成功,但是数据更新失败,这种情况下我们可以选择不做处理,因为我们做了缓存击穿的处理,并且平台级别的数据一般可以认为比较少会更新。
3、拿到分布式锁的线程要更新两次缓存,
一级缓存更新失败,可以不进行处理,由下一个拿到锁的线程来进行更新。
二级缓存更新失败会出现问题,如果此时一级缓存更新成功,二级缓存就不会再有请求,所以这种情况下我们可以直接人工介入处理。
4、由于我们保存了两份相同的数据,所以会出现数据冗余的情况,但是是平台级别的数据,所以我们完全可以接受。

而对于需要保证强一致性的做法就是直接在监听消息之后删除缓存,这得看师姐数据的情况来定方案。