Redis内部的阻塞式操作以及应对方法

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Redis之所以被广泛应用很重要的一个原因就是它支持高性能访问也正因为这样我们必须要重视所有可能影响Redis性能的因素不仅要知道具体的机制尽可能避免异常的情况出现还要提前准备好应对异常的方案。

所以介绍一下影响Redis性能的5大方面的潜在因素分别是

  • Redis内部的阻塞式操作
  • CPU核和NUMA架构的影响
  • Redis关键系统配置
  • Redis内存碎片
  • Redis缓冲区。

这篇笔记我们先学习Redis内部的阻塞式操作以及应对的方法。

Redis的网络IO和键值对读写是由主线程完成的。那么如果在主线程上执行的操作消耗的时间太长就会引起主线程阻塞但是Redis既有服务客户端的请求的键值对增删改查操作也有保证可靠性的持久化操作还有进行主从复制时的数据同步操作等等这么多操作究竟哪些会引起阻塞呢

接下来我们分门别类地梳理下这些操作并且找出阻塞式操作。

Redis实例有哪些阻塞点

Redis实例在运行时要和许多对象进行交互这些不同的交互就会涉及不同的操作下面我们来看看和Redis实例交互的对象以及交互时会发生的操作。

  • 客户端网络IO键值对增删改查操作数据库操作。
  • 磁盘生产RDB快照记录AOF日志AOF日志重写
  • 主从节点主库生成、传输RDB文件从库接收RDB文件、清空数据库、加载RDB文件
  • 切片集群实例向其他实例传输哈希槽信息数据迁移。

为了帮你理解我再画一张图来展示这4类交互对象你和具体操作之间的关系。

image

接下来我们来逐个分析下在这些交互对象中有哪些操作会引起阻塞。

1.和客户端交互时的阻塞点

网络IO有时候会比较慢但是Redis使用了IO多路复用机制避免了主线程一直处于等待网络连接或请求到来的状态所以网络IO不是导致Redis阻塞的因素。

键值对的增删改查操作是Redis和客户端交互的主要部分也是Redis主线程执行的主要任务所以复杂度高的增删改查肯定会阻塞Reids

那么怎么判断操作复杂度是不是高呢这里有一个最基本的标准就是看操作的复杂度是否为O(N)。

Redis中涉及集合的操作复杂度通常为O(N)我们要在使用时重视起来例如集合元素全量查询操作HGETALL、SMEMBERS以及集合的聚合统计操作例如求交、并和差集。这些操作可以作为Redis的第一个阻塞点集合全量查询和聚合操作

除此之外集合自身的删除操作同样也有潜在的阻塞风险你可能会认为删除操作很简单直接把数据删除就好了为什么还会阻塞主线程呢

其实删除操作的本质是要释放键值对占用的内存空间你可不要小瞧内存的释放过程释放内存只是第一步为了更加高效地管理内存空间在应用程序释放内存时操作系统需要把释放掉的内存块插入一个空闲内存块的链表以便后续进行管理和再分配。这个过程本身需要一定时间而且会阻塞当前释放内存的应用程序所以如果一下子释放了大量内存空闲内存链表操作时间就会增加相应地就会造成Redis主线程的阻塞。

那么什么时候会释放大量内存空间呢其实就是大量删除键值对数据的时候最典型的就是删除包含了大量元素的集合也称为bigkey删除为了让你对bigkey的删除性能有一个直观的印象我测试了不同元素数量的集合在进行删除操作时所消耗的时间如下
image

从这张表里我们可以得出三个结论

  1. 当元素数量从10万增加到100万时4大集合类型的删除时间的增长幅度从5倍上升到了近20倍
  2. 集合元素越大删除所花费的时间就越长
  3. 当删除有100万个元素的集合时最大的删除时间绝对值已经达到了1.98s。Redis的响应时间一般在微秒级别所以一个操作达到了近2秒不可避免地会阻塞主线程。

经过刚刚的分析很显然bigkey删除操作就是Redis的第二个阻塞点。删除操作对Redis实例性能的负面影响很大而且在实际业务开发时很容易被忽略所以一定要重视它。

既然频繁删除键值对都是潜在的阻塞点了那么在Redis的数据库级别操作中清空数据库必然也是一个潜在的阻塞风险点因为它涉及删除和释放所有的键值对所以这就是Redis的第三个阻塞点清空数据库

2. 和磁盘交互时的阻塞点

我之所以把Redis与磁盘的交互单独列为一类主要是因为磁盘IO一般都是比较费时费力的需要重点关注。

幸运的是Redis开发者早已认识到磁盘IO会带来阻塞所以把Redis进一步设计为采用子进程的方式生成RDB快照文件以及执行AOF日志重写操作这样一来这两个操作由子进程负责执行慢速的磁盘IO就不会阻塞主线程了。

但是Redis直接记录AOF日志时会根据不同的写回策略对数据做落盘保存一个同步写磁盘的操作的耗时大约是1~2ms如果有大量的写操作需要记录在AOF日志中并同步写回的话就会阻塞主线程了这就得到了Redis的第四个阻塞点了AOF日志同步写

3.主从节点交互时的阻塞点

在主从集群中主库需要生成RDB文件并传输给从库主库在复制的过程中创建和传输RDB文件都是由子进程来完成的不会阻塞主线程但是对于从库来说它在接收RDB文件后需要使用FLUSHDB命令清空当前数据库这就正好撞上了刚才我们分析的第三个阻塞点。

此外从库在清空当前数据库后还需要把RDB文件加载到内存这个过程的快慢和RDB文件的大小密切相关RDB文件越大加载过程越慢所以加载RDB文件就成为了Redis的第五个阻塞点

4.切片集群实例交互时的阻塞点

最后当我们部署Redis切片集群时每个Redis实例上分配的哈希槽信息需要在不同实例间进行传递同时当需要进行负载均衡或者有实例增删时数据会在不同的实例间进行迁移不过哈希槽的信息量不大而数据迁移是渐进式执行的所以一般来说这两类操作对Redis主线程的阻塞风险不大。

不过当你使用了Redis Cluster方案而且同时正好迁移的是bigkey的话就会造成主线程的阻塞因为Redis Cluster使用了同步迁移。

学习来源极客时间 《Redis核心技术与实战》学习笔记 Day08

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: redis