当前位置: 首页 > news >正文

redis6.0之后的多线程版本的问题

一、redis早期版本和新版本的讨论

这个问题其实有些废话,哪个版本肯定都有不同啊。其实这里主要是提到的网上的大家对Redis6.0中的多线程版本的不同即以前宣传的Redis是单线程程版的,之后变成了多线程版本的。网上对这个讨论非常激烈,反正各种说法都有。
其实,结论只有一个,很多讨论的人都是就事论事,没有真正看源码也没有看所谓多线程和单线程应对的场景也就是Redis的正常应用下,它的适应情况。所以,往往大家抓住一个点,开始各种各种表达,然后就没然后了,为了讨论而讨论。

二、redis的单线程和多线程版本

既然是讨论,不妨咱们也多句嘴,百花齐放一下。对Redis来说,其做为一种内存型数据库,其主要目的就是在内存中存储键值对,也就是常说的KV数据。对内存操作来说,速度有多快,开发者们不想都可以知道。假设有一种存储能快到和Cache一样的速度并且容量大,那么多线程意义更不大。前面分析过,所谓各种的处理手段的目的就是为了解决计算机中资源处理速度的不匹配而出来的,多线程也是如此(当然,不能说完全是为了这个)。
那么如果从这种思想出发,可以发现,内存对网络IO的速度那是辗压级别的。好,回头看一下Redis的单线程模型的主要内容:
从上层来看就是一个线程+IO多路复用(epoll或 kevent 或 select)。一个线程对应着这种IO多路复用,恰恰正是优势所在。而前面的网络系列中分析过,无论哪种多路复用,一个前提是,活跃的连接一定不能太多,否则其基本的速度都是差不多的,甚至还不如最简单的select。
如果你要坚持开多个IO多路复用,对Redis这种多点部署的程序来说,不如多部署几个节点。也就是说,需要考虑多点和多线程间的效率、成本和其它条件了。
所以说,所谓单线程指的是这一部分,而不是说整个Redis没有使用多线程,这是第一个要明白的单线程和多线程的区别;其次,单线程在这种环境下,相对多线程至少没有劣势,特别成开发、维护等上反而更有优势。

三、应用场景的分析

在设计和开发一个软件时,最初一定是为了达到自己的某些想法或者说设定目标,如果这种想法和目标不需要某种复杂的技术就可以实现,那么为什么要杀鸡用牛刀呢?换句话说,如果小学的知识可以解决的问题,为什么非要升级到大学知识才去解决呢?但反过来又想,目前小学知识可以解决这个问题,可过了两年发现新的应用场景或者目标如果用到中学的会更好,大学的会更好?做为问题的解决者,你会怎么办?或者可以理解成,可不可以老中青三年一起来解决问题呢?这样想就明白了Redis多线程版本了。推而广之,也就明白了所有的软件迭代升级的特点了。
与时俱进,是每一个人必须掌握的基本思想。
做为内存型的数据库,快是最主要的一种特点。而数据库最典型的特征就是要读写数据到数据库。这二者的目标提出来,可以用后来者的眼光分析一下,多线程在这种场景下是否比单线程更有优势,而且这种优势必须是全面的,成倍以上的。这是什么意思呢。全面,必须要考虑技术的先进性和安全稳定性;也要兼顾容易开发和后期的易维护性,还有其它如成本等等。而不是单纯的考虑一个技术问题。另外,如果使用一项新技术仅仅比旧的技术提高了不多的效率,那么整体的成本仍然是让人无法忍受的。
具体到Redis,其最主要的核心是通过网络接收数据然后通过处理读写内存,这是最基础最核心的需求。前面分析过多路复用,然后再增加一个线程搞一搞读写,既可以快速操作内存,又可以防止出现多线程中的数据一致性和锁,同步等问题。这样一看,单线程没有啥劣势啊,甚至还有优势。然后,再实际测试一下,多线程与单线程在这种情况下,根本没有什么大的优势。而且官方的声明中也提到了:在这种内存IO的数据库中,限制性能的瓶颈不是CPU,而是内存大小和网络IO的处理(注意,这也是后来升到多线程的一个重要原因)。
那么既然不是瓶颈,为什么Redis6要升级多线程呢?
仍然回头看Redis的主流应用线程+IO多路复用。这里有没有可以使用多线程进行优化,从而进一步提高效率的呢?特别是随着Redis的广泛应用,一些复杂的命令和数据结构也被应用上来,协议也在不断的升级和扩充等等。有过网络开发经验的开发者会想到,在网络开发中,高并发是一个重要的特点,虽然不能在同一时间有大量活跃,但可以轮换活跃,保持着一种中等并发的持续性应用。那么此时一个瓶颈出现了,多路复用中,读和写的处理以及监听的处理速度往往不匹配;而且数据读出来的原始解析(解析协议)也很浪费时间,可不可以用一些线程来处理这些功能呢?这些功能如果用多线程处理能提高多少效率呢?会增加多少开发和维护成本呢?而且物理硬件也在不断的推陈出新,多核的CPU已经被广泛在服务器中应用,一些新的技术也涌现出来。这对Redis的开发维护者也提出了更高的要求。
从Redis6.0中提供了这个多线程版本来看,应该是效率明显的,不然不会推出。但仔细看源码,发现整个Redis6.0的核心命令执行仍然是单线程的,这是什么意思?就是最初的设计的意思,简单、安全而又保证效率的情况下,为什么要引入多线程呢?
那么以后会不会继续改进甚至全部改成多线程呢?这个还是得看发展。如果协程被广泛应用后,可以就是协程版了,大家说有没有这种可能?

四、总结

早就跟大家一起分享过,一定要抓住事物本质。针对软件就是找到其应用的目的,其核心思想是什么,而不是简单的说哪种技术好,哪种技术不好。最合适的就最好的,而这个最合适一定是随着应用的发展不断的变化的。孤立的、片面的和僵化的看问题,就很容易陷入到无何止的争论中去。教条主义、本本主义和经验主义,其实大家都犯,但一定要记得打破这层牢笼。否则,就会固步自封,难建寸功。
所以科学和哲学,往往是无法分开的。这也是学习一些思想的目的和原因。

相关文章:

redis6.0之后的多线程版本的问题

一、redis早期版本和新版本的讨论 这个问题其实有些废话,哪个版本肯定都有不同啊。其实这里主要是提到的网上的大家对Redis6.0中的多线程版本的不同即以前宣传的Redis是单线程程版的,之后变成了多线程版本的。网上对这个讨论非常激烈,反正各…...

python的 pandas.Dataframe 和 pandas.Series基础内容

目录 0 有一个比较麻烦琐碎的地方 1 python pandas.Dataframe 2 pd.concat() 可以合并 pd.Dataframe 2.1 pd.concat() 合并规则 3 pd.Dataframe.drop() 删除行列的操作 4 pd.Dataframe 列操作 5 pd.Dataframe 行操作 5.1 sample_dataframe2.head(n2) 取前面的n行&…...

golang学习5

为结构体添加方法 异常处理过程...

【C语言】11月第二次测试 ing

文章目录 1.输入n名同学的成绩和学号,对成绩排序,输出对应学号 要求重复的学号重新输入 计算n名同学的平均值,对小于60分的同学删除分数 大于60分的同学输出:优秀:几人,良好:几人,中…...

行列式的理解与计算:线性代数中的核心概念

开发领域:前端开发 | AI 应用 | Web3D | 元宇宙 技术栈:JavaScript、React、ThreeJs、WebGL、Go 经验经验:6 年 前端开发经验,专注于图形渲染和 AI 技术 开源项目:github 简智未来、数字孪生引擎、前端面试题 大家好&a…...

按出生日期排序(结构体专题)

题目描述 送人玫瑰手有余香,小明希望自己能带给他人快乐,于是小明在每个好友生日的时候发去一份生日祝福。小明希望将自己的通讯录按好友的生日排序排序,这样就查看起来方便多了,也避免错过好友的生日。为了小明的美好愿望&#x…...

【C++】拆分详解 - 多态

文章目录 一、概念二、定义和实现1. 多态的构成条件2. 虚函数2.1 虚函数的重写/覆盖2.2 虚函数重写的两个例外 3. override 和 final关键字4. 重载/重写/隐藏的对比5. 例题 三、纯虚函数和抽象类四、多态的原理1. 虚函数表2. 实现原理3. 动态绑定和静态绑定 总结 一、概念 多态…...

Python世界:力扣题解875,珂珂爱吃香蕉,中等

Python世界:力扣题解875,珂珂爱吃香蕉,中等 任务背景思路分析代码实现坑点排查测试套件本文小结 任务背景 问题来自力扣题目875 Koko Eating Bananas,大意如下: Koko loves to eat bananas. There are n piles of bana…...

Java设计模式 —— Java七大设计原则详解

文章目录 前言一、单一职责原则1、概述2、案例演示 二、接口隔离原则1、概述2、案例演示 三、依赖倒转原则1、概述2、案例演示 四、里氏替换原则1、概述2、案例演示 五、开闭原则1、概述2、案例演示 六、迪米特法则1、概述2、案例演示 七、合成/聚合复用原则1、概述2、组合3、聚…...

SpringBoot学习记录(六)配置文件参数化

SpringBoot学习记录(六)配置文件参数化 一、参数提取到配置文件中二、yml配置文件三、ConfigurationProperties注解实现批量属性注入 一、参数提取到配置文件中 定义在代码中的参数的值分散在各个不同的文件中,不便于后期维护管理&#xff0…...

android 使用MediaPlayer实现音乐播放--获取音乐数据

前面已经添加了权限&#xff0c;有权限后可以去数据库读取音乐文件&#xff0c;一般可以获取全部音乐、专辑、歌手、流派等。 1. 获取全部音乐数据 class MusicHelper {companion object {SuppressLint("Range")fun getMusic(context: Context): MutableList<Mu…...

.net 8使用hangfire实现库存同步任务

C# 使用HangFire 第一章:.net Framework 4.6 WebAPI 使用Hangfire 第二章:net 8使用hangfire实现库存同步任务 文章目录 C# 使用HangFire前言项目源码一、项目架构二、项目服务介绍HangFire服务结构解析HangfireCollectionExtensions 类ModelHangfireSettingsHttpAuthInfoUs…...

第 22 章 - Go语言 测试与基准测试

在Go语言中&#xff0c;测试是一个非常重要的部分&#xff0c;它帮助开发者确保代码的正确性、性能以及可维护性。Go语言提供了一套标准的测试工具&#xff0c;这些工具可以帮助开发者编写单元测试、表达式测试&#xff08;通常也是指单元测试中的断言&#xff09;、基准测试等…...

VB.Net笔记-更新ing

目录 1.1 设置默认VS的开发环境为VB.NET&#xff08;2024/11/18&#xff09; 1.2 新建一个“Hello&#xff0c;world”的窗体&#xff08;2024/11/18&#xff09; 1.3 计算圆面积的小程序&#xff08;2024/11/18&#xff09; 显示/隐式 声明 &#xff08;2024/11/18&…...

centos 服务器 docker 使用代理

宿主机使用代理 在宿主机的全局配置文件中添加代理信息 vim /etc/profile export http_proxyhttp://127.0.0.1:7897 export https_proxyhttp://127.0.0.1:7897 export no_proxy"localhost,127.0.0.1,::1,172.171.0.0" docker 命令使用代理 例如我想在使用使用 do…...

python语言基础

1. 基础语法 Q: Python 中的变量与数据类型有哪些&#xff1f; A: Python 支持多种数据类型&#xff0c;包括数字&#xff08;整数 int、浮点数 float、复数 complex&#xff09;、字符串 str、列表 list、元组 tuple、字典 dict 和集合 set。每种数据类型都有其特定的用途和…...

Python中的Apriori库详解

文章目录 Python中的Apriori库详解一、引言二、Apriori算法原理与Python实现1、Apriori算法原理2、Python实现1.1、数据准备1.2、转换数据1.3、计算频繁项集1.4、提取关联规则 三、案例分析1、导入必要的库2、准备数据集3、数据预处理4、应用Apriori算法5、生成关联规则6、打印…...

MongoDB比较查询操作符中英对照表及实例详解

mongodb比较查询操作符中英表格一览表 NameDescription功能$eqMatches values that are equal to a specified value.匹配值等于指定值。$gtMatches values that are greater than a specified value.匹配值大于指定值。$gteMatches values that are greater than or equal to…...

掌上单片机实验室 – RT-Thread + ROS2 初探(25)

在初步尝试RT-Thread之后&#xff0c;一直在琢磨如何进一步感受它的优点&#xff0c;因为前面只是用了它的内核&#xff0c;感觉和FreeRTOS、uCOS等RTOS差别不大&#xff0c;至于它们性能、可靠性上的差异&#xff0c;在这种学习性的程序中&#xff0c;很难有所察觉。 RT-Threa…...

‌Kotlin中的?.和!!主要区别

目录 1、?.和!!介绍 2、使用场景和最佳实践 3、代码示例和解释 1、?.和!!介绍 ‌Kotlin中的?.和!!主要区别在于它们对空指针的处理方式。‌ ‌?.&#xff08;安全调用操作符&#xff09;‌&#xff1a;当变量可能为null时&#xff0c;使用?.可以安全地调用其方法或属性…...

iframe嵌入踩坑记录

iframe嵌入父子页面token问题 背景介绍 最近在做在平台A中嵌入平台B某个页面的需求&#xff0c;我负责的是平台B这边&#xff0c;使这个页面被嵌入后能正常使用。两个平台都实现了单点登录。 其实这是第二次做这个功能了&#xff0c;原本以为会很顺利&#xff0c;但没想到折腾…...

面试小札:Java的类加载过程和类加载机制。

Java类加载过程 加载&#xff08;Loading&#xff09; 这是类加载过程的第一个阶段。在这个阶段&#xff0c;Java虚拟机&#xff08;JVM&#xff09;主要完成三件事&#xff1a; 通过类的全限定名来获取定义此类的二进制字节流。这可以从多种来源获取&#xff0c;如本地文件系…...

Spring 上下文对象

1. Spring 上下文对象概述 Spring 上下文对象&#xff08;ApplicationContext&#xff09;是 Spring 框架的核心接口之一&#xff0c;它扩展了 BeanFactory 接口&#xff0c;提供了更多企业级应用所需的功能。ApplicationContext 不仅可以管理 Bean 的生命周期和配置&#xff0…...

Wireshark抓取HTTPS流量技巧

一、工具准备 首先安装wireshark工具&#xff0c;官方链接&#xff1a;Wireshark Go Deep 二、环境变量配置 TLS 加密的核心是会话密钥。这些密钥由客户端和服务器协商生成&#xff0c;用于对通信流量进行对称加密。如果能通过 SSL/TLS 日志文件&#xff08;例如包含密钥的…...

测试人员--如何区分前端BUG和后端BUG

在软件测试中&#xff0c;发现一个BUG并不算难&#xff0c;但准确定位它的来源却常常让测试人员头疼。是前端页面的问题&#xff1f;还是后台服务的异常&#xff1f;如果搞错了方向&#xff0c;开发人员之间的沟通效率会大大降低&#xff0c;甚至导致问题久拖不决。 那么&#…...

【Vue】指令扩充(指令修饰符、样式绑定)

目录 指令修饰符 按键修饰符 事件修饰符 双向绑定指令修饰符 输入框 表单域 下拉框 单选按钮 复选框 样式绑定 分类 绑定class 绑定style tab页切换示例 指令修饰符 作用 借助指令修饰符&#xff0c;可以让指令的功能更强大 分类 按键修饰符&#xff1a;用来…...

Ubuntu20.04 Rk3588 交叉编译ffmpeg7.0

firefly 公司出的rk3588的设备&#xff0c;其中已经安装了gcc 交叉编译工具&#xff0c;系统版本是Ubuntu20.04。 使用Ubuntu20.04 交叉编译ffmpeg_ubuntu下配置ffmpeg交叉编译器为arm-linux-gnueabihf-gcc-CSDN博客文章浏览阅读541次。ubuntu20.04 交叉编译ffmpeg_ubuntu下配…...

HTML常用表格与标签

一、table表格标签&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!--有大小为1的边框--> <table border"1">…...

网络安全与加密

1.Base64简单说明描述&#xff1a;Base64可以成为密码学的基石&#xff0c;非常重要。特点&#xff1a;可以将任意的二进制数据进行Base64编码结果&#xff1a;所有的数据都能被编码为并只用65个字符就能表示的文本文件。65字符&#xff1a;A~Z a~z 0~9 / 对文件进行base64编码…...

MySQL数据库-索引的介绍和使用

目录 MySQL数据库-索引1.索引介绍2.索引分类3.创建索引3.1 唯一索引3.2 普通索引3.3 组合索引3.4 全文索引 4.索引使用5.查看索引6.删除索引7.索引总结7.1 优点7.2 缺点7.3 索引使用注意事项 MySQL数据库-索引 数据库是用来存储数据&#xff0c;在互联网应用中&#xff0c;数据…...