redis 缓存问题汇总

服务器

浏览数:152

2019-7-22

AD:资源代下载服务

前言:在使用redis的时候,特别是大型应用,会碰到不少问题,下面就来总结一下使用redis时的常见问题

一、redis为缓存的问题

  1、缓存和数据库双写一致性问题

分析:一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是如果对数据有强一致性要求,不能放缓存。
   我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存。 回答:先淘汰cache,再写db(如果删除缓存失败,那就不要更新数据库,如果说删除缓存成功,而更新数据库失败,那查询的时候只是从数据库里查了旧的数据而已,这样就能保持数据库与缓存的一致性。)

  2、缓存雪崩、击穿问题 

请参考我的另一篇文章:缓存雪崩、击穿解决方案

  3、缓存的并发竞争问题

分析:这个问题大致就是,同时有多个子系统去set一个key。这个时候要注意什么呢?大家思考过么。需要说明一下,博主提前百度了一下,发现答案基本都是推荐用redis事务机制。
   如果生产环境基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。 回答: 1、如果对这个key操作,不要求顺序 这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。 2、如果对这个key操作,要求顺序 一般用串行方式就行,比如队列

二、redis的过期策略及内存淘汰机制

  这个问题其实相当重要,到底redis有没用到家,这个问题就可以看出来。比如你redis只能存5G数据,可是你写了10G,那会删5G的数据。
怎么删的,这个问题思考过么?还有,你的数据已经设置了过期时间,但是时间到了,内存占用率还是比较高,有思考过原因么?

  1、redis采用的是定期删除+惰性删除策略。

  2、为什么不用定时删除策略?

定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.

  3、定期删除+惰性删除是如何工作的呢?

  定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,
而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。 于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

     (1)上面提到的随机抽取的方式

1、随机测试100个设置了过期时间的key
2、删除所有发现的已过期的key
3、若删除的key超过25个则重复步骤1

说明:这是一个基于概率的简单算法,基本的假设是抽出的样本能够代表整个key空间,redis持续清理过期的数据直至将要过期的key的百分比降到了25%以下。

另外每隔100ms检测一次可以手动修改这频率,可以找关于 hz 选项的说明。

注意:当REDIS运行在主从模式时,只有主结点才会执行上述这两种过期删除策略,然后把删除操作”del key”同步到从结点。

  4、采用定期删除+惰性删除就没其他问题了么?

不是的,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。

在redis.conf中有一行配置:# maxmemory-policy volatile-lru

该配置就是配内存淘汰策略的
    1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。--不推荐。
    2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用。
    3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。--不推荐。
    4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。不推荐
    5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。依然不推荐
    6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。不推荐

总结与备忘

1、如果Redis中每天过期大量Key(比如几千万),那么必须得考虑过期Key的清理:
    1)、增加Redis主动清理的频率(通过调大hz参数);
    2)、手动清理过期Key,最简单的方法是进行scan操作,scan操作会触发第一种被动删除,scan操作时候别忘了加count;

2、dbsize命令返回的Key数量,包含了过期Key;

3、randomkey命令返回的Key,不包含过期Key;

4、scan命令返回的Key,包含过期Key;

5、keys对应的Key数量等同于dbsize;

6、info命令返回的# Keyspace:db6:keys=1034937352,expires=994731489,avg_ttl=507838502
    1)、expires指的是设置了过期时间的Key数量;
    2)、avg_ttl指设置了过期时间的Key的平均过期时间(单位:毫秒);

 

作者:Cheney.rain