影响redis性能的一些潜在因素

news2024/7/6 19:34:51

影响 Redis 性能的 5 大方面的潜在因素,分别是:
Redis 内部的阻塞式操作;
CPU 核和 NUMA 架构的影响;
Redis 关键系统配置;
Redis 内存碎片;
Redis 缓冲区

先学习了解下 Redis 内部的阻塞式操作以及应对的方法。

Redis 实例有哪些阻塞点?
Redis 实例在运行时,要和许多对象进行交互,这些不同的交互就会涉及不同的操作,下面我们来看看和 Redis 实例交互的对象,以及交互时会发生的操作。
客户端:网络 IO,键值对增删改查操作,数据库操作;(主线程)
磁盘:生成 RDB 快照,记录 AOF 日志,AOF 日志重写;
主从节点:主库生成、传输 RDB 文件,从库接收 RDB 文件、清空数据库、加载 RDB 文件;
切片集群实例:向其他实例传输哈希槽信息,数据迁移。

客户端阻塞点:
网络 IO 有时候会比较慢,但是 Redis 使用了 IO 多路复用机制,避免了主线程一直处在等待网络连接或请求到来的状态,所以,网络 IO 不是导致 Redis 阻塞的因素。
键值对的增删改查操作是 Redis 和客户端交互的主要部分,也是 Redis 主线程执行的主要任务。所以,复杂度高的增删改查操作肯定会阻塞 Redis。
那么,怎么判断操作复杂度是不是高呢?这里有一个最基本的标准,就是看操作的复杂度是否为 O(N)。
Redis 中涉及集合的操作复杂度通常为 O(N),我们要在使用时重视起来。例如集合元素全量查询操作 HGETALL、LRANGE,SMEMBERS,以及集合的聚合统计操作,例如求交、并和差集。这些操作可以作为 Redis 的第一个阻塞点:集合全量查询和聚合操作。

除此之外,集合自身的删除操作同样也有潜在的阻塞风险。
其实,删除操作的本质是要释放键值对占用的内存空间。你可不要小瞧内存的释放过程。释放内存只是第一步,为了更加高效地管理内存空间,在应用程序释放内存时,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配。这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序,所以,如果一下子释放了大量内存,空闲内存块链表操作时间就会增加,相应地就会造成 Redis 主线程的阻塞。
那么,什么时候会释放大量内存呢?其实就是在删除大量键值对数据的时候,最典型的就是删除包含了大量元素的集合,也称为 bigkey 删除

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

和磁盘交互时的阻塞点
Redis 开发者早已认识到磁盘 IO 会带来阻塞,所以就把 Redis 进一步设计为采用子进程的方式生成 RDB 快照文件,以及执行 AOF 日志重写操作。这样一来,这两个操作由子进程负责执行,慢速的磁盘 IO 就不会阻塞主线程了。
但是,Redis 直接记录 AOF 日志时,会根据不同的写回策略对数据做落盘保存。一个同步写磁盘的操作的耗时大约是 1~2ms,如果有大量的写操作需要记录在 AOF 日志中,并同步写回的话,就会阻塞主线程了。这就得到了 Redis 的第四个阻塞点了:AOF 日志同步写。

主从节点交互时的阻塞点
在主从集群中,主库需要生成 RDB 文件,并传输给从库。主库在复制的过程中,创建和传输 RDB 文件都是由子进程来完成的,不会阻塞主线程。
但是,对于从库来说,它在接收了 RDB 文件后,需要使用 FLUSHDB 命令清空当前数据库,这就正好撞上了刚才我们分析的第三个阻塞点(删除大量数据bigkey)。
此外,从库在清空当前数据库后,还需要把 RDB 文件加载到内存,这个过程的快慢和 RDB 文件的大小密切相关,RDB 文件越大,加载过程越慢,所以,加载 RDB 文件就成为了 Redis 的第五个阻塞点。

切片集群实例交互时的阻塞点
最后,当我们部署 Redis 切片集群时,每个 Redis 实例上分配的哈希槽信息需要在不同实例间进行传递,同时,当需要进行负载均衡或者有实例增删时,数据会在不同的实例间进行迁移。不过,哈希槽的信息量不大,而数据迁移是渐进式执行的,所以,一般来说,这两类操作对 Redis 主线程的阻塞风险不大。
不过,如果你使用了 Redis Cluster 方案,而且同时正好迁移的是 bigkey 的话,就会造成主线程的阻塞,因为 Redis Cluster 使用了同步迁移。你只需要知道,当没有 bigkey 时,切片集群的各实例在进行交互时不会阻塞主线程,就可以了。

五个阻塞点:
集合全量查询和聚合操作;
bigkey 删除;
清空数据库;
AOF 日志同步写;
从库加载 RDB 文件

如果在主线程中执行这些操作,必然会导致主线程长时间无法服务其他请求。为了避免阻塞式操作,Redis 提供了异步线程机制。所谓的异步线程机制,就是指,Redis 会启动一些子线程,然后把一些任务交给这些子线程,让它们在后台完成,而不再由主线程来执行这些任务。使用异步线程机制执行操作,可以避免阻塞主线程。
不过,这个时候,问题来了:这五大阻塞式操作都可以被异步执行吗?
对于 Redis 的五大阻塞点来说,除了“集合全量查询和聚合操作”和“从库加载 RDB 文件”,其他三个阻塞点涉及的操作都不在关键路径上,所以,我们可以使用 Redis 的异步子线程机制来实现 bigkey 删除,清空数据库,以及 AOF 日志同步写。
那么,Redis 实现的异步子线程机制具体是怎么执行呢?
异步的子线程机制
Redis 主线程启动后,会使用操作系统提供的 pthread_create 函数创建 3 个子线程,分别由它们负责 AOF 日志写操作、键值对删除以及文件关闭的异步执行。
在这里插入图片描述
键值对删除:当你的集合类型中有大量元素(例如有百万级别或千万级别元素)需要删除时,我建议你使用 UNLINK 命令。(unlink是指redis用异步方式去del键值,但是异步删除键值有一个判断条件.会根据元素的个数来判断是否值得用异步线程去del,因为异步会有额外的消耗,如果元素较少(比如string,无论string多大都是在主线程里删除),直接在主线程里删除就行.)
清空数据库:可以在 FLUSHDB 和 FLUSHALL 命令后加上 ASYNC 选项,这样就可以让后台子线程异步地清空数据库,如下所示:
FLUSHDB ASYNC
FLUSHALL AYSNC

为什么CPU结构也会影响Redis的性能?
一个CPU处理器中一般有多个运行核心,我们把一个运行核心称为一个物理核,每个物理核都可以运行应用程序。每个物理核都拥有私有的一级缓存(Level 1 cache,简称L1 cache),包括一级指令缓存和一级数据缓存,以及私有的二级缓存(Level 2 cache,简称L2 cache)。

在这里插入图片描述
不同的物理核还会共享一个共同的三级缓存(Level 3 cache,简称为L3 cache)。L3缓存能够使用的存储资源比较多,所以一般比较大,能达到几MB到几十MB,这就能让应用程序缓存更多的数据。当L1、L2缓存中没有数据缓存时,可以访问L3,尽可能避免访问内存。
另外,现在主流的CPU处理器中,每个物理核通常都会运行两个超线程,也叫作逻辑核。同一个物理核的逻辑核会共享使用L1、L2缓存。

在这里插入图片描述
同时,为了提升服务器的处理能力,服务器上通常还会有多个CPU处理器(也称为多CPU Socket),每个处理器有自己的物理核(包括L1、L2缓存),L3缓存,以及连接的内存,同时,不同处理器间通过总线连接。
在这里插入图片描述
在多CPU架构下,一个应用程序访问所在Socket的本地内存和访问远端内存的延迟并不一致,所以,我们也把这个架构称为非统一内存访问架构(Non-Uniform Memory Access,NUMA架构)。

CPU多核对Redis性能的影响
在一个CPU核上运行时,应用程序需要记录自身使用的软硬件资源信息(例如栈指针、CPU核的寄存器值等),我们把这些信息称为运行时信息。同时,应用程序访问最频繁的指令和数据还会被缓存到L1、L2缓存上,以便提升执行速度。
但是,在多核CPU的场景下,一旦应用程序需要在一个新的CPU核上运行,那么,运行时信息就需要重新加载到新的CPU核上。而且,新的CPU核的L1、L2缓存也需要重新加载数据和指令,这会导致程序的运行时间增加。
如果在CPU多核场景下,Redis实例被频繁调度到不同CPU核上运行的话,那么,对Redis实例的请求处理时间影响就更大了。每调度一次,一些请求就会受到运行时信息、指令和数据重新加载过程的影响,这就会导致某些请求的延迟明显高于其他请求。分析到这里,我们就知道了刚刚的例子中99%尾延迟的值始终降不下来的原因。
所以,我们要避免Redis总是在不同CPU核上来回调度执行。于是,我们尝试着把Redis实例和CPU核绑定了,让一个Redis实例固定运行在一个CPU核上。我们可以使用taskset命令把一个程序绑定在一个核上运行。
比如说,我们执行下面的命令,就把Redis实例绑在了0号核上,其中,“-c”选项用于设置要绑定的核编号。
taskset -c 0 ./redis-server

CPU的NUMA架构对Redis性能的影响
那么,在CPU的NUMA架构下,当网络中断处理程序、Redis实例分别和CPU核绑定后,就会有一个潜在的风险:如果网络中断处理程序和Redis实例各自所绑的CPU核不在同一个CPU Socket上,那么,Redis实例读取网络数据时,就需要跨CPU Socket访问内存,这个过程会花费较多时间。
在这里插入图片描述

为了避免Redis跨CPU Socket访问网络数据,我们最好把网络中断程序和Redis实例绑在同一个CPU Socket上,这样一来,Redis实例就可以直接从本地内存读取网络数据了。不过,需要注意的是,在CPU的NUMA架构下,对CPU核的编号规则,并不是先把一个CPU Socket中的所有逻辑核编完,再对下一个CPU Socket中的逻辑核编码,而是先给每个CPU Socket中每个物理核的第一个逻辑核依次编号,再给每个CPU Socket中的物理核的第二个逻辑核依次编号。

Redis除了主线程以外,还有用于RDB生成和AOF重写的子进程。
当我们把Redis实例绑到一个CPU逻辑核上时,就会导致子进程、后台线程和Redis主线程竞争CPU资源,一旦子进程或后台线程占用CPU时,主线程就会被阻塞,导致Redis请求延迟增加。

虽然绑核可以帮助Redis降低请求执行时间,但是,除了主线程,Redis还有用于RDB和AOF重写的子进程,以及4.0版本之后提供的用于惰性删除的后台线程。当Redis实例和一个逻辑核绑定后,这些子进程和后台线程会和主线程竞争CPU资源,也会对Redis性能造成影响。所以,我给了你两个建议:

如果你不想修改Redis代码,可以把按一个Redis实例一个物理核方式进行绑定,这样,Redis的主线程、子进程和后台线程可以共享使用一个物理核上的两个逻辑核。(只能是缓解)
如果你很熟悉Redis的源码,就可以在源码中增加绑核操作,把子进程和后台线程绑到不同的核上,这样可以避免对主线程的CPU资源竞争。不过,如果你不熟悉Redis源码,也不用太担心,Redis 6.0出来后,可以支持CPU核绑定的配置操作了。

那么redis变慢因素的排查?
1**、获取Redis实例在当前环境下的基线性能。**
所谓的基线性能呢,也就是一个系统在低压力、无干扰下的基本性能,这个性能只由当前的软硬件配置决定。redis-cli命令提供了–intrinsic-latency选项,可以用来监测和统计测试期间内的最大延迟,这个延迟可以作为Redis的基线性能。
./redis-cli --intrinsic-latency 120
一般来说,你要**把运行时延迟和基线性能进行对比,如果你观察到的Redis运行时延迟是其基线性能的2倍及以上,就可以认定Redis变慢了。**比如虚拟机因为虚拟化软件层开销,基线性能差一点,10ms左右。

**是否用了慢查询命令?**如果是的话,就使用其他命令替代慢查询命令,或者把聚合计算命令放在客户端做。比如把smemebers换成sscan,多次返回避免阻塞。比如SORT、SUNION、SINTER聚合范围计算放在客户端。
slowlog get 10

是**否对过期key设置了相同的过期时间?**你要检查业务代码在使用EXPIREAT命令设置key过期时间时,是否使用了相同的UNIX时间戳。对于批量删除的key,可以在每个key的过期时间上加一个随机数,避免同时删除。

是否存在bigkey? 对于bigkey的删除操作,如果你的Redis是4.0及以上的版本,可以直接利用异步线程机制减少主线程阻塞;如果是Redis 4.0以前的版本,可以使用SCAN命令迭代删除;对于bigkey的集合查询和聚合操作,可以使用SCAN命令在客户端完成。

AOF 日志同步写(alaways);从库加载 RDB 是不能异步的,肯定阻塞。Redis AOF配置级别是什么?业务层面是否的确需要这一可靠性级别?如果我们需要高性能,同时也允许数据丢失,可以将配置项no-append fsync-on-rewrite设置为yes,避免AOF重写和fsync竞争磁盘IO资源,导致Redis延迟增加。当然, 如果既需要高性能又需要高可靠性,最好使用高速固态盘作为AOF日志的写入盘。

**Redis实例的内存使用是否过大?****发生swap了吗?**如果是的话,就增加机器内存,或者是使用Redis集群,分摊单机Redis的键值对数量和内存压力。同时,要避免出现Redis和其他内存需求大的应用共享机器的情况。
$ redis-cli info | grep process_id查看进程号, $ cd /proc/5332 $cat smaps | egrep ‘^(Swap|Size)’ 当出现百MB,甚至GB级别的swap大小时,就表明,此时,Redis实例的内存压力很大,很有可能会变慢。

**在Redis实例的运行环境中,是否启用了透明大页机制?**如果是的话,直接关闭内存大页机制就行了。Linux内核从2.6.38开始支持内存大页机制,该机制支持2MB大小的内存页分配,而常规的内存页分配是按4KB的粒度来执行的。
虽然内存大页可以给Redis带来内存分配方面的收益,但是,不要忘了,Redis为了提供数据可靠性保证,需要将数据做持久化保存。这个写入过程由额外的线程执行,所以,此时,Redis主线程仍然可以接收客户端写请求。客户端的写请求可能会修改正在进行持久化的数据。在这一过程中,Redis就会采用写时复制机制,也就是说,一旦有数据要被修改,Redis并不会直接修改内存中的数据,而是将这些数据拷贝一份,然后再进行修改。
如果采用了内存大页,那么,即使客户端请求只修改100B的数据,Redis也需要拷贝2MB的大页。相反,如果是常规内存页机制,只用拷贝4KB

是否运行了Redis主从集群?如果是的话,把主库实例的数据量大小控制在2~4GB,以免主从复制时,从库因加载大的RDB文件而阻塞。

是否使用了多核CPU或NUMA架构的机器运行Redis实例?使用多核CPU时,可以给Redis实例绑定物理核;使用NUMA架构时,注意把Redis实例和网络中断处理程序运行在同一个CPU Socket上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/393937.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据架构系列-03】数据仓库、大数据平台、数据中台... 我不太认同《DataFun数据智能知识地图》中的定义

关注DataFunTalk有2年多了,DataFun确实像创始人王大川讲的那样,践行选择、努力和利他原则,专注于大数据、人工智能技术应用的分享与交流,秉承着开源开放的精神,免费的共享了很多有营养的行业实践专业知识,对…

1.win10环境搭建Elasticsearch7.2.0环境

环境介绍jdk1.8安装Elasticsearch7.2.0下载安装包直接解压进入到bin目录,双击elasticsearch.bates启动成功访问http://localhost:9200/jdk版本1.8,很有可能因为jdk版本的问题es启动失败支持连接https://www.elastic.co/cn/support/matrix#matrix_jvm安装Kibana7.2.0…

云计算介绍,让你更了解云计算

同学们好! 第一次接触IT行业吗?没关系,看完这篇文章肯定会让你不再陌生。给自己几分钟时间,认真看完哦! 1、不知道什么是云计算? 网络计算云计算 官方定义是:通过网络提供可伸缩的分布式计算…

建立相关在线社群的3个简单步骤

在线社群管理和社交媒体营销通常被视为一回事。虽然社群管理确实是社交媒体营销的一个关键部分,但它的意义超越了社交媒体的内容发布。因此,在线社群对于企业的数字营销十分重要。创建、维护和发展社群不是一件容易的工作,也不是一个快速的过…

枚举学习贴

1. 概述 1.1 是什么 枚举对应英文(enumeration, 简写 enum)枚举是一组常量的集合。可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象 1.2 枚举的二种实现方式 自定义类实现枚举使用 enum 关键字实现枚举 1.3 什么时候用 存在有限…

利用HGT聚类单细胞多组学数据并推理生物网络

单细胞多组学数据允许同时对多种组学数据进行定量分析,以捕捉复杂的分子机制和细胞异质性。然而现有的工具不能有效地推断不同细胞类型的活性生物网络以及这些网络对外部刺激的反应。 来自:Single-cell biological network inference using a heterogen…

操作系统_Linux_问答_2023_自用

GeeksforGeeks(https://www.geeksforgeeks.org/):GeeksforGeeks是一个技术学习平台,它提供了广泛的操作系统知识,包括操作系统概念、进程管理、内存管理、文件系统等内容。IBM Developer(https://developer…

代理模式-大话设计模式

一、定义 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 著名的代理模式例子为引用计数(英语…

如何基于AI智能视频技术实现公园景区的人流量实时统计?

一、方案背景春暖花开的季节来临,外出旅游的人群也越来越多。无论是景区、公园、博物馆、步行街等场所,客流超载非常大,给游客带来的体验较差,同时也存在安全隐患。当前景区面临的管理痛点包括:客流信息查询难&#xf…

Hadoop3.1.3单机(伪分布式配置)

参考:林子雨老师网站博客 Hadoop安装搭建伪分布式教程(全面)吐血整理 环境 Vmare12 Ubuntu16.04 创建Hadoop用户 若安装Ubuntu不是用的“hadoop”用户,则需要增加一个名为"hadoop"的用户 直接快捷键ctrlaltt或者点…

【C语言督学训练营 第二天】C语言中的数据类型及标准输入输出

文章目录一、前言二、数据类型1.基本数据类型①.整形②.浮点型③.字符型2.高级数据类型3.数据分类①.常量②.变量三、标准输入输出1.scanf2.printf四、进制转换1.进制转换简介2.十进制转其他进制3.其他进制转换五、OJ网站的使用一、前言 王道2024考研408C语言督学营第二天&…

公安室内射击场设计

公安室内射击场是为了训练和提高警察、特警、部队等职业人士的射击技能而设计的。其设计需要考虑的因素包括安全性、实用性、灵活性、耐久性等多个方面。下面将详细介绍公安室内射击场的设计要点。 首先,安全性是设计公安室内射击场的最重要因素之一。射击场应该具备…

杂记——19.git上传时出现the remote end hung up unexpectedly错误

git是大家常用的项目版本控制工具,熟练地使用git可以提高开发效率,但是有时在使用git推送代码时,会提示“the remote end hung up unexpectedly”的问题,那么git推送代码提示“the remote end hung up unexpectedly”怎么解决呢&a…

Java多线程还不会的进来吧,为你量身打造

💗推荐阅读文章💗 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》🌺MySQL系列🌺👉2️⃣《MySQL系列教程》🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》…

Anaconda的安装及使用

Anaconda集成了常用的扩展包,能够方便地对这些扩展包进行管理,比如安装和卸载包,这些操作都需要依赖conda。conda是一个在Windows、Mac OS和Linux上运行的开源软件包管理系统和环境管理系统,可以快速地安装、运行和更新软件包及其…

升压模块直流隔离低压转高压稳压电源5v12v24v转50V100V110V150V200V250V400V500V600V800V1000V

特点效率高达80%以上1*2英寸标准封装单电压输出价格低稳压输出工作温度: -40℃~85℃阻燃封装,满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRB W2~40W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为:4.5~9V、9~18V、及18~36VDC标准&…

计算机网络--网络基础

目录 一.互联网的组成 ​编辑 1.互联网的边缘部分 1.1客户-服务器方式 1.2对等连接方式 ​编辑 2.互联网的核心部分 2.1电路交换 2.2分组交换 2.3报文交换 二.计算机网络的类别 1.按网络的作用范围进行分类 2.按网络的使用者进行分类 3.用来把用户接入互联…

I.MX6ULL_Linux_系统篇(23) busybox文件系统构建

Linux“三巨头”已经完成了 2 个了,就剩最后一个 rootfs(根文件系统)了,本章我们就来学习一下根文件系统的组成以及如何构建根文件系统。这是 Linux 移植的最后一步,根文件系统构建好以后就意味着我们已经拥有了一个完整的、可以运行的最小系…

零代码工具我推荐Oracle APEX

云原生时代零代码工具我推荐Oracle APEX 国内的低码开发平台我也看了很多,感觉还是不太适合我这个被WEB抛弃的老炮。自从看了Oracle APEX就不打算看其它的了。太强大了,WEB服务器都省了,直接数据库到WEB页面。功能很强大,震撼到我…

快速将小程序生成APP八步走!

在开始之前,让我们一起来了解一下Finclip吧! Finclip是凡泰极客公司研发的一款在开发体验、学习门槛、应用场景、生态能力等方面都体现巨大优势的小程序容器。不论是移动APP,还是电脑、电视、车载主机等设备,在集成Finclip小程序…