【Redis】Redis线程IO模型与基于文件的网络通信模型(Redis专栏启动)

📫作者简介:小明java问道之路2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。

        

📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。

        

🏆 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人

🏆 InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家

        

🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~ 


🍅 文末获取联系 🍅  👇🏻 精彩专栏推荐订阅收藏 👇🏻

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥Redis从入门到精通与实战🔥

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

🔥Java全栈白宝书🔥

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

本文目录

本文目录

本文导读

一、为什么Redis是单线程的还那么快

二、Redis6.0之前为什么选择单线程

三、Redis线程IO模型与基于文件的网络通信模型

1、IO模型与网络通信模型

2、客户端向 Redis 发起请求命令的工作原理

四、Redis 6.0的多线程模型

1、Redis6.0版本为什么变为多线程模型?

2、Redis6.0多线程模型的工作原理

总结


本文导读

本文深入浅出,首先分析为什么Redis是单线程的还那么快以及Redis6.0之前为什么选择单线程,深入Redis线程IO模型与基于文件的网络通信模型和客户端向 Redis 发起请求命令的工作原理,最后剖析Redis6.0版本为什么变为多线程模型,Redis6.0多线程模型的工作原理。

一、为什么Redis是单线程的还那么快

1、完全基于内存,大多数请求都基于纯内存操作(I/O),与其他基于磁盘的DB相比,Redis纯内存操作具有自然的性能优势。

2、C语言实现,并且数据结构简单,操作简单,Redis中的数据结构是专门设计的。

3、采用单线程,避免不必要的上下文切换和竞争,不存在多进程或多线程切换导致的CPU消耗

4、基于epoll、select、kqueue和其他I/O复用技术的复用I/O模型(非阻塞IO),以实现高吞吐量网络I/O模型。

5、Redis直接构建MV操作(document move),如果一般系统调用函数,那么会浪费一定的时间来移动和请求。MV操作意味着用户可以使用MV命令重命名文件或目录,或将文件从一个目录移动到另一个目录。

二、Redis6.0之前为什么选择单线程

 官方给出的答案是:It's not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.也就是说CPU成为Redis的瓶颈并不常见,因为Redis通常是内存或网络受限的。例如,使用在平均Linux系统上运行的管道Redis每秒可以发送100万个请求,因此如果您的应用程序主要使用O(N)(N)或O(log(N))命令,它几乎不会使用太多CPU。

考虑到Redis的性能,单线程避免了频繁的上下文切换问题,效率高;考虑到Redis的内部结构设计原则,Redis基于actor模式开发了自己的网络事件处理器:该处理器称为文件事件处理器(file event handler)。文件事件处理程序是单线程的,因此被称为Redis的单线程模型,这也决定了Redis是单线程。

如果Redis选择多线程模型,Redis必然会涉及底层数据同步的问题,并且会引入一些同步机制,比如锁。我们知道,Redis不仅提供了简单的键值数据结构,还提供了列表、集合、哈希等丰富的数据结构,不同的数据结构对于同步访问具有不同的锁定粒度,这可能会在数据操作过程中造成大量的锁定和解锁成本,增加程序的复杂性,也会降低性能。

总的来说是避免过多的上下文切换开销,避免同步机制的开销。

三、Redis线程IO模型与基于文件的网络通信模型

1、IO模型与网络通信模型

从1.0到6.0,Redis的核心网络模型一直是单 Reactor 模型:使用epoll/select/kqueue等IO多路复用技术,在单线程事件循环处理事件(客户端请求),最后将响应数据写回客户端。如下图所示

 

其中从左到右:

Client:客户端对象,Redis是典型的CS体系结构(客户端/服务器)。客户端通过socket与服务器建立网络通道,并发送请求命令。服务器执行请求命令并回复。Redis 使用结构体 client 存储客户端的所有相关信息。

Socket:文件事件是socket操作的抽象,当socket准备好执行接受、读取、写入和关闭等操作时,将生成文件事件。服务器通常链接多个socket,多个socket可以同时生成不同的操作,每个操作对应于不同的文件事件。当相应的事件处理器执行上一个socket生成的事件时,I/O多路复用模型将向文件事件分派器发送下一个socket。

I/O多路复用模型:I/O多路复用模型将复制并侦听多个socket。尽管文件事件可能同时发生,但I/O多路复用模型会将所有生产事件的socket放入队列,并以有序、同步的方式一次一个socket将其发送给文件事件分派器。aeApiPoll基于 epoll_wait/select/kevent 等系统调用的封装,监听等待读写事件触发,然后进行处理,是事件循环中的核心功能,也是事件驱动操作的基础。

文件事件调度器(dispatcher):文件事件调度器从I/O复用器接收socket,并根据socket生成的事件类型调用相应的事件处理器

文件事件处理程序:服务器将为执行不同任务的socket关联不同的事件处理程序。这些处理程序是定义事件发生时服务器应执行的操作的函数。

2、客户端向 Redis 发起请求命令的工作原理

1、Redis服务器启动,当Redis开始初始化时,Redis会首先将事件处理器中的连接回复给处理器,AE_REASABLE事件,启动主线程事件循环(Event Loop),将连接响应处理器对应的文件描述符注册到用户配置的监听端口,并等待新连接到达;

2、客户端和服务器建立网络连接(Socket);

3、如果客户端启动与Redis的连接,产生AE_READABLE事件后被I/O多路复用程序监听到;

4、I/O多路复用程序会把监听到的socket信息放入到队列中

5、事件分派器每次都从队列中读取socket,然后事件分派器(dispatcher)将socket发送给相应的事件处理器。

6、由于命令应答处理器AE_READABLE事件与Redis初始化相关,因此连接响应处理器处理与客户端的连接建立,然后通过serverSocket逐个创建与客户端对应的socket,称为socket01,同时将这个socket01的AE_READABLE事件和命令请求处理器关联起来。

6、如果命令应答处理器完成执行,socket01事件和命令应答处理器之间的关联将被删除

7、由于命令应答处理器执行一次就足够了,如果客户端在下一次执行该操作,那么它将由命令请求处理器处理并重复执行。

四、Redis 6.0的多线程模型

在Redis v6.0正式引入多线程之前,其网络模型一直是单线程的,但是Redis早在v4.0就引入了多线程。因此,当我们讨论Redis的多线程时,有必要为Redis版本划定两个重要节点:Redis 4.0引入多线程处理异步任务、Redis 6.0 引入I/O多线程在网络模型中正式实现

1、Redis6.0版本为什么变为多线程模型?

 Redis 6.0版本中新增加的多线程模型有助于提高Redis在复杂场景下的性能、稳定性和可用性。

首先,多线程模型有助于减少Redis服务器的响应延迟,可以快速响应客户端的请求,以更好地满足客户在复杂场景下对高性能的要求。

其次,多线程模型的实现可以在复杂的场景下保证Redis的稳定性,提升Redis的可用性。

最后,多线程模型的实现有助于提高Redis的安全性,减少攻击者利用服务器的缺陷来攻击Redis的可能性。

此外,新的多线程模型也有助于简化Redis的设置,减少Redis服务器的管理成本,可以使Redis服务器更加高效管理。也就是说,多线程模型可以在复杂场景下更好地兼顾Redis服务器的性能、稳定性、可用性和安全性,从而更加高效地管理Redis服务器。

总之,Redis 6.0版本采用多线程模型的最终目的是为了提高Redis在复杂场景下的性能、稳定性和可用性,以满足客户对复杂场景下的高性能、高可用性和高安全性的要求,同时简化Redis的设置,减少Redis服务器的管理成本。 

2、Redis6.0多线程模型的工作原理

Redis 6.0采用多线程模型,是继多线程支持下的Redis 5.0之后的重要改进,其主要的作用是提高Redis的处理性能、提高Redis的处理数据量,同时缩短Redis的处理时间,以满足实际应用的要求,其工作原理如下:

1、Redis 6.0的多线程模型是基于Redis的事件模型实现的。事件模型是一种轻量级的多线程机制,它由多个事件循环组成,每个事件循环可以处理多个事件,并且它可以实现一次性分发多个任务,以达到更高的效率。

2、Redis 6.0的多线程模型采用了多种“任务”,每个任务都有自己的线程来处理,包括I/O任务、连接任务、内存任务等,以实现不同任务之间的更加有效的分发。

3、Redis 6.0中还支持客户端线程,每个客户端可以分配一个线程来处理,而不需要在单个线程中进行处理,从而实现更快的处理速度。 Redis 6.0还支持多个线程之间的消息传递,以实现线程间的信息传递,以及实现更高效的网络操作。

总之,Redis 6.0的多线程模型充分利用了更多的任务分发机制,以及线程之间的信息传递,可以在更高的效率下处理更多的数据,提供更快的响应时间,从而满足实际应用的需求。 

总结

本文深入浅出,首先分析为什么Redis是单线程的还那么快以及Redis6.0之前为什么选择单线程,深入Redis线程IO模型与基于文件的网络通信模型和客户端向 Redis 发起请求命令的工作原理,最后剖析Redis6.0版本为什么变为多线程模型,Redis6.0多线程模型的工作原理。

  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小 明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值