12.MySQL和Redis一致性
# 01.如何保证MySQL和Redis一致性
# 0、说明
没有完美的方案,只有最适合某场景的方案
这个是数据一致性、系统性能和系统复杂度的选择与取舍
# 1、先更新MySQL,再更新Redis
如果先更新MySQL成功了,还未对Redis进行更新的间隙期,这时如果请求过来,读到的都是Redis的更新前数据
如果先更新MySQL成功了,再更新Redis失败了的话,后面的请求读到的都是Redis的更新前数据,并且后续的补救方案很难做
补救方案一
为Redis更新失败,将MySQL中的对应数据也回滚了,以此达到两者数据的一致性
但MySQL是主数据源,它代表的是数据的“权威性”,这样做显然并不合理
补救方案二
通过Redis重试更新的方式进行补救。但如果重试也失败了,还要继续重试吗?
另外,重试时间间隔设置多少?时间间隔设置长了,影响业务的时间也会变长
时间间隔设置短了,重试成功率又会降低,这些其实都是问题
# 2、先更新Redis,再更新MySQL
这个方案,要比方案一的“先更新MySQL,再更新Redis”合理一些
原因在于更新完Redis的话,哪怕还没更新MySQL,这时如果请求过来,读到的都是Redis更新后的新数据
另外,先更新Redis成功,再更新MySQL失败,可以通过再删除Redis所对应的数据进行补救
缺点:读到的都是Redis未生效的新数据
# 3、先更新MySQL,再删除Redis
如果先更新MySQL成功了,还未对Redis进行删除的间隙期,这时如果请求过来,读到的都是Redis的删除前数据。
如果先更新MySQL成功了,再删除Redis失败了的话,后面的请求读到的都是Redis的删除前数据,并且后续的补救方案很难做
# 4、先删除Redis,再更新MySQL
如果先删除Redis成功了,还未对MySQL进行更新的间隙期
只存在于MySQL一个存储载体中,也就没有了数据一致性的问题
如果先删除Redis成功了,再更新MySQL失败了的话
只存在于MySQL一个存储载体中,所谓的补救方案也就不需要了,直接当这条数据没更新成功
产生问题
- 某商品的库存数为10个,用户A购买一件商品时进行库存扣减,因此第一步先删除了Redis中的库存数
- 这时,用户B查询该商品的库存,发现Redis中并没有该商品的库存,于是从MySQL中读取库存数后,写入到了Redis中(10个)
- 然后,用户A更新数据库,将库存数从10个扣减为9个
- 最终,Redis中的库存数是10个,MySQL中的库存数是9个
# 5、分布式锁
- 分布式锁完全可以解决一致性问题,但是性能会降低,我们设置缓存的目的就是为了性能