在Redis的实际部署应用中,可能存在着Redis突然变慢的问题,在此问题发生的时候,会影响到旁人,以至于和Redis在同一个系统中的其他系统,比如数据库.
举个例子,就是在下单的时候,如果Redis变慢了,下单的请求就会被拖慢,也就是用户提交了下单申请,但是没有任何响应,会造成非常糟糕的使用体验.
而在Redis变慢的可能阻塞点中,包含异步线程机制和CPU绑核,除此外,还有一些因素会导致Redis变慢,那么我们将分为两节课,分别从问题认定,系统性排查,应对方案来进行讲解
对于Redis变慢来说,需要基于Redis本身的工作原理,并结合何其交互的操作系统,存储以及网络等外部系统关键机制来进行分析
Redis自身存在的阻塞点包含自身的操作特性,文件系统以及操作系统
那么我们先说一下Redis自身提供的键值对命令对延迟的影响,关键的操作就是慢查询命令和过期key
1.慢查询命令
指的是在Redis中执行速度慢的命令,这和命令操作的副再度有关
比如Value为String类型的时候,GET和SET就是操作Redis的哈希表索引,操作复杂固定为O(1),但是集合操作中的,SORT SUNION SMEMBERS 操作复杂度为 O(N+M*log(M))和O(N),N为Set中的元素个数,复杂度就增多了
对于这些复杂度过高的问题,可以使用Redis提供的日志查看是否存在,并且考虑进行处理
其处理的方式主要有
(1).使用其他的高效命令进行代替,如果需要返回一个SET中的所有成员时候,不使用SMEMBERS命令,而是要使用SSCAN多次迭代返回,避免造成线程阻塞
(2).如果需要排序 交集和并集操作的时候,可以考虑在客户端完成,尽量减少SORT SUNION SINTER命令,避免拖慢Redis实例
还有一些容易忽略的慢查询命令,就是KEYS,用于返回和输入模式匹配所有的key
KEYS *name*
KEYS命令需要遍历存储的键值对,所以操作延迟高,所以KEYS命令不建议用于生产环境
2.过期key命令
过期key的自动删除机制,是Redis用于回收内存空间的常用机制,应用广泛,本身就会引起Redis操作阻塞,导致性能变慢
Redis键值对的key可以设置过期时间,而对于过期的key,Redis每100毫秒会删除一些过期key
比如
采用 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP个数的key,并且其中过期的key删除
然后如果采样到的key中超过25%的key过期了,就重复删除的过程,直到过期key的比例降至25%以下
所以对于删除操作,因为本身就是阻塞的,一旦循环删除开始了,Redis线程就会一直执行删除,从而拖慢Redis
为了避免循环删除的触发,需要避免将大量的Key的过期时间设置为同一时间,避免同一时间有大量key同时过期.
这就需要检查业务代码中,是否有大量的KEY使用了相同的时间戳或者相同的过期秒数,如果是真的有一批key存在相同的过期时间,可以在EXPIREAT和EXPIRE的过期参数上,加上一个固定范围内的随机数,保证了key在一个邻近范围删除,避免了同时过期造成过多的压力
总结一下:
Redis变慢的原因可以基本分为了自身操作,以及文件系统和操作系统
对于自身操作,则包含慢查询命令和过期key导致的,也是本章主要介绍的
最后一个问题,KEYS命令可能导致Redis线程阻塞,不适合生产环境,但是本身的功能是上层业务需要的话,还是需要其他命令来代替KEYS命令,有什么其他命令可以代替吗?
可以利用SCAN来进行命令,对于其中存在的重复key,上层利用set这种天然去重的数据结构来进行接收