移民者的Redis教程(二十):性能提升与故障排除
前言
你是否遇到过以下情况:
- 在Redis中执行同一个命令时,为什么有时会很快却很慢的答案?
- 为什么Redis执行SET和DEL命令需要这么长时间?
- 为什么我的Redis突然变慢然后又恢复了?
- 为什么我的Redis连续运行了很长时间,突然在某个时刻开始变慢?
Redis 真的很慢吗?
首先在开始之前,你需要知道Redis
是否真的很慢?
如果您发现您的业务服务API
变得越来越长,您需要首先查看服务内部,看看哪些链接正在减慢整个服务的速度。
更高效的方式是在服务内部添加链路监控(也可以打印日志),即在进入和退出访问外部依赖的服务时,记录每个请求对外部依赖的响应延迟。
如果你发现Redis
功能之间的关系变得非常长,那么你需要关注从业务服务到
的链接
Redis
该链路慢可能有两个原因:
- 企业服务器与Redis服务器之间存在网络问题,如网络质量差、数据传输延迟等。包裹。 、丢包等;
- Redis本身存在问题,需要更多调查Redis为什么慢。
这两种坑我都遇到过,哈哈哈
第一种出现的概率比较小。如果是,请联系网络运维。我们的文章主要讨论第二种情况。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。
什么是基本表演?
除了网络因素之外,如何检查Rediso是否真的很慢?首先需要对Redis
进行性能测试,了解Rediso在生产环境服务器上的性能。基线性能是指Redis
在负载正常的机器上,最大响应延迟和平均响应延迟是多少? ? (不!)。 Redis提供了慢日志命令的统计功能,记录任何执行时间较长的命令。
redis.config
文件:日志大小:config 设置 Slowlog-Log-Log-Log-Log-Slow-Slower 5000
127.0.0.1:6379> SLOWLOG get 5
1) 1) (integer) 32693 # 慢日志ID
2) (integer) 1593763337 # 执行时间戳
3) (integer) 5299 # 执行耗时(微秒)
4) 1) "LRANGE" # 具体执行的命令和参数
2) "user_list:2000"
3) "0"
4) "-1"
通过查看慢度日志,我们知道哪些命令在什么时间执行需要时间。经常使用
- 复杂命令或更高
O(N),例如
key、flushdb❀❀。
- 在难度中使用命令
O(N)
,但是N
的值非常大。例如:hgetall、lrange、smembers、zrange
等。不能使用,但需要明确N的值。
第一种情况变慢的原因是 **每类数据(5种key类型,不是全部数据)**安装的最大内存/哪个key元素最多,以及每种数据的Average比例和大小输入整个样本/项目数量。使用此命令的原理是 执行该命令时,请注意问题2: 硬件地址:https://github.com/weiyanwei412/rdb_bigkeys 如果你发现经常使用 被动删除:当读/写过期键时,会触发被动删除策略,键❀❀过期; 主动删除:由于惰性删除策略无法保证及时删除, 超过限制 也就是说,如果在主动过期过程中需要移除多个过期的key,那么在访问Redis
在使用内存数据时复杂度太大,需要更多的CPU第二个原因。导致慢的原因是
。它也是在命令执行之前执行的。也就是说,它会增加我们的Redis
需要返回太多给客户端
大于,则不断重复此过程,直到
,会释放
,花费更多时间slowlog-log-slower-than #它决定要对执行时间大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的命令进行记录。
slowlog-max-len #它决定 slowlog 最多能保存多少条日志,当发现redis性能下降的时候可以查看下是哪些命令导致的。
》关于汇编和数据协议在传输中网络
。 ? 示例中CPU
的使用率非常高,可能是因为命令的使用过于复杂
),执行命令时DEL。
分配内存Redis
是一个单线程客户端应用程序。如果你经常使用上面的命令,那么当
Redis
反转客户端请求时,只要上一个命令存在,就会生成下一个请求。对于顾客来说,延误会更长
。 ?然后你必须问自己你的实例是否写了 bigkey
。
Redis
写入数据时,需要为新数据。相应地,当从
Redis写入数据时,从删除数据时,
用于获取会释放
对应的内存空间。如果的键
值
写得很大,那么♿❿❿这个 键
,释放内存需要更多时间。这种类型的key
通常称为bigkey
。 如何查看示例中的bigkey分布?
Redis
提供了检查bigkey
的命令。您可以通过运行以下命令来检查bigkey。 的分布:
$ redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01
...
-------- summary -------
Sampled 829675 keys in the keyspace!
Total key length in bytes is 10059825 (avg len 12.13)
Biggest string found 'key:291880' has 10 bytes
Biggest list found 'mylist:004' has 40 items
Biggest set found 'myset:2386' has 38 members
Biggest hash found 'myhash:3574' has 37 fields
Biggest zset found 'myzset:2704' has 42 members
36313 strings with 363130 bytes (04.38% of keys, avg size 10.00)
787393 lists with 896540 items (94.90% of keys, avg size 1.14)
1994 sets with 40052 members (00.24% of keys, avg size 20.09)
1990 hashs with 39632 fields (00.24% of keys, avg size 19.92)
1985 zsets with 39750 members (00.24% of keys, avg size 20.03)
redis
在内部执行Scan
命令,通过实例中的所有键进行迭代,然后执行 ,分别表示关键类型。 HLEN、SCARD、ZCARDString
类型的长度和类型容器的元素数量(,,
可用。但是,如果一个键有多个元素,则)。 。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。
-i
来控制扫描频率。 表示扫描过程中每次检查后剩余的时间间隔,单位为秒
。在搜索结果List、Hash、Set、ZSet
),仅包含最多元素的键不一定意味着
。我们需要根据业务情况进一步评估内存使用情况。 rdb_bigkeys
工具,编写的工具,去
分析‶文件,找到 文件中的bigkeys,直接导出到文件
csv
方便查看。我个人推荐使用这个工具来查找大钥匙。 bigkey
的问题有什么好的解决办法吗? bigkey
(强烈推荐) 异步删除过期(lazyfree-lazy-expire yes)
,有阻塞Redis的可能。Redis
为 4.0
或更高版本,请使用命令 UNLINK‷ 而不是‷
,该命令可以从内存中释放 core 操作在后台线程中执行,减少对
Redis
的影响; Redis
是4.0
或更高,可以启用没有lazy
bit位级别操作:GETRANGE, SETRANGE, GETBIT and SETBIT
byte字节级别操作:GETRANGE and SETRANGE
的内存,并在后台线程
中执行。 bigkey
很多情况下,仍然会存在性能问题。例如,bigkey
在分片集群模式下,移动数据
会影响性能、、数据利用、 ,会影响性能。bigkey的影响。
,如果key集中过期
Redis
,并没有太大的延迟,但有时候突然有一波延迟。如下:延迟时间
很正常,每个间隔都会有延迟波。如果出现这种情况,需要检查业务代码中是否存在多个key
中心过期文件。如果多个key
同时过期,此时进入Redis
时,延迟可能会比较大。Redis 对于过期键有三种清理策略:
Redis
会定期删除key‷,‾过期。 内部 维持预定的工作。默认情况下,每
100
毫秒,20
会从全局过期表
中随机移除,过期的将被删除。 键按下至
:随机删除密钥,无论哪个密钥即将过期。 25%
或更低,或者在退出循环之前执行此操作需要 25
毫秒。 ** 这个废弃的key调度操作是在Redis线程中执行的。 **当当前使用内存
maxmemory
时,触发内存消除策略。 Redis
时,应用程序必须等待过期操作完成。。只有 Redis
可以满足此客户端请求。 bigkey
此时应该已经过期删除了,所以需要很长时间。此外,本次活动的迟到订单将不会记录在慢日志
中。 Slow log
中没有耗时的命令,但我们的应用程序意识到延迟变得更大
。事实上,删除key
所花费的时间已经过时了,我们需要特别注意这种情况。更多学习Redis的文章请参见:NoSQL数据库中的Redis系列。该系列定期更新。解决方案
key
添加随机过期时间,削减中间过期时间,减少key 点击;
Redis
为4.0
或更高,可以启用机制,无需lazy
当key过期时被删除s
松开按钮即可执行操作memory 在后台线程中进行,以免阻塞主线程。 Atendra 达到最大内存限制,但是当
redis
在新数据有时间之前达到 maxmemory
redis
必须从实例中逐出部分数据在写入新数据之前,将整个实例的内存保持在maxmemory
以下。 ? -random易失性随机
:仅随机删除过期时间的密钥。 allkeys-ttl
:是否设置了 key 并不重要。过期,删除过期的密钥noeviction
:没有可以撤销的密钥。当示例内存达到maxmeory时,写入新数据会直接返回错误allkeys-lfu
:无论设置什么key都已过期,移除访问频率最低的key(4.0+版本支持) volatile-lfu
:只需移除访问频率最低的key,并设置过期时间即可(4.0+版本支持) Redis
数据删除逻辑与删除过期数据相同键Redis
的延迟。此外,输入 OPS
越高,延迟越明显。示例 Redis
存储了 bigkey
,因此取消和删除 ” 需要很长时间。
建议改进:
- 不存储
bigkey
,减少内存释放耗时; - 淘汰策略改为随机淘汰,随机淘汰率
LRU
更快(根据工厂情况调整); - 分享例子,分享很多情况下
key
的取消压力; - 如果您使用的是Redis 4.0或更高版本,启用layz-free机制,以便按键驱逐和内存释放操作在后台线程中执行(配置lazyfree-lazy-eviction = yes);
持久化/配置影响
Fork 需要大量时间
操作 可以在Redis
并发送到 A Redis
背景RDB
和AOF重复写入
期间,您需要进行调查。在此期间可能会导致经济衰退。当Redis开放其起源rdb
和aof rewrite
时,在执行过程中,它们都需要自己的进程来创建数据持久化的方法。主进程创建子进程时,会调用操作系统提供的fork
。在fork
执行过程中,主进程需要将其内存页表复制给子进程
。如果这个案例很大,这个复制过程也会花费更多的时间。而这个fork
会消耗资源CPU
。在完成fork
之前,Redis
将被阻塞,无论客户端请求如何都无法处理。如果现在CPU
的资源已经很紧张的话,fork
会花费更长的时间,即使达到第二级,这确实会影响Redis的性能。 Redis
上运行命令INFO
,看到k_c单位,单位是微秒。
数据的持久化会生成
RDB
另外,当主从节点建立第一个数据同步时,Master也会创建第一个节点。 RDB 完整配置
从节点完成。因此,这一步会影响Redis
上的性能。
优化
- 控制
Redis
实例的内存:尝试以下的时间fork
与实例大小有关..推荐在非周末期间以及对数据丢失不敏感的公司进行备份。 (例如使用Redis作为纯缓存),您可以禁用AOF和AOF写入
。 Redis
不要把实例放在虚拟机中:fork
连接到系统也需要时间,♷比物理机本体需要更多
虚拟机。
发布主页
主页是什么?
我们都知道,当应用程序向操作系统请求内存时,会申请内存页,内存页的正常大小为4KB
。
Linux
从2.6.38
开始,内核支持
,内核支持 2.6.38。2MB
大小以单位为单位,向操作系统请求内存。应用程序在操作系统上使用的单位变得更大
,但这也意味着请求内存所需的时间增加。主进程fork子进程
后,当前主进程仍然可以接收写入请求,传入的写入请求将使用Copy On Write()数据。一旦主进程有数据需要修改,Redis不会直接修改内存中已有的数据。相反,它会先复制内存数据,然后修改新内存中的数据。您还可以获得写时复制,这意味着需要先复制需要写入的内容,然后再更改。注意,当主进程复制内存数据时,就可以申请新的内存了。如果现在正在运行Memory Huge Pages
,在此期间,即使更改了10B,‿,‿,‿,‿,‿,‿的数据, Re 也适用于组件 2MB
请求内存时的操作系统, 请求内存需要更长的时间
,这会导致每次请求结束。 Redis
性能。如果此写入请求在bigkey
上有效,则在复制此bigkey
时,内存将应用于内存。 ,时间会更长。 bigkey
似乎再次影响了这里的性能。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。

应用 AOF
AOF
配置始终为 appendfsync‾ Redis
每次发生写操作时,都会将其写入磁盘。还是那句话,整个过程都是在主线程中执行的,这个过程肯定会增加Redis
的写入负载。 aof
被制作为appendfsync no
,redis
redis❀单独写。由操作系统决定何时将数据从内存刷新到磁盘。 ,Redis
对性能的影响很小,但是当Redis
时,由于数据保护,部分数据会丢失。当 –♿ 断开连接时,
AOF
设置为 appendfsync everysec
–♿ ‶ AOF 当文件已满时,如果 则磁盘负载为 IT
很高,所以后台线程在做flash操作时会被阻塞(fsync系统通道)
。这时候主线程仍然会收到写请求,然后主线程需要将数据写入文件内存(写调用)
,但是现在子线程应该处于high状态磁盘负载,导致fsync阻塞
并且长时间无法恢复。当主线程执行系统调用
时,也会被阻塞,直到后台线程fsync
Print‾‾最后主执行‾
才能返回安全。
我总结了以下几种情况,大家可以参考排查:
- 子进程执行AOF重写,会占用大量IO磁盘资源;
- 还有其他应用程序进行大量编写。
Redis
的AOF
后台子线程刷操作打到子进程AA Redis
提供确认元素。当子进程处于AOF重写
时,无法进行磁盘刷新())这个和临时安装一样appendfsync
于 无在
期间,配置为:# AOF rewrite 期间,AOF 后台子线程不进行刷盘操作
# 相当于在这期间,临时把 appendfsync 设置为了 none
no-appendfsync-on-rewrite yes
发送到在AOF重写
期间,如果实例宕机,很多现在数据将丢失,性能和数据安全,您需要权衡各种选择。 碎片整理数据
Redis
存储在内存中。当我们的应用程序频繁更改 Redis
中的数据时,可能会导致 Redis
产生内存碎片。内存分区会减少Redis
的内存占用。我们可以通过执行命令 INFO
来获取本例中内存分配的比例: 
used_memory
表示 ❀ used_memory_rss
表示提供的大小由操作系统传递给进程Redis
。
mem_fragmentation_ratio
> 1.5,说明内存碎片率超过❿**50%**。现在我们需要采取措施减少内存碎片。 解决方法如下:
- 如果您使用的是
Redis 4.0
或以下版本,可以通过重启示例来解决Redis 4.0版本,它恰好提供了自动碎片整理功能。可以通过配置启用自动碎片整理。然而,启用内存碎片整理也会导致Redis
。
原因是Redis
的碎片整理操作也是在主线程中完成的。当它损坏时,就要消耗CPU
资源,导致消耗更多。时间,从而影响顾客的需求。
其他原因
- 频繁的短连接:您的业务应用程序应该使用长连接来运行Redis,以避免频繁的短连接。
- 其他程序争夺资源:其他程序占用CPU、内存和磁盘资源,留给Redis的资源不足。
总结
大家应该也注意到了,性能问题Redis
包含的知识点非常广泛,几乎涵盖了和内存、和 。 无论如何,同时需要了解计算机系统和操作系统的各个系统。
考虑到资源使用
,知识概念如下:
CPU
与CPU相关
内存
相关:申请与释放大内存、过期、数据删除、碎片整理、大内存页、写时复制内存与内存密切相关磁盘
延迟化、AOF磁盘扫描策略,也会影响磁盘
网络
相关:短期连接,例如流量太大,网络流量太大,降低性能 Redis 计算机 Sy CPU结构和内存分配是计算机系统最基本的知识
操作系统
:写时复制、主内存页、交换和CPU绑定都是操作系统级别的知识一些改进的建议
- 1。尝试使用短按键
当然,为了简化,不要为了“知道按键的名称和含义”而这样做。有些值还可以简化,比如性别用0和1。
- 2。请勿使用*
键*
。此命令是阻塞的,这意味着在执行该操作时,无法在您的实例上执行其他命令。当redis底层数据很小的时候还好,但是当数据很大的时候就真的很糟糕了。所以我们应该避免使用这个命令。您可以使用 SCAN 代替。
- 3。在将数据存储到 Redis 之前摄取数据 Redis 会针对不同情况自动调整适当的过滤方法。
- 4。设置有效期
应尽可能使用有效期。比如临时数据(短信验证码)过期了,Redis会自动帮你删除!
- 5。选择回滚策略(maxmemory策略)
当Redis实例空间满时,会尝试轮换一些key。根据您的使用情况,强烈建议使用 volatile-lru(默认)策略 - 如果您为密钥设置了时间限制。但如果你运行的是类似于缓存的东西,并且没有为key设置停止机制,你可以考虑使用allkeys-lru机制。参见详细解释。 maxmemory-samples 3 表示每次删除时,将随机选择 3 个键,并删除最不常用的键(默认选项)。
maxmemory-policy 六种方式 :
volatile-lru #只对设置了过期时间的key进行LRU(默认值)
allkeys-lru #是从所有key里 删除 不经常使用的key
volatile-random #随机删除即将过期key
allkeys-random #随机删除
volatile-ttl #删除即将过期的
noeviction #永不过期,返回错误
- 6。使用位级操作和字节级操作来减少不必要的内存使用
bit位级别操作:GETRANGE, SETRANGE, GETBIT and SETBIT
byte字节级别操作:GETRANGE and SETRANGE
- 7。尽可能使用哈希存储
- 8。当业务情况不需要数据持久化时,关闭所有持久化方法可以达到最佳性能。坚持不懈/成功。
- 9.当您想一次添加多个零件时,可以使用通道
- 10。限制redis内存大小(64位系统不限制内存,32位系统默认最多使用3GB内存)
如果redis数据量意外且内存有限,请尝试限制redis内存的使用size,这样可以防止redis使用交换分区或者OOM错误。 (使用交换分区,性能较低,如果内存有限,达到指定内存时无法添加数据,否则会报OOM错误。可以设置maxmemory-policy,内存不够的时候删除数据)
- 11。 SLOWLOG [get/reset/len]
slowlog-log-slower-than #它决定要对执行时间大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的命令进行记录。
slowlog-max-len #它决定 slowlog 最多能保存多少条日志,当发现redis性能下降的时候可以查看下是哪些命令导致的。
来源:https://blog.csdn.net/weixin_42128977/article/details/127622146
注意,当主进程复制内存数据时,就可以申请新的内存了。如果现在正在运行 这个和临时安装一样 发送到在AOF重写 原因是 大家应该也注意到了,性能问题 考虑到 当然,为了简化,不要为了“知道按键的名称和含义”而这样做。有些值还可以简化,比如性别用0和1。 应尽可能使用有效期。比如临时数据(短信验证码)过期了,Redis会自动帮你删除! 当Redis实例空间满时,会尝试轮换一些key。根据您的使用情况,强烈建议使用 volatile-lru(默认)策略 - 如果您为密钥设置了时间限制。但如果你运行的是类似于缓存的东西,并且没有为key设置停止机制,你可以考虑使用allkeys-lru机制。参见详细解释。 maxmemory-samples 3 表示每次删除时,将随机选择 3 个键,并删除最不常用的键(默认选项)。 如果redis数据量意外且内存有限,请尝试限制redis内存的使用size,这样可以防止redis使用交换分区或者OOM错误。 (使用交换分区,性能较低,如果内存有限,达到指定内存时无法添加数据,否则会报OOM错误。可以设置maxmemory-policy,内存不够的时候删除数据)Memory Huge Pages
,在此期间,即使更改了10B,‿,‿,‿,‿,‿,‿的数据, Re 也适用于组件
2MB
请求内存时的操作系统, 请求内存需要更长的时间
,这会导致每次请求结束。 Redis
性能。如果此写入请求在bigkey
上有效,则在复制此bigkey
时,内存将应用于内存。 ,时间会更长。 bigkey
似乎再次影响了这里的性能。更多学习Redis的文章请参见:NoSQL数据库系列-Redis。该系列定期更新。
应用 AOF
AOF
配置始终为 appendfsync‾ Redis
每次发生写操作时,都会将其写入磁盘。还是那句话,整个过程都是在主线程中执行的,这个过程肯定会增加Redis
的写入负载。 aof
被制作为appendfsync no
,redis
redis❀单独写。由操作系统决定何时将数据从内存刷新到磁盘。 ,
Redis
对性能的影响很小,但是当Redis
时,由于数据保护,部分数据会丢失。当 –♿ 断开连接时,
AOF
设置为 appendfsync everysec
–♿ ‶ AOF 当文件已满时,如果
才能返回安全。 则磁盘负载为 IT
很高,所以后台线程在做flash操作时会被阻塞(fsync系统通道)
。这时候主线程仍然会收到写请求,然后主线程需要将数据写入文件内存(写调用)
,但是现在子线程应该处于high状态磁盘负载,导致fsync阻塞
并且长时间无法恢复。当主线程执行系统调用
时,也会被阻塞,直到后台线程fsync
Print‾‾最后主执行‾我总结了以下几种情况,大家可以参考排查:
Redis
的AOF
后台子线程刷操作打到子进程AA
Redis
提供确认元素。当子进程处于AOF重写
时,无法进行磁盘刷新())
appendfsync
于 无在
期间,配置为:
表示提供的大小由操作系统传递给进程# AOF rewrite 期间,AOF 后台子线程不进行刷盘操作
# 相当于在这期间,临时把 appendfsync 设置为了 none
no-appendfsync-on-rewrite yes
期间,如果实例宕机,很多现在数据将丢失,性能和数据安全,您需要权衡各种选择。
碎片整理数据
Redis
存储在内存中。当我们的应用程序频繁更改 Redis
中的数据时,可能会导致 Redis
产生内存碎片。内存分区会减少Redis
的内存占用。我们可以通过执行命令 INFO
来获取本例中内存分配的比例: used_memory
表示 ❀ used_memory_rss Redis
。
mem_fragmentation_ratio
> 1.5,说明内存碎片率超过❿**50%**。现在我们需要采取措施减少内存碎片。 解决方法如下:
Redis 4.0
或以下版本,可以通过重启示例来解决Redis 4.0版本,它恰好提供了自动碎片整理功能。可以通过配置启用自动碎片整理。然而,启用内存碎片整理也会导致Redis
。 Redis
的碎片整理操作也是在主线程中完成的。当它损坏时,就要消耗CPU
资源,导致消耗更多。时间,从而影响顾客的需求。 其他原因
总结
Redis
包含的知识点非常广泛,几乎涵盖了和内存、和 。 无论如何,同时需要了解计算机系统和操作系统的各个系统。 资源使用
,知识概念如下: CPU
与CPU相关
内存
相关:申请与释放大内存、过期、数据删除、碎片整理、大内存页、写时复制内存与内存密切相关磁盘
延迟化、AOF磁盘扫描策略,也会影响磁盘
网络
相关:短期连接,例如流量太大,网络流量太大,降低性能 Redis Sy CPU结构和内存分配是计算机系统最基本的知识
操作系统
:写时复制、主内存页、交换和CPU绑定都是操作系统级别的知识一些改进的建议
键*
。此命令是阻塞的,这意味着在执行该操作时,无法在您的实例上执行其他命令。当redis底层数据很小的时候还好,但是当数据很大的时候就真的很糟糕了。所以我们应该避免使用这个命令。您可以使用 SCAN 代替。 maxmemory-policy 六种方式 :
volatile-lru #只对设置了过期时间的key进行LRU(默认值)
allkeys-lru #是从所有key里 删除 不经常使用的key
volatile-random #随机删除即将过期key
allkeys-random #随机删除
volatile-ttl #删除即将过期的
noeviction #永不过期,返回错误
bit位级别操作:GETRANGE, SETRANGE, GETBIT and SETBIT
byte字节级别操作:GETRANGE and SETRANGE
来源:https://blog.csdn.net/weixin_42128977/article/details/127622146 slowlog-log-slower-than #它决定要对执行时间大于多少微秒(microsecond,1秒 = 1,000,000 微秒)的命令进行记录。
slowlog-max-len #它决定 slowlog 最多能保存多少条日志,当发现redis性能下降的时候可以查看下是哪些命令导致的。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。