前言:上次面试被面试官问到redis做缓存时如何保证与数据库的数据一致。尽管能答出个八九不离十,但是总感觉缺少一下发自内心的自信,可能也没有去深究为啥要先“更新数据库,再删除redis;为何不直接更新redis?”。
抛出问题
对于redis做缓存的业务场景,在对数据进行增删改时,都要面对同时操作数据库和redis缓存的情况,
一般会有以下4种方案选择。那么该如何选择呢!相信很多同学都知道,一般都是先更新数据库,再删除缓存。
但是为什么要这么做呢?其他3种方案会存在什么样的问题呢?这么多是否还存在问题?
带着问题继续往下看,此时你也可以先思考或者回忆甚至物色一个场景上代码验证一下自己心中的答案。
- 先更新数据库,再更新缓存。
- 先更新缓存,再更新数据库。
- 先更新数据库,再删除缓存。
- 先删除缓存,再更新数据库。
业务场景
某购物网站推出特价商品活动,由于是特价,所以被浏览的次数也会大大增加。
因此这些特价商品会保存在缓存里面,又因为是特价商品,所以库存也有限。
当用户购买特价商品时,分别采用上述4种方案进行处理,分析商品库存会存在什么样的问题。
过程分析
方案一:先更新数据库,再更新缓存。
正常逻辑是:用户下单商品时,先查询redis库存,库存数量>=用户购买数量,请求通过。更新数据库该商品的库存(此处更新的库存数是计算后的库存,而不是通过sql去更新再计算),然后再更新redis商品的库存。(此处先不用纠结真实的业务逻辑,把更新库存操作当做管理员更新商品的描述等参数即可)
问题1:当用户A的下单操作更新完数据库后,还没有更新缓存前。用户B的下单操作刚好发起,并抢在A更新redis之前完成所有操作。假如原本有库存10,A下单3,那么数据库库存先变为7,此时redis中的库存仍然为10。此时用户B的下单8,由于redis中的库存为10,因此B会将数据库的库存更新为2,现在无论是谁先去执行后续操作,数据都不正确。