如何保证缓存与数据库双写时的数据一致性?

在做系统优化时,想到了将数据进行分级存储的思路。因为在系统中会存在一些数据,有些数据的实时性要求不高,比如一些配置信息。基本上配置了很久才会变一次。而有一些数据实时性要求非常高,比如订单和流水的数据。所以这里根据数据要求实时性不同将数据分为三级。

第1级:订单数据和支付流水数据;这两块数据对实时性和精确性要求很高,所以不添加任何缓存,读写操作将直接操作数据库。

第2级:用户相关数据;这些数据和用户相关,具有读多写少的特征,所以我们使用redis进行缓存。

第3级:支付配置信息;这些数据和用户无关,具有数据量小,频繁读,几乎不修改的特征,所以我们使用本地内存进行缓存。

但是只要使用到缓存,无论是本地内存做缓存还是使用 redis 做缓存,那么就会存在数据同步的问题,因为配置信息缓存在内存中,而内存时无法感知到数据在数据库的修改。这样就会造成数据库中的数据与缓存中数据不一致的问题。怎样保证缓存和数据库双写时的数据一致性。有什么好的解决方案吗。

老生常谈的问题了,只要是用到缓存就会有一致性问题。方案有以下几种:

  1. 先删除缓存,再写入数据库。这种方案实现简单,但在高并发下仍然有不一致的问题。如果业务能容忍一定时间的不一致,可以减少缓存有效期缓解不一致。
  2. 延迟双删。先删除缓存,再写入数据库,最后延迟一定时间(比如1秒)再次删除缓存。这就可以避免方案一的问题。但该方案与方案一都需要考虑删除失败的场景。
  3. 使用canal监听数据库binlog变更,有变更时就去缓存里将旧缓存删除掉。这种方案最保险,但要引入第三方中间件,会增加项目技术复杂度。

这里给出一些拙见:根据你分的等级,3级这种几乎不变的配置信息,直接采取先读缓存在读DB的方式即可,因为几乎不变,如果变动直接清除缓存即可;2级信息,这种偶尔会变的数据读取方式和3级一样先缓存在DB,这是时候可以给缓存设置有效期,这个有效期可以根据数据变动的最小频率设置;1级的实时性有效就比较高了,这种一般采用延时双删的策略,先删除缓存,读取数据库,等待一定的时间(目的等待一次调用),再删除缓存。