谈谈Redis中的多路复用

目录

前言

什么是多路服用

Redis中的多路复用

Redis单线程?多线程?


前言

redis是单线程的(不严谨的讲法的哈),为什么还这么快,很多人相信会回答因为redis是基于内存操作的, 内存的读写速度是非常快的。答到这,逼格还是不够高的,基于内存是一方面,但还有一个关键点是:redis采用了多路复用技术,今天我们就来聊聊这个点。

什么是多路服用

  • ​多路:多个客户端连接
  • 复用:使用单进程就能够实现同时处理多个客户端的连接 ​

它的基本原理就是不再由应用程序自己监视连接,而是由内核替应用程序监视文件描述符。客户端在操作的时候,会产生具有不同事件类型的 socket。在服务端,I/O 多路复用程序(I/O Multiplexing Module)会把消息放入队列中,然后通过文件事件分派器(Fileevent Dispatcher),转发到不同的事件处理器中。

可以想象一条高速公路,车辆在不同的车道上行驶,但它们共用同一条路。 

I/O多路复用的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符, 一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作

在Unix/Linux系统中,常用的IO多路复用机制有以下几种:

  • select:是最早引入的IO多路复用机制,通过select函数来监视多个文件描述符的状态变化,但其缺点是性能不高,同时对文件描述符的数量有一定的限制。
  •  poll:是select的改进版本,没有了描述符数量的限制,但其性能仍然不是很高。
  • epoll:是Linux特有的IO多路复用机制,是目前性能最好的IO多路复用技术。它使用了事件驱动的方式,通过epoll_ctl函数注册文件描述符的事件,然后通过epoll_wait函数等待IO事件的发生。epoll在处理大量连接时具有更好的扩展性和性能。

epoll 最大的优点就在于它只管你“活跃”的连接 ,而跟连接总数无关,因此在实际的网络环境
中, epoll 的效率就会远远高于 select 和 poll 。 (redis 的iO模型默认采用epoll实现的。)

IO多路复用的主要优点包括:

  •  节省了线程/进程的创建和销毁开销,降低了系统资源的占用。
  •  可以实现高并发处理,提高系统的性能和吞吐量。
  • 编程模型相对简单,代码量较少,易于维护和管理。
selectpollepoll
操作方式遍历遍历回调
数据结构bitmap数组红黑树
最大连接数1024(x86)或者2048(x64)无上限无上限
最大支持文件描述符数有最大值限制6553565535
fd拷贝每次调用,都需要把fd结合从用户态拷贝到内核态每次调用,都需要把fd结合从用户态拷贝到内核态只有首次调用的时候拷贝
工作效率每次都要遍历所有文件描述符,时间复杂度O(n)每次都要遍历所有文件描述符,时间复杂度O(n)每次只用遍历需要遍历的文件描述符,时间复杂度O(1)

Redis中的多路复用

Redis 是跑在单线程中,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以IO操作一般情况下往往不能直接返回,这会导致某一文件的I/O 阻塞导致整个进程无法对其他客户提供服务,I/O多路复用是为了解决这个问题而出现的。

Redis中的IO多路复用模式:

  • (1)一个 socket 客户端与服务端连接时,会生成对应一个套接字描述符(套接字描述符是文件描述符的一种),每一个 socket 网络连接其实都对应一个文件描述符。
  • (2)多个客户端与服务端连接时,Redis 使用 「I/O 多路复用程序」 将客户端 socket 对应的 FD 注册到监听列表(一个队列)中。当客服端执行 read、write 等操作命令时,I/O 多路复用程序会将命令封装成一个事件,并绑定到对应的 FD 上。
  • (3)「文件事件处理器」使用 I/O 多路复用模块同时监控多个文件描述符(fd)的读写情况,当 acceptreadwriteclose 文件事件产生时,文件事件处理器就会回调 FD 绑定的事件处理器进行处理相关命令操作。
  • (4)整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,当其中一个 client 端达到写或读的状态,文件事件处理器就马上执行,从而就不会出现 I/O 堵塞的问题,提高了网络通信的性能。

这种IO多路复用机制能够有效地减少系统调用和上下文切换的开销,提高了Redis的性能和并发能力。同时,由于采用了非阻塞IO模型,Redis能够处理大量的连接而不会造成线程堵塞,提高了系统的可伸缩性。

Redis单线程?多线程?

Redis 在处理客户端的请求时,包括获取 (socket 读)、解析、执⾏、内容返回 (socket 写) 等都由⼀个顺序串⾏的主线程处理,这就是所谓的「单线程」

Redis是单线程来执行命令的,每一条到达读服务端的命令并不会立即执行,所有的命令都会进入一个 socket 任务队列中,当 socket 可读则交给单线程事件分发器逐个被执行,即一个线程处理所有网络请求

Redis 采⽤多个 IO 线程来处理⽹络请求,提⾼⽹络请求处理的并⾏度。Redis 多 IO 线程模型只⽤来处理处理网络数据的读写和协议解析,对于 Redis 的读写命令,依然是单线程处理。

因为网络 I/O 在 Redis 执行期间占用了大部分 CPU 时间, 所以把网络 I/O 部分单独抽离出来, 做成多线程的方式。这里所说的多线程, 其实就是将 Redis 单线程中做的这两件事情"从客户端读取数据、回写数据给客户端"(也可以称为网络 I/O), 处理成多线程的方式, 但是"执行 Redis 命令"还是在主线程中串行执行, 这个逻辑保持不变 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一个风轻云淡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值