Redis线程模型解析
引言
Redis是一个高性能的键值对(key-value)内存数据库,以其卓越的读写速度和灵活的数据类型而广受欢迎。在Redis 6.0之前的版本中,它采用的是一种独特的单线程模型来处理客户端的请求。尽管单线程在概念上似乎限制了其扩展性和并发能力,但通过精妙的设计,Redis依然能够支撑大量的并发连接。本文将深入探讨Redis的单线程模型及其如何实现高效能。
Redis单线程模型
在讨论Redis的线程模型之前,需要理解其基于事件的编程模型。Redis服务器在启动时会初始化一套文件事件处理器,用于处理来自客户端的连接请求、命令读取以及数据写入等操作。
Reactor模式
Reactor模式是Redis能够高效处理I/O的核心设计之一。在这种模式下,Redis将所有客户端的socket连接都抽象为文件描述符(file descriptor),然后使用I/O多路复用技术统一监听这些文件描述符上的事件。当某个文件描述符准备好进行读/写操作时,Reactor就会相应地处理这个事件。
I/O多路复用
I/O多路复用是允许单个线程同时监控多个文件描述符的技术。这意味着Redis可以在等待某些慢操作(如网络IO或磁盘IO)的同时,处理其他客户端的命令。这种非阻塞I/O的能力使得Redis可以高效利用CPU资源,即使在单线程环境下也能维持高并发的客户端连接。
事件循环
事件循环是Redis单线程模型的中心环节。它是一个无限循环,不断地检查是否有新的事件到来,并调用相应的事件处理器来响应这些事件。事件循环的效率直接影响到Redis的整体性能。
事件分派与处理
当I/O多路复用程序检测到有文件描述符上的事件发生时,它会将这些事件放入一个队列中。事件分派器随后会从队列中取出事件,并将它们分派给对应的事件处理器。每个事件处理器负责执行具体的任务,比如接受新的客户端连接、执行命令或向客户端发送响应。
为何选择单线程?
-
简单性: 单线程模型极大简化了程序的设计,因为不需要担心状态同步和并发控制的问题。
-
高效性: 由于省去了线程间切换和锁机制的开销,单线程可以快速地执行命令。
-
可预测性: 单线程模型下,命令的执行顺序是线性且确定的,这有助于优化命令的执行效率。
Reactor模式详解
Reactor模式是一种基于事件驱动的设计模式,它旨在通过非阻塞I/O和多路复用技术提高系统性能。
Reactor模式的核心思想是利用单个线程来处理所有客户端的事件。这种模式特别适合于需要处理大量并发连接的网络应用程序。以下是对Reactor模式的详细解释:
-
- 事件分离与分发(Dispatcher): Reactor模式也被称为Dispatcher模式,因为它的工作方式是将接收到的事件分发给对应的处理器。这些事件可以是网络IO操作,比如连接打开、数据读取或写入等。
-
- 服务处理器(Service Handler): 在Reactor模式中,有一个核心组件叫做服务处理器,它负责监听并分派事件。服务处理器会同步地将输入的请求事件分发给相应的请求处理器。
-
- 请求处理器(Request Handlers): 针对不同类型的事件,Reactor模式提供了多个请求处理器。每个请求处理器都专门处理一种类型的事件,这样可以提高处理事件的效率和灵活性。
-
- I/O多路复用: Reactor模式通常与I/O多路复用技术结合使用。这使得单个线程可以高效地管理多个连接,而不必为每个连接创建一个线程。这样既节省了资源,又减少了线程切换的开销。
此外,Reactor模式没有使用队列作为缓冲,事件一旦被服务处理器接收,就会被立即分发给相应的处理器进行处理。这种方式避免了可能因为队列填满而导致的性能瓶颈。
Redis多线程
在Redis 4.0版本中,为了解决大键删除导致服务器阻塞的问题,Redis引入了Lazy Free线程。这个线程专门负责回收内存,当执行删除大键等耗时操作时,这些任务会由Lazy Free线程在后台异步完成,从而避免了主线程的阻塞。
而Lazy Free,即惰性删除或延迟释放,是Redis为了解决删除大键时可能导致的性能和可用性问题而引入的一种机制。当执行删除操作时,尤其是在删除大键(big key)的情况下,这个过程可能会非常耗时。在Redis的传统单线程模型中,这样的操作会阻塞主线程,导致在此期间无法处理其他请求,从而影响整体性能。
此外,虽然Redis的核心网络模型仍然是单线程的,但Redis 6.0版本进一步引入了I/O Thread线程,正式实现了多线程。这些线程主要用于处理网络I/O,提高数据读写的并发性能。具体来说,I/O线程负责处理客户端的读取请求和写回响应,这样的设计使得Redis在处理大量连接时能够更加高效。
总的来说,Redis的多线程设计是对原有单线程模型的补充,它通过将一些耗时的操作异步化,提高了Redis在处理重负载任务时的性能和响应能力。
总结
Redis的单线程模型通过Reactor模式、I/O多路复用技术和事件循环实现了高效的数据处理。虽然它在表面上看似限制了并发能力,但实际上,由于几乎所有操作都是在内存中完成,加之高效的设计和实现,Redis即便在单线程下也能提供非常高的吞吐量和低延迟的响应。
不过,随着业务需求的增长和技术发展,Redis在6.0版本引入了多线程以提升特定操作的性能,这表明即使是优秀的设计也需要随着时代的发展而不断进化。
相关文章:

Redis线程模型解析
引言 Redis是一个高性能的键值对(key-value)内存数据库,以其卓越的读写速度和灵活的数据类型而广受欢迎。在Redis 6.0之前的版本中,它采用的是一种独特的单线程模型来处理客户端的请求。尽管单线程在概念上似乎限制了其扩展性和并…...
ros2 launch如何控制node的启动顺序
ros2 launch如何控制node的启动顺序 文章目录 引言如何写launch文件启动流程图具体launch代码总结引言 本文用来说明如何控制ros2 launch 节点的先后顺序,我们有时候需要一个节点启动完成后再启动其它节点,实现这个功能有两种方式: 在launch.py时写event根据事件触发使用li…...
Android13 framework层添加关机接口
framework层修改: t0_sys/frameworks/base/core/api/current.txt method RequiresPermission(android.Manifest.permission.REBOOT) public void reboot(Nullable String);method public void rebootp();t0_sys/frameworks/base/core/java/android/os/IPowerManager…...

GDB调试入门笔记
文章目录 What?WhyHow安装GDB安装命令查看是否安装成功调试简单的程序预备一个程序调试 使用breakinfolistnextprintstep一些小技巧在gdb前shell日志功能watch point| catch point 调试core调试一个运行的程序 What? GDB是什么? 全称GNU sym…...

JavaScript的`call`方法:实现函数间的调用!
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

qt5-入门-使用拖动方式创建Dialog
参考: C GUI Programming with Qt 4, Second Edition 本地环境: win10专业版,64位,Qt5.12 目录 实现效果基本流程逐步实操1)创建和初始化子部件2)把子部件放进布局中3)设置tab顺序4)…...

【Redis】RedisTemplate和StringRedisTemplate的区别
两者的关系是 StringRedisTemplate 继承 RedisTemplate 。 两者的数据是不共通的:也就是说 StringRedisTemplate 只能管理 StringRedisTemplate 里面的数据,RedisTemplate 只能管理 RedisTemplate 中的数据。 RedisTemplate 看这个类的名字后缀是 Temp…...
面试经典150题(101-104)
leetcode 150道题 计划花两个月时候刷完之未完成后转,今天(第1天)完成了4道(101-104)150: 101.(215. 数组中的第K个最大元素) 题目描述: 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请…...

Java实现读取转码写入ES构建检索PDF等文档全栈流程
背景 之前已简单使用ES及Kibana和在线转Base64工具实现了检索文档的demo,并已实现WebHook的搭建和触发流程接口。 传送门: 基于GitBucket的Hook构建ES检索PDF等文档全栈方案 使用ES检索PDF、word等文档快速开始 实现读取本地文件入库ES 总体思路&…...
主流开发环境和开发语言介绍
主流开发环境和开发语言介绍 一、主流开发环境介绍 主流开发环境是指广泛应用于软件开发的集成开发环境(Integrated Development Environment,简称IDE)。IDE是一种集成了编辑器、编译器、调试器等工具的软件,提供了一站式的开发环…...
C++ 使用 nlohmann::json存储json文件
C 使用 nlohmann::json存储json文件 nlohmann::json 概述JSON 存储的示例以追加的方式存储json文件 nlohmann::json 概述 nlohmann::json 是 C 中一个流行的 JSON 库,由 Niels Lohmann 开发。它提供了一个简单而强大的 API,用于解析、构建、操作和序列化…...
何为OOM(Out of Memory)?
OOM(Out of Memory) 是指程序运行过程中内存不足的情况。在 Spark 应用程序中,OOM 是一个非常常见的问题,尤其是在处理大规模数据集或执行资源密集型的操作时。当 Spark 作业尝试使用的内存超过了为其分配的内存限制时,…...

SpringBoot+Mybatis-plus+shardingsphere实现分库分表
SpringBootMybatis-plusshardingsphere实现分库分表 文章目录 SpringBootMybatis-plusshardingsphere实现分库分表介绍引入依赖yaml配置DDL准备数据库ds0数据库ds1 entitycotrollerserviceMapper启动类测试添加修改查询删除 总结 介绍 实现亿级数据量分库分表的项目是一个挑战…...

FPGA DDR3简介及时序
一,DDR3基础知识 1、DDR3全称第三代双倍速率同步动态随机存储器。 特点:①掉电无法保存数据,需要周期性的刷新。 ②时钟上升沿和下降沿都会传输数据。 ③突发传输,突发长度Burst Length一般为8 2、DDR3的存储: bank、行地址和列地址 数据怎么存入到D…...

java网络编程 02 socket
01.socket定义 02.TCP编程 import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;public class clientSocket {public static void main(String[] args) throws IOException {Socket socket new Socket(Ine…...

【Web安全】SQL各类注入与绕过
【Web安全】SQL各类注入与绕过 【Web安全靶场】sqli-labs-master 1-20 BASIC-Injection 【Web安全靶场】sqli-labs-master 21-37 Advanced-Injection 【Web安全靶场】sqli-labs-master 38-53 Stacked-Injections 【Web安全靶场】sqli-labs-master 54-65 Challenges 与62关二…...

C++ 设计模式
文章目录 类图泛化实现关联聚合组合依赖总结 类内部的三种权限(公有、保护、私有)类的三种继承方式描述与图总结 面向对象七大原则单一职责原则(Single Responsibility Principle)里氏替换原则(Liskov Substitution Pr…...

安卓使用ExoPlayer出现膨胀类异常
1.导包 implementation com.google.android.exoplayer:exoplayer-core:2.15.1implementation com.google.android.exoplayer:exoplayer-ui:2.15.1 2.在Androidifest.xml加入权限,我这里加了网络与读写权限 <uses-permission android:name"android.permissio…...
C++之析构函数
在 C 中,析构函数(Destructor)是一个特殊的成员函数,用于在对象生命周期结束时执行清理工作和资源释放。析构函数的名称与类名相同,前面加上波浪号(~),不接受任何参数,也…...

108. 将有序数组转换为二叉搜索树【简单】
108. 将有序数组转换为二叉搜索树【简单】 题目描述: 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...

未授权访问事件频发,我们应当如何应对?
在当下,数据已成为企业和组织的核心资产,是推动业务发展、决策制定以及创新的关键驱动力。然而,未授权访问这一隐匿的安全威胁,正如同高悬的达摩克利斯之剑,时刻威胁着数据的安全,一旦触发,便可…...