redis 缓存问题汇总
前言:在使用redis的时候,特别是大型应用,会碰到不少问题,下面就来总结一下使用redis时的常见问题
一、redis为缓存的问题
1、缓存和数据库双写一致性问题
分析:一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。
就是如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,
只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存。 回答:先淘汰cache,再写db(如果删除缓存失败,那就不要更新数据库,如果说删除缓存成功,而更新数据库失败,
那查询的时候只是从数据库里查了旧的数据而已,这样就能保持数据库与缓存的一致性。)
问题:先删缓存再更新数据库存在的问题,如下图
方案一:采用延时双删策略。
(1)先淘汰缓存
(2)再写数据库(这两步和原来一样)
(3)休眠1秒,再次淘汰缓存(这样可以把读请求造成的脏数据缓存清掉)
这么做,可以将1秒内所造成的缓存脏数据,再次删除。(为何是1秒?需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。当然这种策略还要考虑redis和数据库主从同步的耗时。不过这1秒内读取到的还是旧数据)
方案二:队列串行处理
(1)先删除缓存,再更新数据库
(2)将更新数据库的操作加入到队列中
(3)在更新期间有读请求到来时,发现没缓存,这时候将读请求按路由唯一key加入到队列中
(4)等待更新操作执行完后,再去读取最新的数据,然后更新缓存
注意:这块需要多模拟压测自己业务的写请求有多少,如果写请求过多,会存在读请求超时等问题
2、缓存雪崩、击穿问题
请参考我的另一篇文章:缓存雪崩、击穿解决方案
3、缓存的并发竞争问题
分析:这个问题大致就是,同时有多个子系统去set一个key。这个时候要注意什么呢?大家思考过么。需要说明一下,博主提前百度了一下,发现答案基本都是推荐用redis事务机制。
如果生产环境基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。
回答:
1、如果对这个key操作,不要求顺序
这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。
2、如果对这个key操作,要求顺序
一般用串行方式就行,比如队列