【Redis知识点总结】(二)——Redis高性能IO模型剖析

Redis知识点总结(二)——Redis高性能IO模型及其事件驱动框架剖析

  • IO多路复用
    • 传统的阻塞式IO
    • 同步非阻塞IO
    • IO多路复用机制
  • Redis的IO模型
  • Redis的事件驱动框架

IO多路复用

Redis的高性能的秘密,在于它底层使用了IO多路复用这种高性能的网络IO,IO多路复用是一种高性能的IO机制。

传统的阻塞式IO

传统的同步阻塞式IO,一个IO连接对应一个线程,也就是说一个线程只能监听一个IO连接,并且在没有数据到达前,这个线程会阻塞等待数据的到达,在数据到达后,才把数据读取到应用程序的内存区域。

比如我们熟悉的socket编程,就是典型的同步阻塞式网络IO,ServerSocket的accept()方法监听指定端口接收客户端建立连接,此时当前线程会阻塞,等待客户端发起连接。建立连接后返回一个Socket表示与客户端建立了一个连接,然后我们创建一个线程Thread,在线程中调用Socket的read()方法,等待客户端发送数据,如果客户端迟迟不发送数据,那么该线程将会一直被阻塞

在这里插入图片描述

这是一种性能比较低的IO机制,原因在于一个线程只能监听一个连接,并且在数据没有到达之前,需要阻塞等待。

同步非阻塞IO

而同步非阻塞式IO则不一样,它可以尝试性的读取看看是否有数据,如果没有数据可以立即返回,不会阻塞,当前线程可以去干点别的事情,然后再次回来尝试读取,如果发现有数据到达,才会阻塞当前线程,当前线程会把数据读取到应用程序用户空间。

在这里插入图片描述

在没有数据达到前,当前线程不会阻塞,因此叫非阻塞式IO,而有数据达到时,数据读取的工作是当前线程自己处理的(异步IO不需要线程自己读取数据),因此又叫同步IO,合在一起就是同步非阻塞IO。

这种IO机制虽然不会阻塞当前线程,但是不停尝试读取的做法非常消耗CPU资源,于是就有了IO多路复用。

IO多路复用机制

IO多路复用最大的特点就是一个线程可以监听多个socket。在Linux操作系统里面,提供了select、poll、epoll三种IO多路复用API,由于Redis底层使用的时epoll,我们就分析一下epoll这种IO多路复用机制。

epoll这种IO多路复用机制有三个函数,分别是epoll_create、epoll_ctl、epoll_wait。epoll_create的作用是创建一个epoll实例,这个epoll实例是一个IO多路复用器,里面使用一个红黑树结构存储注册进来的socket文件描述符,当某个socket有数据到达或有连接需要建立时,又会把该socket复制到一个链表结构当中;epoll_ctl则是把一个socket文件描述符注册到epoll实例当中;epoll_wait则是获取epoll实例中已经有事件就绪的socket,也就是epoll实例中的链表,把该链表拷贝到用户空间,当前线程就可以遍历该链表进行处理。

在这里插入图片描述

如果是建立连接事件,则调用socket的accept()函数建立连接获取另一个socket,把该socket注册到epoll实例中,如果是有数据达到,则调用socket的read()函数读取数据,如果是有数据需要写出,则调用socket的write()函数。

在这里插入图片描述

Redis的IO模型

redis基于IO多路复用进行封装,就有了自己的IO模型。Redis的IO模型是单线程Reactor模型,也就是事件监听(reactor)、建立建立连接(acceptor)、事件处理(handler),都由同一个线程负责。这里的reactor、acceptor、handler是IO模型中的三种角色,三个角色可以由不同线程担当,也可由同一个线程担当,在单线程Reactor这种IO模型中,显然三种角色都是由同一个线程担当。此时reactor表示事件监听的处理逻辑,acceptor表示连接建立的处理逻辑,handler表示处理读写事件的逻辑。

在这里插入图片描述

在单线程reactor这种IO模型下,程序会启动一个主线程,主线程启动时,会调用epoll的epoll_create函数创建一个epoll实例,并创建一个socket,调用listen函数把它转成监听socket,调epoll_ctl函数,注册到epoll实例中。然后主线程会调用epoll中的epoll_wait函数,监听注册到epoll实例中的所有socket,一旦有事件就绪就会进行事件分派,分派给acceptor或handler处理,这就是reactor的逻辑,

在这里插入图片描述

当注册到epoll实例中的socket有事件就绪,epoll_wait函数就会返回,当前线程就会遍历有事件就绪的socket,根据事件类型进行事件分派。如果是建立连接事件,就会调用acceptor的逻辑处理,acceptor中的逻辑就是调用socket.accept()获取已建立连接的socket,然后调用epoll_ctl把该socket注册到epoll实例;如果是读写事件,就会调用handler的逻辑处理读写事件,读事件的处理就是调用socket.read()获取数据然后进行相应处理,写事件就是调用socket.write()把数据写出。

在这里插入图片描述

Redis的事件驱动框架

基于这种单线程reactor的IO模型,redis就封装出了自己的事件驱动框架。

在这里插入图片描述

整个Redis事件驱动框架的主体逻辑就是一个主线程的死循环,在循环中,当前线程调用epoll_wait进行监听,获取有事件就绪的socket,然后放入一个队列,所有socket都放入队列后,会遍历队列中的socket进行事件分派。如果是连接建立事件,就会调用socket.accept()建立连接,然后调用epoll_ctl函数把返回的socket注册到epoll实例中;如果是读就绪事件,就调用socket.read()函数读取客户端发送的数据,也就是客户端发来的redis命令,然后执行该redis命令对应的函数;如果是写就绪事件,则调用socket.write()函数把数据写出。

Redis的核心逻辑是单线程处理,但不表示Redis真的就只有一个线程,一些文件关闭、惰性删除、AOF文件刷盘、执行bgsave命令写内存快照等任务,还是由后台线程来执行,所以Redis并不是真正的单线程。

在这里插入图片描述

在Redis的6.0版本开始,引入了多线程IO读写机制,此时Redis的事件驱动框架,在处理IO读写时会使用多线程的方式进行处理,而核心逻辑(也就是redis的命令处理)还是由一个主线程执行。

在这里插入图片描述

Redis会把所有读就绪的socket以轮询的方式分配给所有IO线程处理,IO线程会读取socket中的数据,然后主线程等待所有的IO线程读取完毕,再进行命令处理。处理完毕后,需要把处理结果写回客户端时,Redis再次进行分配,把待写回数据的socket分配给IO线程进行数据写回。

这样,即保持了Redis单线程处理的核心逻辑不变,又通过多线程IO读写这种机制,提升了IO读写的速度,从而进一步提升Redis的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/526939.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年装修新潮流,你get到了吗?福州中宅装饰,福州装修

在装修这个行业,每年都会出现一些新的设计理念和流行趋势,同时也存在一些传统的设计理念。今天,我们就来对比一下2024年装修设计的传统与新趋势。 传统设计理念 1. 落地电视柜 在过去,落地电视柜被认为是一种实用的设计&#xf…

React-路由小知识

1.默认路由 说明:当访问的是一级路由时,默认的二级路由组件可以得到渲染,只需要在二级路由的位置去掉path,设置index.属性为true。 2.404路由 说明:当浏览器输入ul的路径在整个路由配置中都找不到对应的pth,为了用户体验&#x…

深入理解React中的useReducer:管理复杂状态逻辑的利器

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

Coggle数据科学 | 小白学数据科学:20个技术和框架(建议收藏!)

本文来源公众号“Coggle数据科学”,仅用于学术分享,侵权删,干货满满。 原文链接:小白学数据科学:20个技术和框架 随着互联网使用率的增长,公司如何利用数据进行创新和获得竞争优势。截至2024年1月&#x…

Qt 实现诈金花的牌面值分析工具

诈金花是很多男人最爱的卡牌游戏 , 每当你拿到三张牌的时候, 生活重新充满了期待和鸟语花香. 那么我们如果判断手中的牌在所有可能出现的牌中占据的百分比位置呢. 这是最终效果: 这是更多的结果: 在此做些简单的说明: 炸弹(有些地方叫豹子) > 同花顺 > 同花 > 顺…

css--浮动

一. 浮动的简介 在最初,浮动是用来实现文字环绕图片效果的,现在浮动是主流的页面布局方式之一。 二. 元素浮动后的特点 🤢脱离文档流。😊不管浮动前是什么元素,浮动后:默认宽与高都是被内容撑开&#xff0…

[HackMyVM]靶场 Espo

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

manjaro 安装 wps 教程

内核: Linux 6.6.16.2 wps-office版本: 11.10.11719-1 本文仅作为参考使用, 如果以上版本差别较大不建议参考 安装wps主体 yay -S wps-office 安装wps字体 (如果下载未成功看下面的方法) yay -S ttf-waps-fonts 安装wps中文语言 yay …

ZJUBCA研报分享 | 《BTC/USDT周内效应研究》

ZJUBCA研报分享 引言 2023 年 11 月 — 2024 年初,浙大链协顺利举办为期 6 周的浙大链协加密创投训练营 (ZJUBCA Community Crypto VC Course)。在本次训练营中,我们组织了投研比赛,鼓励学员分析感兴趣的 Web3 前沿话题…

kali当中不同的python版本切换(超简单)

kali当中本身就是自带两个python版本的 配置 update-alternatives --install /usr/bin/python python /usr/bin/python2 100 update-alternatives --install /usr/bin/python python /usr/bin/python3 150 切换版本 update-alternatives --config python 0 1 2编号选择一个即可…

【Linux】Shell及Linux权限

Shell Shell的定义 Shell最简单的定义是:命令行解释器。 Shell的主要任务:1. 将使用者的命令翻译给核心进行处理。2.将核心的处理结果翻译给使用者 为什么要有Shell? 使用者和内核的关系就相当于两个完全陌生的外国人之间的关系,他们要进…

农场管理小程序|基于微信小程序的农场管理系统设计与实现(源码+数据库+文档)

农场管理小程序目录 目录 基于微信小程序的农场管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、农场信息管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 五、核心代码 七、最新计算机毕设选题推荐 八、源码获取&#x…