目录

Redis网络模型

1、用户空间和内核空间

阻塞IO

非阻塞IO

2、IO多路复用

信号驱动IO

异步IO

Redis网络模型(面试)

3、Redis通信协议

RESP协议

Redis网络模型

1、用户空间和内核空间

为了避免用户应用导致冲突甚至内核崩溃,用户应用与内核是分离的:

  • 进程的寻址空间会划分为两部分:内核空间、用户空间

  • 用户空间智能执行受限的命令(Ring3),而且不能直接调用系统资源,必须通过内核提供的接口来访问

  • 内核空间可以执行特权命令(Ring0),调用一切系统资源

Linux系统为了提供IO效率,会在用户空间和内核空间加入缓冲区:

  • 写数据时,把用户缓冲数据拷贝到内核缓冲区,然后写入设备

  • 读数据时,从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区


阻塞IO

阻塞IO就是两个阶段都必须阻塞等待:


非阻塞IO

非阻塞IO的recvfrom操作会立即返回结果而不是阻塞用户进程

非阻塞IO模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。虽然是非阻塞,但性能并没有得到提高。

相反可能导致CPU使用率暴增


2、IO多路复用

文件描述符:简称FD,是一个从0开始递增的无符号整数,用来关联linux中的一个文件。在linux中,一切皆为文件。

IO多路复用:是利用单个线程来同时监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待

监听FD的方式、通知的方式有多种实现,常见的有:

  • select(linux最早的IO多路复用)

  • poll

  • epoll

差异:

1、select和poll只会通知用户进程有FD就绪,但不确定具体哪个FD,需要用户进程逐个遍历FD来确定

2、epoll则会在通知用户进程FD就绪的同时,把已就绪的FD写入用户空间

事件通知机制

当FD有数据可读时,我们调用epoll_wait就可以得到通知。

事件通知分为两种:

LevelTriggered: 简称LT。当FD有数据可读时,会重复通知多次,直至数据处理完成。是Epoll默认模式

EdgeTriggered:简称ET。当FD有数据可读时,只会被通知一次,不管数据是否处理完成

基于epoll模式的web服务基本流程图:


信号驱动IO

信号驱动IO是与内核建立SIGIO的信号关联并设置回调,当内核有FD就绪时,会发出SIGIO信号通知用户,期间用户应用可以执行其他业务,无需阻塞等待

缺点:

1、当有大量IO操作时,信号较多,SIGIO处理函数不能及时处理可能导致信号队列溢出

2、内核空间与用户空间的频繁信息交互新能低


异步IO

异步IO的整个过程都是非阻塞,用户进程调用完异步API后就可以做其他事情,内核等待数据就绪并拷贝到用户空间后才会递交信号,通知用户进程


Redis网络模型(面试)

Redis到底是单线程还是多线程?

  • 如果仅仅聊Redis的核心业务部分(命令处理),是单线程

  • 如果是聊整个Redis,答应就是多线程

💖在Redis版本迭代过程中,在两个重要的时间节点上引入了多线程的支持:

Redis v4.0 :引入多线程异步处理一些耗时较长的任务,例如异步删除命令unlink

Redis v6.0:在核心网络模型中引入多线程,进一步提高对于多核CPU的利用率

为什么Redis要选择单线程?

😎抛开持久化不谈,Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大性能提升

😁多线程会导致过多的上下文的切换,带来不必要的开销

❤️引入多线程会面临线程安全问题,必然要引入线程锁这样安全手段,实现复杂度增高,而且性能也会大打折扣

Redis单线程整个网络模型:

Redis6.0版本引入多线程,目的是为了提高IO读写效率。因此在解析客户端命令、写响应结果采用了多线程

核心的命令执行、IO多路复用模块依然是由主线程执行


3、Redis通信协议

RESP协议

Redis是一个CS架构软件,通信一般分为两步(不包括pipeline和PubSub):

1、客户端(client)向服务端(server)发送一条命令

2、服务端解析并执行命令,返回响应结果给客户端

  • 因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通信协议

在Redis中采用的是RESP协议:

😀Redis 1.2版本引入RESP协议

😁Redis 2.0版本中成为与Redis服务端通信的标准,称为RESP2

😆Redis 6.0版本中,从RESP2升级到RESP3协议,增加了更多数据类型并且支持6.0的新特性——客户端缓存

RESP协议—数据类型:

在RESP协议中,通过首字节的字符来区分不同数据类型,常用的数据类型有5种:

类型 首字节 格式示例 说明
单行字符串 + +OK\r\n 简单状态回复,如 "OK"
错误信息 - -Error msg\r\n 错误回复,如 "-ERR unknown command"
整数 : :100\r\n 数字回复,如 :1
多行字符串 $ $5\r\nhello\r\n 二进制安全的字符串$0\r\n\r\n 表示空串$-1\r\n 表示 null/不存在
数组 * *2\r\n$5\r\nhello\r\n$5\r\nworld\r\n 多个元素的组合,用于命令和回复


Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐