其他
你的 Redis 为什么变慢了?
点击上方蓝色“程序猿DD”,选择“设为星标”
回复“资源”获取独家整理的学习资料!
使用复杂度高的命令
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近1000条慢日志
CONFIG SET slowlog-max-len 1000
SLOWLOG get 5
查询最近5条慢日志:1) 1) (integer) 32693 # 慢日志ID
2) (integer) 1593763337 # 执行时间
3) (integer) 5299 # 执行耗时(微妙)
4) 1) "LRANGE" # 具体执行的命令和参数
2) "user_list_2000"
3) "0"
4) "-1"
2) 1) (integer) 32692
2) (integer) 1593763337
3) (integer) 5044
4) 1) "GET"
2) "book_price_1000"
...
O(n)
以上复杂度的命令,例如sort
、sunion
、zunionstore
,或者在执行O(n)
命令时操作的数据量比较大,这些情况下Redis处理数据时就会很耗时。存储大key
SET
、DELETE
操作出现在慢日志记录中,那么你就要怀疑是否存在Redis写入了大key的情况。-i
参数控制即可,它表示扫描过程中每次扫描的时间间隔,单位是秒。scan
命令,遍历所有key,然后针对不同类型的key执行strlen
、llen
、hlen
、scard
、zcard
来获取字符串的长度以及容器类型(list/dict/set/zset)的元素个数。lazy-free
的机制,用于异步释放大key的内存,降低对Redis性能的影响。即使这样,我们也不建议使用大key,大key在集群的迁移过程中,也会影响到迁移的性能,这个后面在介绍集群相关的文章时,会再详细介绍到。集中过期
主动过期:Redis内部维护一个定时任务,默认每隔100毫秒会从过期字典中随机取出20个key,删除过期的key,如果过期key的比例超过了25%,则继续获取20个key,删除过期的key,循环往复,直到过期key的比例下降到25%或者这次任务的执行耗时超过了25毫秒,才会退出循环 懒惰过期:只有当访问某个key时,才判断这个key是否已过期,如果已经过期,则从实例中删除
expireat
或pexpireat
命令,在代码中搜索这个关键字就可以了。redis.expireat(key, expire_time + random(300))
info
可以拿到所有的运行数据,在这里我们需要重点关注expired_keys
这一项,它代表整个实例到目前为止,累计删除过期key的数量。实例内存达到上限
maxmemory
,然后开启LRU淘汰策略。maxmemory
后,你会发现之后的每次写入新的数据,有可能变慢了。maxmemory
后,每次写入新的数据之前,必须先踢出一部分数据,让内存维持在maxmemory
之下。allkeys-lru:不管key是否设置了过期,淘汰最近最少访问的key volatile-lru:只淘汰最近最少访问并设置过期的key allkeys-random:不管key是否设置了过期,随机淘汰 volatile-random:只随机淘汰有设置过期的key allkeys-ttl:不管key是否设置了过期,淘汰即将过期的key noeviction:不淘汰任何key,满容后再写入直接报错 allkeys-lfu:不管key是否设置了过期,淘汰访问频率最低的key(4.0+支持) volatile-lfu:只淘汰访问频率最低的过期key(4.0+支持)
allkeys-lru
或volatile-lru
策略,它们的处理逻辑是,每次从实例中随机取出一批key(可配置),然后淘汰一个最少访问的key,之后把剩下的key暂存到一个池子中,继续随机取出一批key,并与之前池子中的key比较,再淘汰一个最少访问的key。以此循环,直到内存降到maxmemory
之下。allkeys-random
或volatile-random
策略,那么就会快很多,因为是随机淘汰,那么就少了比较key访问频率时间的消耗了,随机拿出一批key后直接淘汰即可,因此这个策略要比上面的LRU策略执行快一些。maxmemory
限制实例的内存上限,同时面临淘汰key导致延迟增大的的情况,要想缓解这种情况,除了上面说的避免存储大key、使用随机淘汰策略之外,也可以考虑拆分实例的方法来缓解,拆分实例可以把一个实例淘汰key的压力分摊到多个实例上,可以在一定程度降低延迟。fork耗时严重
fork
出一个子进程进行数据的持久化,在fork
执行过程中,父进程需要拷贝内存页表给子进程,如果整个实例内存占用很大,那么需要拷贝的内存页表会比较耗时,此过程会消耗大量的CPU资源,在完成fork
之前,整个实例会被阻塞住,无法处理任何请求,如果此时CPU资源紧张,那么fork
的时间会更长,甚至达到秒级。这会严重影响Redis的性能。info
命令,查看最后一次fork
执行的耗时latest_fork_usec
,单位微妙。这个时间就是整个实例阻塞无法处理请求的时间。fork
的耗时也与系统有关,如果把Redis部署在虚拟机上,那么这个时间也会增大。所以使用Redis时建议部署在物理机上,降低fork
的影响。绑定CPU
fork
出的子进程,子进程会继承父进程的CPU使用偏好,而此时子进程会消耗大量的CPU资源进行数据持久化,子进程会与主进程发生CPU争抢,这也会导致主进程的CPU资源不足访问延迟增大。开启AOF
fork
执行耗时导致Redis延迟增大,除了这个之外,如果开启AOF机制,设置的策略不合理,也会导致性能问题。appendfsync always
:每次写入都刷盘,对性能影响最大,占用磁盘IO比较高,数据安全性最高appendfsync everysec
:1秒刷一次盘,对性能影响相对较小,节点宕机时最多丢失1秒的数据appendfsync no
:按照操作系统的机制刷盘,对性能影响最小,数据安全性低,节点宕机丢失数据取决于操作系统刷盘机制
appendfsync always
时,Redis每处理一次写命令,都会把这个命令写入磁盘,而且这个操作是在主线程中执行的。appendfsync everysec
会每隔1秒刷盘,而appendfsync no
取决于操作系统的刷盘时间,安全性不高。因此我们推荐使用appendfsync everysec
这种方式,在最坏的情况下,只会丢失1秒的数据,但它能保持较好的访问性能。使用Swap
网卡负载过高
总结
fork
原理、Swap机制等,并对Redis的容量进行合理规划,预留足够的机器资源,对机器做好完善的监控,才能保证Redis的稳定运行。往期推荐
Java程序员必备的11大IntelliJ插件
如果MySQL事务中发生了网络异常?
Spring Boot 注解大全,一键收藏!回城路上复习!
裸辞1天 vs 裸辞10天 vs 裸辞一个月
还剩10天,赶紧登下百度网盘,拯救你的2T存储空间吧!
《最受欢迎的女友职业排行榜Top10》
﹀
﹀
﹀
推荐加入
最近热门内容回顾 #技术人系列