一、为什么这么快?
Redis使用单线程模型会达到每秒万级别的处理能力呢?可以将其归结为三点:
-
纯内存访问,Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,这是Redis达到每秒万级别访问的重要基础。
-
非阻塞I/O,Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间。
-
单线程避免了线程切换和竞态产生的消耗。
单线程会有一个问题:对于每个命令的执行时间是有要求的。
如果某个命令执行过长,会造成其他命令的阻塞,对于Redis这种高性能的服务来说是致命的,所以Redis是面向快速执行场景的数据库。
二、Redis的噩梦,阻塞
当Redis阻塞时,线上应用服务应该最先感知到,这时应用方会收到大量Redis超时异常。常见的做法是在应用方加入异常统计并通过邮件/短信/电话等报警,以便及时发现通知问题。
阻塞原因分析
1. API或数据结构
通常Redis执行命令速度非常快,但也存在例外,如对一个包含上万个元素的hash结构执行hgetall操作,由于数据量比较大且命令算法复杂度是 O(n),这条命令执行速度必然很慢。这个问题就是典型的不合理使用API和数据结构。对于高并发的场景我们应该尽量避免在大对象上执行算法复杂度超过O(n)的命令。
如何发现慢查询
slowlog get {n}命令可以获取最近的n条慢查询命令。
慢查询日志配置
slowlog-log-slower-than和slowlog-max-len配置来解决这两个问题。从字面意思就可以看出,slowlog-log-slower-than就是那个预设阀值, 它的单位是微秒(1秒=1000毫秒=1000000微秒),默认值是10000。 slowlog-log-slower-than=0会记录所有的命令,slowlog-log-slower- than<0对于任何命令都不会进行记录。慢查询队列长度默认128,可适当调大。
Redis客户端执行一条命令分为如下4个部分:
1)发送命令 2)命令排队 3)命令执行 4)返回结果 其中1)+4)称为Round Trip Time(RTT,往返时间) 慢查询只统计步骤3)的时间,因此客户端发生阻塞异常后,可能不是当前命令缓慢,而是在等待其他命令执行。需要重点比对异常和慢查询发生的时间点,确认是否有慢查询造成的命令阻塞排队。
调整方向
-
修改为低算法度的命令,如hgetall改为hmget等,禁用keys、sort等命令。
-
调整大对象,缩减大对象数据或把大对象拆分为多个小对象,防止一次命令操作过多的数据。
如何发现大对象
bigkey的危害体现在三个方面:
-
内存空间不均匀(平衡):例如在Redis Cluster中,bigkey会造成节点的内存空间使用不均匀
-
超时阻塞:由于Redis单线程的特性,操作b

本文分析了Redis变慢的常见原因,包括大对象、CPU饱和、持久化阻塞、过期Key集中、网络问题及内存交换。提出了优化建议,如避免大Key、设置过期时间、限制命令复杂度、使用批量操作和读写分离,以提高Redis性能和稳定性。
最低0.47元/天 解锁文章
1064

被折叠的 条评论
为什么被折叠?



