代码编织梦想

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38862257/article/details/128754595

Redis五大影响性能原因(一):Redis实例内部的阻塞操作-爱代码爱编程

思路: 1.建立一张redis主从切片集群图 ->-> 2.以一个切片节点为中心考虑其与周围节点会造成阻塞的情况 ->-> 3.对每一个阻塞情况考虑其是否是客户端需要的返回数据决定是否可以用异

redis学习笔记之阻塞篇_循环ing的博客-爱代码爱编程

1.内因: A.api或数据结构使用不合理: 如:对一个包含上万元素的hash结构执行hgetall操作,数据量大且命令复杂度O(n),必然阻塞 B.慢查询:前面有介绍 C.大对象: 执行./redis-cli -h {ip} -p {port} --bigkeys命令可找出当前最大对象出来,接着便可对大对象进行调整或缩减或分成多个小对象 生产环境可执行d

redis阻塞处理分析_shadow_zed的博客-爱代码爱编程

1.内因: A.api或数据结构使用不合理: 如:对一个包含上万元素的hash结构执行hgetall操作,数据量大且命令复杂度O(n),必然阻塞 B.慢查询:和很多关系型数据库(例如:MySQL)一样, Redis 也提供了慢查询日志记录,Redis 会把命令执行时间超过 slowlog-log-slower-than 的都记录在 Reids 内部的一个

php7.2 安装phpredis扩展,以及phpredis操作redis命令列表-爱代码爱编程

phpredis是redis的php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系;以下是redis官方提供的命令使用技巧: 下载安装地址如下: https://www.cnblogs.com/zzming/p/10018096.html 连接服务器操作 Redis::__construct构造函数 $red

Redis高性能原因解析——Redis内部的阻塞式操作及应对方法-爱代码爱编程

Redis被广泛使用的一个很重要的原因是它的高性能。因此我们必要要重视所有可能影响Redis性能的因素、机制以及应对方案。影响Redis性能的五大方面的潜在因素,分别是: Redis内部的阻塞式操作CPU核和NUMA架构的影响Redis关键系统配置Redis内存碎片Redis缓冲区本篇文章我们主要了解Redis内部的阻塞式操作以及应对方法。 Redis

redis线程阻塞原因排插_Redis高性能原因解析——Redis内部的阻塞式操作及应对方法...-爱代码爱编程

Redis被广泛使用的一个很重要的原因是它的高性能。因此我们必要要重视所有可能影响Redis性能的因素、机制以及应对方案。影响Redis性能的五大方面的潜在因素,分别是:Redis内部的阻塞式操作 CPU核和NUMA架构的影响 Redis关键系统配置 Redis内存碎片 Redis缓冲区 本篇文章我们主要了解Redis内部的阻塞式操作以及应对

php redis 堵塞请求,Redis阻塞问题排查-爱代码爱编程

Redis是一个单线程的架构,所有的操作全部都在一个主线程中完成。所以一旦Redis发生阻塞,那将是一场噩梦。接下来,我们就来看下对于Redis发生阻塞问题。如何排查以及解决。 Redis数据结构或API使用不合理 存在大对象且对大对象进行复杂的较高的命令 1、对一个有千万个元素的hash执行hgetall操作, 或del操作.类似的这种操作

02Redis的慢操作-爱代码爱编程

02Redis的慢操作 前言一、Redis数据类型的底层实现二、键和值的结构组织三、哈希表操作变慢的原因3.1、链式哈希3.2、rehash3.3、渐进式rehash四、集合类型数据操作效率五、集合类型的底层数据结构六、不同操作的复杂度总结 前言 为啥 Redis 能有这么突出的表现呢? Redis是内存数据库,所有操作都在内存上完成,内存

【Redis专题】redis阻塞情况--为什么阻塞?-爱代码爱编程

1、内部原因 (1)redis采用单线程处理请求,reactor是同步IO,需要等待命令执行完成,才会返回执行结果,然后进入下一个请求(队列) (2)持久化阻塞 fork阻塞: fork操作发生在rdb和aof重写时,redis主线程调用fork操作产生共享内存的子进程,由子进程完成持久化文件重写工作,若fork操作本身耗时过长,则必会导致主线程阻塞

redis的内部编码和数据结构类型-爱代码爱编程

1.redis原理 reids使用了单线程架构和I/O多路复用模型来实现性能的内存数据库服务 2.简化的工作流程 发送命令,执行命令,返回结果 3.单线程处理但处理快速的原因 纯内存访问非阻塞I/O,redis使用epoll作为I/O多路复用技术单线程避免了线程切换和竞态产生的消耗redis内部编码 1)string内部编辑 raw:大于的39个字

Redis 内部的阻塞式操作以及应对的方法。-爱代码爱编程

Redis 内部的阻塞式操作以及应对的方法 主线程阻塞Redis 实例有哪些阻塞点和客户端交互时的阻塞点和磁盘交互时的阻塞点主从节点交互时的阻塞点集群实例交互时的阻塞点 主线程阻塞 如果在主线程上执行的操作消耗的时间太长,就会引起主线程阻塞。但是,Redis 既有服务客户端请求的键值对增删改查操作,也有保证可靠性的持久化操作,还有进行主从复制

02 快速的Redis有哪些慢操作-爱代码爱编程

Redis 在查找数据速率方面特别突出,通常是微秒级别的查找操作。其中一方面的原因就得益于 Redis 属于的是内存数据库,内存的访问速率本身就很快;另一方面的原因在于其 Redis 中数据结构,对键值对的操作最终可以看作是对数据结构的增删改查操作。 一、Redis 中数据结构 Redis 中 Value 的数据类型有 String, List, Ha

redis有哪些慢操作?_鸨哥学java的博客-爱代码爱编程

Redis是否变慢了? 从业务服务器到Redis服务器这条调用链路中变慢的原因可能有2个 业务服务器到Redis服务器之间出现了网络问题,例如网络丢包,延迟比较严重Redis本身的执行出现问题,此时我们就需要排查Redis的问题 但是大多数情况下都是Redis服务的问题。但是应该如何衡量Redis变慢了呢?命令执行时间大于1s,大于2s?这其实并没有一

聊聊redis中有哪些阻塞点以及如何解决?_肥肥技术宅的博客-爱代码爱编程

Redis 中的优秀设计有很多,今天我们一起来聊聊群友刷题遇到的:“Redis的异步机制 —— redis有哪些阻塞点以及如何解决?” 前言 说到 Redis,大家自然而然的会想到基于内存、单线程执行等。话说回来,Redis 真的只有单线程吗?这篇文章来说说 Redis 的异步机制。 有哪些影响redis性能的因素 我们从 Redis 内部及外

redis中有哪些阻塞点以及如何解决_zninesun的博客-爱代码爱编程

我们从 Redis 内部及外部因素总结一下有哪些会影响redis性能的因素。 可能会导致Redis实例产生阻塞点的情况: 客户端:网络 IO,键值对的增删改查操作,数据库操作;磁盘:生成 RDB 快照,记录 AOF 日志