Redis核心技术与实战【学习笔记】 - 28.Redis 6.0新特性(多线程、客户端缓存与安全)

简述

Redis 6.0 新增了几个关键新特性,分别是面向网络处理的多 IO 线程、客户端缓存、细粒度的权限控制,以及 RESP 3 协议的使用。

其中,面向网络处理的多 IO 线程可以提高网络请求处理的速度,而客户端缓存可以让应用直接在客户端本地读取数据,这两个特性可以提升 Redis 的性能。除此之外,细粒度权限控制让 Redis 可以按照命令粒度控制不同用户的访问权限,加强了 Redis 的安全保护。RESP 3 协议则增强客户端的功能,可以让应用更加方便地使用 Redis 的不同数据类型。


1.从单线程处理网络请求到多线程处理

Redis 6.0 中,非常受关注的第一个特性就是多线程。Redis 一直被大家熟知的就是它的单线程架构,虽然有些命令可以用后台线程或子进程执行(比如数据删除、快照生成、AOF 重写),但是,从网络 IO 处理到实际命令处理,都是由单个线程完成的。

随着网络硬件性能的提升,Redis 的性能瓶颈有时会出现在网络 IO 的处理上,也就是说,单个主线程处理网络请求的速度跟不上底层网络硬件的速度

为了应对这个问题,一般有两个方法:

  • 第一种方法是,用户网络协议栈(例如 DPDK)取代内核网络协议栈,让网络请求的处理不用在内核里执行,直接在用户态完成处理就行。

    对于高性能 Redis 来说,避免频繁让内核进行网络请求处理,可以很好地提升请求处理效率。但是,这个方法要求在 Redis 的整体架构中,添加对用户态网络协议栈的支持,需要修改 Redis 源码中和网络相关的部门(例如,修改所有的网络收发请求函数),这会带来很多开发工作量。而且新增代码还可能引入新 BUG,导致系统不稳定。所以,Redis 6.0 中并没有采用这个方法。

  • 第二种方法就是采用多个 IO 线程来处理网络请求,提高网络请求处理的并发度。Redis 6.0 就是采用的这种方法。

    但是,Redis 的多 IO 线程只是用来处理网络请求的,对于读写命令,Redis 仍然使用单线程来处理。这是因为,Redis 处理请求时,网络处理经常是瓶颈,通过多个 IO 线程并行处理网络操作,可以提升实例的整体处理性能。而继续使用单线程执行命令操作,就不用为了保证 Lua 脚本、事务的原子性,额外开发多线程互斥机制了。这样一来,Redis 线程模实现就简单了。

我们再来看下,在 Redis 6.0 中,主线程和 IO 线程具体是怎么协作完成请求处理的。为了方便你理解,我把主线程和多 IO 线程的协作分为四个阶段。

阶段一:服务端和客户端建立 Socket 连接,并分配处理线程
首先,主线程负责接受建立连接请求。当有客户端请求和实例建立 Socket 连接时,主线程会创建和客户端的连接,并把 Socket 放入全局等待队列中。紧接着,主线程通过轮询方法把 Socket 连接分配给 IO 线程

阶段二:IO 线程读取并解析请求
主线程一旦把 Socket 分配给 IO 线程,就会进入阻塞状态,等待 IO 线程完成客户端请求读取和解析。因为有多个 IO 线程在并行处理,所以,这个过程很快就可以完成。

阶段三:主线程执行请求操作
等到 IO 线程解析完请求,主线程还是以单线程的方式执行这些命令操作。

下图展示了上面介绍的三个阶段。
在这里插入图片描述

阶段四:IO 线程回写 Socket 和主线程清空全局队列
当主线程执行完请求操作后,会把需要返回的结果写入缓冲区,然后主线程会阻塞等待 IO 线程把这些结果回写到 Socket 中,并返回给客户端。

和 IO 线程读取和解析请求一样,IO 线程会写 Socket 时,也是由多个线程在并发执行,所以回写 Socket 的速度也很快。等到 IO 线程回写 Socket 完毕,主线程会清空全局队列,等待客户端的后续请求。

下图展示了这个阶段主线程和 IO 线程的操作。
在这里插入图片描述

了解了 Redis 主线程和多线程的协作方式,我们该如何启动多线程?在 Redis 6.0 中,多线程机制是默认关闭的,如果需要启用多线程功能,需要在 redis.conf 中完成两个设置。

  1. 设置 io-thread-do-reads 配置项为 yes,表示启用多线程。
io-thread-do-reads yes
  1. 设置多线程个数。一般来说,线程个数要小于 Redis 实例所在机器的 CPU 个数,例如,对一个 8 核机器来说,官方推荐配置 6 个 IO 线程。
io-threads 6

如果你在实际应用中,发现 Redis 实例的 CPU 开销不大,吞吐量却没有提升,可以考虑使用 Redis 6.0 的多线程机制,加速网络处理,进而提升实例的吞吐量。

2.实现服务端协助的客户端缓存

和之前的版本相比,Redis 6.0 新增了一个重要的特性,就是实现了服务协助的客户端缓存功能,也称为跟踪(Tracking)功能。有了这个功能,业务应用中的 Redis 客户端就可以把读取的数据缓存在业务应用本地了,应用可以直接在本地快速读取数据了。

不过,当把数据缓存在客户端本地时,我们会面临一个问题:如果数据被修改了或是失效了,如何通知客户端对换下的数据做失效处理

Redis 6.0 Tracking 功能实现了两种模式,来解决这个问题。

第一种模式是普通模式

在这个模式下,实例会在服务端记录客户端读取过的 key,并监测 key 是否有修改。一旦 key 的值发生变化,服务端就会给客户端方 invalidate 消息,通知客户端缓存失效了

在使用普通模式时,有一点你需要注意下,服务端对于记录的 key 只会报告一次 invalidate 消息,也就是说,服务端在给客户端发送过一次 invalidate 消息后,如果 key 再被修改,此时,服务端就不会再给客户端发送 invalidate 消息。

只有当客户端再次执行读命令时,服务端才会再次检测被读取的 key,并在 key 修改时发送 invalidate 消息。这样设计的考虑是节省优先的内存空间。毕竟,客户端不在访问这个 key 了,而服务端仍然记录 key 的修改情况,就会浪费内存资源。

我们可以通过执行下面的命令,打开或关闭普通模式下的 Tracking 功能。

CLIENT TRACKING ON|OFF

第二种模式是广播模式

在这个模式下,服务端会给客户端广播所有 key 的失效情况,不过,这样做了之后,如果 key 被频繁修改,服务端会发生大量的失效广播消息,这就会消耗大量的网络带宽资源。

所以,在实际应用时,我们会让客户端注册希望跟踪的 key 的前缀,当带有注册前缀的 key 被修改时,服务端会把失效消息广播给所有注册的客户端。和普通模式不同,在广播模式下,即使客户端没有读取过 key,但只要它注册了要跟踪的 key,服务端都会把失效消息通知给客户端

举个例子,当我们在客户端执行下面的命令,如果服务端更新了 user🆔1003 这个 key,那么,客户端就会接收到 invalidate 消息。

CLIENT TRACKING ON BCAST PREFIX user

这种检测带有前缀的 key 的广播模式,和我们对 key 的命名规范非常匹配。我们在实际应用时,会给同一个业务下的 key 设置相同的业务名前缀,所以,我们就可以非常方便地使用广播模式。

不过刚才介绍的普通模式和广播模式,需要客户端使用 RESP 3 协议,RESP 3 协议是 6.0 新企业的通信协议。

对于使用 RESP 2 协议的客户端来说,就需要使用另一种模式,也就是重定向模式(redirect)。在重定向模式下,想要获得失效消息通知的客户端,就需要执行订阅命令 SUBSCRIBE,专门订阅用于发送失效消息的频道 _redis_:invalidate。同时,再使用另外一个客户端,执行 CLIENT TRACKING 命令,设置服务端将失效消息转发给使用 RESP 2 协议的客户端

假设客户端 B 想要获取失效信息,但是客户端 B 只支持 RESP 2 协议,客户端 A 支持 RESP 3 协议。我们可以分别在客户端 B 和 A 上执行 SUBSCRIBE 和 CLIENT TRACKING,如下所示:

//客户端B(RESP 2,客户ID是 303),执行 SUBSCRIBE 订阅失效消息的频道 _redis_:invalidate
SUBSCRIBE _redis_:invalidate//客户端A(RESP 3),执行CLIENT TRACKING,进行转发
CLIENT TRACKING ON BCAST REDIRECT 303

这样设置以后,如果有键值对被修改了,客户端 B 就可以通过 _redis_:invalidate 频道,获得失效消息了。

3.从简单的基于密码访问到细粒度的权限控制

Redis 6.0 版本之前,要想实现实例的安全访问,只能通过设置密码来控制,例如,客户端连接实例前需要输入密码。

对于,一些高风险的命令(例如 KEYS、FLUSHDB、FLUASHALL 等),在 Redis 6.0 之前,我们也能通过 rename-command 来重新命名这些命令,避免了客户端直接调用。

Redis 6.0 提供了更加细粒度的访问权限控制,这主要有两方面的体现。

  • 首先,6.0 版本支持创建不同用户来使用 Redis。在 6.0 中,我们可以使用 ACL SETUSER 命令创建用户。例如,我们可以执行下面的命令,创建并启用一个用户 normaluser,把它的密码设置为 “abc”:ACL SETUSER nornaluser on > abc

  • 另外,6.0 版本还支持以用户为粒度设置命令操作的访问权限。具体的命令在下表列出,其中,加号(+)和减号(-)分别表示给用户赋予或撤销命令的调用权限。

    操作作用
    +[command]将一个命令添加到用户可以调用的命令列表中
    -[command]将一个命令从用户可以调用的命令列表中移除
    +@[category]将一类命令添加到用户可以调用的命令列表中
    -@[category]将一类命从用户可以调用的命令列表中移除
    +@all允许用户调用所有命令
    -@all进制用户调用所有命令

    假设我们要设置用户 normaluser 只能调用 Hash 类型的命令操作,而不能调用 String 类型的命令操作,可以执行如下命令:

     ACL SETUSER normaluser +@hash -@string
    

除了设置某个或某类命令的访问控制权限,6.0 版本还支持以 key 为粒度设置访问权限。

具体的做法是使用波浪号“~”key 的前缀来表示控制访问的 key。例如,我们执行下面的命令,可以设置用户 normaluser 只能对以 “user:” 为前缀的 key 进行操作:

ACL SETUSER normal ~user:* +@all

现在,你知道了,Redis 6.0 可以设置不同用户来访问实例,而且可以基于用户和 key 的粒度,设置某个用户对某些 key 允许或禁止执行的命令操作。这样一来,我们在有多个用户的应用场景下,就可以非常方便和灵活地为不同用户设置不同级别的命令操作权限了,这对于提供安全的 Redis 访问非常有帮助。

4.启用 RESP 3 协议

Redis 6.0 实现了 RESP 3 通信协议,而之前都是使用 RESP 2。在 RESP 2 中,客户端和服务器端的通信内容都是以字节数组的形式进行编码的,客户端需要根据操作的命令或是数据类型自行对传输的数据进行解码,增加了客户端开发复杂度。

RESP 3 直接支持多种数据类型的区分编码,包括 空值、浮点数、布尔值、有序的字典集合、无需的集合等。

所谓区分编码,就是直接通过不同的开头字符,区分不同的数据类型,这样一来,客户端就可以直接通过判断传递消息的开头字符,来实现数据转换操作了,提升了客户端的效率。除此之外,RESP 3 协议还可以支持客户端以普通模式和广播模式实现客户端缓存。

5.小结

Redis 6.0 的新特性总结在下表中:

新增特性作用注意事项使用场景
多IO线程使用多个IO线程并行读取网络请求、进行协议解析、会写Socket多线程 IO 只负责处理网络请求,不执行命令操作提升 Redis 吞吐量
客户端缓存使用普通模式,检测客户端读取的key的修改情况普通模式和广播模式需要启用 RESP 3 协议接收失效消息加速业务应用访问
客户端缓存使用广播模式,将key失效信息发送给所有客户端加速业务应用访问
客户端缓存使用重定向模式,支持使用 RESP 2 协议的客户端加速业务应用访问
访问权限控制区分不同用户,支持以用户和key为粒度设置某个或某类命令的调用权限支持多用户以不同权限访问 Redis
RESP 3协议使用不同开头字符表示多种数据类型,简化客户端开发复杂度高效支持不同数据类型使用,支持客户端缓存

另外,因为 Redis 6.0 是刚刚推出的,新的功能特性还需要在实际应用中进行部署和验证,如果想要试用 Redis 6.0,可以尝试先在非核心业务上使用 Redis 6.0 ,一方面可以验证新特性带来的性能或功能优势,另一方面,也可以避免因为新特性不稳定而导致核心业务受到影响。

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

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

相关文章

fast.ai 深度学习笔记(二)

深度学习 2:第 1 部分第 4 课 原文:medium.com/hiromi_suenaga/deep-learning-2-part-1-lesson-4-2048a26d58aa 译者:飞龙 协议:CC BY-NC-SA 4.0 来自 fast.ai 课程的个人笔记。随着我继续复习课程以“真正”理解它,这…

【机器学习300问】22、什么是超参数优化?常见超参数优化方法有哪些?

在之前的文章中,我主要介绍了学习率 η和正则化强度 λ 这两个超参数。这篇文章中我就主要拿这两个超参数来进行举例说明。如果想在开始阅读本文之前了解这两个超参数的有关内容可以参考我之前的文章,文章链接为你放在了这里: 【机器学习300…

kvm qemu 优化 windows 虚拟机速度

主要优化磁盘 io 和网络 io 都选为 virtio windows 驱动下载 https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.185-2/virtio-win-0.1.185.iso I also had incredibly slow performance with my virtual HDD. The followin…

每日一个shell脚本之自动化采集监控指标+登录欢迎

每日一个shell脚本之自动化采集监控指标登录欢迎 效果图参上 源码奉上 #!/usr/bin/bashclear#空闲内存Frfree -h | awk NR2{print $4}#已用内存Usfree -h | awk NR2{print $3}#系统存储空间Us_systemdf -Th | grep /dev/ | tail -1 | awk {print $4}Us_freedf -Th | grep /de…

直播app开发,技术驱动的实时互动新纪元

随着互联网技术的快速发展,直播已成为我们日常生活的重要组成部分。从娱乐、教育到商业活动,直播的广泛应用正在改变着我们的生活和工作方式。在这一变革中,直播开发扮演着至关重要的角色。本文将探讨直播开发的核心理念、技术挑战以及未来的…

【C++】初识模板:函数模板和类模板

目录 一、模板函数 1、函数模板的概念 2、函数模板的格式 3、函数模板的原理 4、函数模板实例化 5、 模板参数的匹配原则 二、类模板 1 、类模板的定义格式 2 、类模板的实例化 3、模板类示例 一、模板函数 1、函数模板的概念 函数模板代表了一个函数家族&#xff0c…

C语言之预处理详解

目录 1. 预定义符号2. #define定义常量3. #define定义宏练习 4. 带有副作用的宏参数5. 宏替换的规则6. 宏函数的对比宏和函数的一个对比 7. #和###运算符##运算符 8. 命名约定9. #undef10. 命令行定义11. 条件编译常见的条件编译 12. 头文件的包含头文件的包含方式库文件包含嵌…

通过遵循最佳做法来提高 EDA 和 HPC 应用程序的 Azure NetApp 文件性能

介绍 Azure NetApp 文件是一项托管存储解决方案,适用于各种方案,包括高性能计算 (HPC) 基础结构。 低延迟和每秒高 I/O 操作数 (IOPS) 对于大规模企业而言是一种很好的组合。 假设你就职于一家半导体公司。 你的任务是设计公司的集成电路芯片&#xff…

新春快乐(烟花、春联)【附源码】

新春快乐 一&#xff1a; C语言 -- 烟花二&#xff1a;Python -- 春联三&#xff1a;Python -- 烟花四&#xff1a;HTML -- 烟花 一&#xff1a; C语言 – 烟花 运行效果&#xff1a; #include <graphics.h> #include <math.h> #include <time.h> #include…

电商小程序07显示用户个人信息

目录 1 全局变量2 控制登录按钮显示3 设置布局4 搭建我的页面5 修改个人信息总结 在登录章节我们已经实现了用户名和密码登录首页的功能&#xff0c;在登录之后&#xff0c;可以切换到我的页面&#xff0c;显示用户的头像和名称&#xff0c;可以修改个人信息。本篇我们介绍一下…

【Spring MVC篇】参数的传递及json数据传参

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、普通参数的传…

STM32能够做到数据采集和发送同时进行吗?

STM32能够做到数据采集和发送同时进行吗&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「STM32的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&am…

专业140+总分420+河海大学863信号与系统考研经验电子信息通信与信息技术,真题,大纲,参考书。

今年的成绩出来倍感欣慰&#xff0c;决定考研的时候并没有想到自己可以考出420的分数&#xff0c;通过自己一年来的努力&#xff0c;成功上岸&#xff0c;期中专业课863信号与系统140接近满分&#xff08;非常感谢信息通信Jenny老师的专业课辅导和平时悉心答疑&#xff0c;不厌…

【MATLAB源码-第138期】基于matlab的D2D蜂窝通信仿真,对比启发式算法,最优化算法和随机算法的性能。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 D2D蜂窝通信介绍 D2D蜂窝通信允许在同一蜂窝网络覆盖区域内的终端设备直接相互通信&#xff0c;而无需数据经过基站或网络核心部分转发。这种通信模式具有几个显著优点&#xff1a;首先&#xff0c;它可以显著降低通信延迟&…

波奇学Linux: 文件描述符

文件和操作系统的关系 操作系统控制进程&#xff0c;文件的打开是在进程中进行。意味着用来控制进程的PCB必然有文件的信息&#xff0c;操作系统通过控制PCB的信息来控制文件的读写。 Q1&#xff1a;如何证明文件打开是在进程中进行&#xff1f; 编写c文件调用fopen来操作文件…

SpringBoot 接入讯飞星火大模型实现对话

申请地址 https://xinghuo.xfyun.cn/sparkapi?scrprice 免费申请200万Token 开发文档 https://www.xfyun.cn/doc/spark/Web.html#_1-接口说明 页面最下面有相关demo可以参考 介绍 接口是以套接字的形式分段返回&#xff0c;而且非http请求&#xff0c;比较繁琐&#xff0c;官…

如何使用Airtest进行UI自动化测试

一、环境搭建 1、Airtest客户端下载 访问官网http://airtest.netease.com/&#xff0c;根据自己的系统下载相应的客户端安装&#xff1b; 2、python工具下载与环境搭建 在本地python环境中安装airtest和pocoui&#xff0c;然后用命令行运行脚本&#xff1b; 1、建议使用3.…

猫头虎分享已解决Bug || RuntimeError: size mismatch, m1: [32 x 100], m2: [500 x 10]

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

奶茶点餐|奶茶店自助点餐系统|基于微信小程序的饮品点单系统的设计与实现(源码+数据库+文档)

奶茶店自助点餐系统目录 目录 基于微信小程序的饮品点单系统的设计与实现 一、前言 二、系统功能设计 三、系统实现 1、商品信息管理 2、商品评价管理 3、商品订单管理 4、用户管理 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 …

Linux操作系统基础(八):Linux的vi/vim编辑器

文章目录 Linux的vi/vim编辑器 一、vi/vim编辑器介绍 二、打开文件 三、VIM编辑器的三种模式(重点) 四、命令模式相关命令 五、底行模式相关命令 Linux的vi/vim编辑器 一、vi/vim编辑器介绍 vi是visual interface的简称, 是Linux中最经典的文本编辑器 vi的核心设计思想…