Redis性能排查调优
Redis性能排查调优
Redis执行命令变慢的原因
1. 网络问题
2. 业务问题
设置慢日志阈值,开启慢日志slowLog
2.1 命令复杂度过高
- 经常使用
O(N)以上复杂度的命令,例如SORT、SUNION、ZUNIONSTORE聚合类命令 - 使用
O(N) 复杂度的命令,但N的值非常大
解决方法:
- 尽量不使用
O(N)以上复杂度过高的命令,对于数据的聚合操作,放在客户端做 - 执行
O(N)命令,保证N尽量的小(推荐N <= 300),每次获取尽量少的数据,让 Redis 可以及时处理返回
2.2 bigkey
- 避免写入bigkey
- bigkey分为多个小key
2.3 集中过期
大量key同时过期,过期删除策略定期删除过期的key,如果有很多key同时过期,就会一直处于删除状态,该操作在执行命令之前执行,因此慢日志也看不出来(redis4.0之后的版本可以开启 lazy-free,将过期删除操作放到后台线程去执行)
2.4 内存淘汰
内存不够用了,写入新数据之前需要淘汰老数据,这就和内存淘汰策略的耗时有关了,其中随机淘汰效率最高
3. 运维问题
3.1 RDB、AOF日志
rdb、aof持久化时都需要主进程fork一个子进程去执行,这个fork的过程中主进程需要拷贝自己的内存页表给子进程,如果实例很大,拷贝的过程也会很长时间耗时
3.2 使用Swap虚拟内存
Redis遵循 key-value模型。同时key和value通常都存储在内存中。然而有时这并不是一个最好的选择,所以在设计过程中我们要求key必须存储在内存中(为了保证快速查找),而value在很少使用时,可以从内存被交换出至磁盘上。 实际应用中,如果内存中有一个10万条记录的key值数据集,而只有10%被经常使用,那么开启虚拟内存的Redis将把与较少使用的key相对应的value转移至磁盘上。当客户端请求获取这些value时,他们被将从swap 文件中读回,并载入到内存中。从磁盘中读取速度肯定会慢很多。
预留更多的空间,避免使用 swap
3.3 内存碎片
Redis 的数据都存储在内存中,当我们的应用程序频繁修改 Redis 中的数据时,就有可能会导致 Redis 产生内存碎片(比如当一个key过期后,其占用的内存空间会被释放,如果这份释放的空间无法被新数据填满,就会出现内存碎片)。
碎片化的内存空间无法得到有效利用,即使总的剩余内存充足,但由于碎片的存在,可能导致新数据无法找到足够大的连续空闲空间进行分配,从而引发“内存不足”的假象,迫使 Redis 进行不必要的数据淘汰或触发 swap。
Redis4.0之后可以开启内存碎片自动整理,但是由于碎片整理工作也是在主线程中执行的,所以碎片整理也可能会导致redis性能下降