前言:在使用redis的时候,特别是大型应用,会碰到很多问题,下面就来总结一下使用redis时的常见问题html
1、redis为缓存的问题redis
一、缓存和数据库双写一致性问题算法
分析:一致性问题是分布式常见问题,还能够再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是若是对数据有强一致性要求,不能放缓存。
咱们所作的一切,只能保证最终一致性。另外,咱们所作的方案其实从根本上来讲,只能说下降不一致发生的几率,没法彻底避免。所以,有强一致性要求的数据,不能放缓存。
回答:先淘汰cache,再写db(若是删除缓存失败,那就不要更新数据库,若是说删除缓存成功,而更新数据库失败,那查询的时候只是从数据库里查了旧的数据而已,这样就能保持数据库与缓存的一致性。)
二、缓存雪崩、击穿问题 数据库
请参考个人另外一篇文章:缓存雪崩、击穿解决方案
三、缓存的并发竞争问题缓存
分析:这个问题大体就是,同时有多个子系统去set一个key。这个时候要注意什么呢?你们思考过么。须要说明一下,博主提早百度了一下,发现答案基本都是推荐用redis事务机制。
若是生产环境基本都是redis集群环境,作了数据分片操做。你一个事务中有涉及到多个key操做的时候,这多个key不必定都存储在同一个redis-server上。所以,redis的事务机制,十分鸡肋。
回答:
一、若是对这个key操做,不要求顺序
这种状况下,准备一个分布式锁,你们去抢锁,抢到锁就作set操做便可,比较简单。
二、若是对这个key操做,要求顺序
通常用串行方式就行,好比队列
2、redis的过时策略及内存淘汰机制并发
这个问题其实至关重要,到底redis有没用到家,这个问题就能够看出来。好比你redis只能存5G数据,但是你写了10G,那会删5G的数据。
怎么删的,这个问题思考过么?还有,你的数据已经设置了过时时间,可是时间到了,内存占用率仍是比较高,有思考过缘由么?
一、redis采用的是按期删除+惰性删除策略。dom
二、为何不用定时删除策略?分布式
定时删除,用一个定时器来负责监视key,过时则自动删除。虽然内存及时释放,可是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,所以没有采用这一策略.
三、按期删除+惰性删除是如何工做的呢?测试
按期删除,redis默认每一个100ms检查,是否有过时的key,有过时key则删除。须要说明的是,redis不是每一个100ms将全部的key检查一次,
而是随机抽取进行检查(若是每隔100ms,所有key进行检查,redis岂不是卡死)。所以,若是只采用按期删除策略,会致使不少key到时间没有删除。
因而,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key若是设置了过时时间那么是否过时了?若是过时了此时就会删除。
(1)上面提到的随机抽取的方式spa
一、随机测试100个设置了过时时间的key
二、删除全部发现的已过时的key
三、若删除的key超过25个则重复步骤1
说明:这是一个基于几率的简单算法,基本的假设是抽出的样本可以表明整个key空间,redis持续清理过时的数据直至将要过时的key的百分比降到了25%如下。
另外每隔100ms检测一次能够手动修改这频率,能够找关于 hz 选项的说明。
注意:当REDIS运行在主从模式时,只有主结点才会执行上述这两种过时删除策略,而后把删除操做”del key”同步到从结点。
四、采用按期删除+惰性删除就没其余问题了么?
不是的,若是按期删除没删除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优先移除。不推荐
总结与备忘
一、若是Redis中天天过时大量Key(好比几千万),那么必须得考虑过时Key的清理:
1)、增长Redis主动清理的频率(经过调大hz参数);
2)、手动清理过时Key,最简单的方法是进行scan操做,scan操做会触发第一种被动删除,scan操做时候别忘了加count;
二、dbsize命令返回的Key数量,包含了过时Key;
三、randomkey命令返回的Key,不包含过时Key;
四、scan命令返回的Key,包含过时Key;
五、keys对应的Key数量等同于dbsize;
六、info命令返回的# Keyspace:db6:keys=1034937352,expires=994731489,avg_ttl=507838502
1)、expires指的是设置了过时时间的Key数量;
2)、avg_ttl指设置了过时时间的Key的平均过时时间(单位:毫秒);