Redis之线程IO模型

引言

Redis是个单线程程序!这点必须铭记。除了Redis之外,Node.js也是单线程,Nginx也是单线程,但是他们都是服务器高性能的典范。

Redis单线程为什么能够这么快! 因为他所有的数据都在内存中,所有的运算都是内存级别的运算。正因为Redis是单线程,所以要小心使用Redis指令,对于那些时间复杂度为O(n)级别的指令,一定要谨慎使用,一不小心可能就会导致Redis卡顿。

Redis单线程如何处理那么多的并发客户端连接! 其答案就是多路复用

非阻塞IO

Redis使用基于事件的非阻塞IO模型,这种模型使得Redis能够在不阻塞主线程的情况下,同时处理多个客户端连接。Redis使用IO多路复用技术,通常是select、epoll、kqueue,这取决于运行Redis的操作系统。这些技术允许单个线程监视多个文件描述符,以检测是否有IO操作成为可能,例如数据可读或者可写。

读写过程

  • 读操作:当客户端发送命令到Redis服务器时,服务器使用非阻塞socket读取命令。命令读取完成后,单线程执行命令并处理数据
  • 写操作:处理完客户端命令后,生成的输出将通过非阻塞socket发送回客户端,如果数据无法一次性发送完毕(例如,输出缓冲区已满),剩余的数据会被缓存,并在socket可写时继续发送。

事件轮询(多路复用)

非阻塞IO有个问题,那就是线程要读数据,结果读了一部分就返回了,线程如何知道何时才应该继续读。也就是当数据到来时,线程如何得到通知,写也是一样,如果缓冲区满了,写不完,剩下的数据何时才能继续写,线程也应该得到通知。
在这里插入图片描述

事件轮询API就是用来解决这个问题的,最简单的事件轮询API是select函数,他是操作系统提供给用户程序的API。输入是读写描述符列表read_fds&write_fds, 输出是与之对应的可读可写事件。同时还提供了一个timeout参数,如果没有任何事件到来,那么就最多等待timeout时间,线程处于阻塞状态。一旦期间有任何事件到来,就可以立即返回。时间过了之后还是没有任何事件到来,也会立即返回。拿到事件后,线程就可以继续挨个处理相应的事件。处理完了继续过来轮询。于是线程就进入了一个死循环,我们把这个死循环称为事件循环,一个循环为一个周期。

每个客户端套接字socket都有对应的读写文件描述符。

read_events, write_events = select(read_fds, write_fds, timeout) 
for event in read_events:
 handle_read(event.fd) 
for event in write_events:
 handle_write(event.fd)
handle_others() # 处理其它事情,如定时任务等

因为我们通过select系统调用同时处理多个通道描述符的读写事件,因此我们将这类系统调用称为多路复用API。现代操作系统的多路复用API已经不再使用select系统调用,而改用epoll(linux)和kqueue(freebsd&macosx),因为select系统调用的性能在描述符特别多时性能会非常差。他们使用起来可能在形式上略有差异,但是本质上差不多,都可以使用上面的伪代码进行理解。

服务器套接字serversocket对象的读操作指调用accept接受客户端新连接,何时有新连接到来,也是通过select系统调用的读事件来得到通知。

指令队列

Redis会将每个客户端套接字都关联一个指令队列,客户端的指令通过队列来排队进行顺序处理,先到先服务。

响应队列

Redis同样也为每个客户端套接字关联一个响应队列。Redis服务器通过响应队列来将指令的返回结果返回给客户端。如果队列为空,那么意味着连接暂时处于空闲状态,不需要去获取写事件,也就是可以将当前的客户端描述符从write_fds里面移除,等到队列有数据了,再将描述符放进去,避免select系统调用立即返回写事件,如果发现没什么数据可以写。出这种情况的线程会飙高CPU。

定时任务

服务器除了要响应IO事件外,还要处理其他事情。比如定时任务就是非常重要的一件事,如果线程阻塞在select系统调用上,定时任务将无法得到准时调度。那么Redis是如何解决的呢。

Redis的定时任务会记录在一个称为最小堆的数据结构中,这个堆中,最快要执行的任务排在堆的最上方,在每个循环周期,Redis都会将最小堆里面已经到点的任务立即进行处理。处理完毕后,将最快要执行的任务还需要的时间记录下来,这个时间就是select系统调用的timeout参数。因为Redis知道未来timeout时间内,没有其他定时任务需要处理,所以可以安心睡眠timeout时间。

总结

Redis单线程,利用IO多路复用技术,单线程监听多个文件描述符,并进行事件轮询(单线程循环),轮询期间如果发生可读事件,从缓冲区中读取事件并进行处理,处理完后再将数据发送到写缓冲区写回给客户端。轮询通过select(read_fds, write_fds, timeout) 函数进行,其中timeout为轮询阻塞时间。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式系统中判断大小端的方法与实现

第一:大小端基本分析 程序判断计算机是大端的还是小端的,判断的思路是确定一个多字节的值(下面使用的是4字节的整数),将其写入内存(即赋值给一个变量),然后用指针取其首地址所对应的字节(即低地址的一个字节),判断该字…

解决:selenium运行时driver初始化失败 DevToolsActivePort file doesn‘t exist的问题

解决:selenium运行时driver初始化失败 DevToolsActivePort file doesn‘t exist的问题 DevToolsActivePort file doesnt exist报错信息:![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b3f8acc1c47d45e3912575896e421567.png)现象&#xff1…

ubuntu软件安装

目录 更新Ubuntu软件下载地址 1. 寻找国内镜像源 2. 备份Ubuntu默认的源地址 3. 更新源服务器列表 4. 更新源 更新Ubuntu软件下载地址 1. 寻找国内镜像源 所谓的镜像源:可以理解为提供下载软件的地⽅,⽐如 Android ⼿机上可以下载软件的 91 ⼿机助…

AnythingLLM 的 Docker 使用

AnythingLLM是使用大语言模型LLM的一站式简便框架。官网的介绍如下: AnythingLLM is the easiest to use, all-in-one AI application that can do RAG, AI Agents, and much more with no code or infrastructure headaches. 1. 使用官方docker 最方便的方法是使…

Day50 代码随想录打卡|二叉树篇---验证二叉搜索树

题目(leecode T98): 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右…

SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件

SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件 H2 是一个用 Java 开发的嵌入式数据库,它的主要特性使其成为嵌入式应用程序的理想选择。H2 仅是一个类库,可以直接嵌入到应用项目中,而无需独立安装客户端和服务器端。 常用开源数…

Docker部署常见应用之大数据基础框架Hadoop

文章目录 Hadoop简介主要特点核心组件生态系统 Docker Compose 部署集群参考文章 Hadoop简介 Hadoop是一个开源框架,由Apache软件基金会开发,用于在普通硬件构建的集群中存储和处理大量数据。它最初由Doug Cutting和Mike Cafarella创建,并受…

安卓照片找回不再困扰,掌握5个步骤让回忆永不褪色

手机照片记录了过去,承载着我们的回忆,让我们能够在繁忙的生活中找到那份温暖和宁静。然而,随着时间的推移和技术的进步,照片的存储和备份方式也在不断变化。当我们不小心删除了手机里的照片时,那份失落和焦虑便油然而…

【Python】数据处理:SQLite操作

使用 Python 与 SQLite 进行交互非常方便。SQLite 是一个轻量级的关系数据库,Python 标准库中包含一个名为 sqlite3 的模块,可以直接使用。 import sqlite3数据库连接和管理 连接到 SQLite 数据库。如果数据库文件不存在,则创建一个新数据库…

家用洗地机前十名排行榜:2024十大热销款式好用不踩雷

洗地机强大的清洁力和高效的清洁效率,迅速代替了吸尘器、电动拖把、蒸汽拖把的位置,成为家庭地面清洁的新宠,各大厂商也纷纷上新自家新品。但是这个也造成了人们在挑选机型的时候无从下手,甚至很多新手购机,几乎对洗地…

【学习笔记】finalshell上传文件夹、上传文件失败或速度为0

出现标题所述的情况,大概率是finalshell上传文件的过程中的权限不够。 可参照:Finalshell上传文件失败或者进度总为百分之零解决方法 如果不成功,建议关闭客户端重试。 同时建议在设置finalshell的ssh连接时根据不同用户设置多个连接&#xf…

【git使用一】windows下git下载、安装和卸载

目录 (1)下载安装包 (2)安装git (3)安装验证 (4)卸载git (1)下载安装包 官网下载地址:Git 国内镜像下载地址:CNPM Binaries Mir…

[C++] 从零实现一个ping服务

💻文章目录 前言ICMP概念报文格式 Ping服务实现系统调用函数具体实现运行测试 总结 前言 ping命令,因为其简单、易用等特点,几乎所有的操作系统都内置了一个ping命令。如果你是一名C初学者,对网络编程、系统编程有所了解&#xff…

Qt creator day1 练习

自由发挥登录窗口的应用场景,实现一个登录窗口界面,要求:第行代码都有注释 #include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {this->setWindowTitle("贪玩蓝月——是兄弟就来砍我 登入&#…

[亲测好用]10个热门音频剪辑软件分享,快来看看你适合哪种

市面上的音频剪辑软件千千万,要想找到适合自己的音频剪辑软件的话,还是需要多多对比。今天小编总结了市面上比较热门的10款热门音频剪辑软件来进行对比测评,希望可以通过这篇文章可以帮助你找到适合自己的音频剪辑软件。 音频剪辑软件一&…

论文研读|以真实图像为参考依据的AIGC检测

前言:这篇文章介绍几篇AIGC检测的相关工作,其中前几篇文章是以真实图像的特征作为标准进行检测,最后一篇文章就当拓展一下知识边界吧~ 目录 Detecting Generated Images by Real Images Only (202311 arXiv)Let Real Images be as…

高速直线导轨驱动与控制,精准稳定的运动核心元件

直线导轨在工业生产中,精度和稳定性是至关重要的。而在各种机械设备中,高精度直线导轨是提高设备运动控制精度和平稳性的核心部件,当我们考虑高速运动时,直线导轨的精度和稳定性是非常重要的因素。 直线导轨系统中如何确保高速运动…

美丽的拉萨,神奇的布达拉宫

原文链接:美丽的拉萨,神奇的布达拉宫 2022年11月30日,可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5,将人工智能的发展推向了一个新的高度。2023年11月7日,OpenAI首届…

Selenium - 启动后报org.openqa.selenium.InvalidArgumentException: invalid argument错

● 出现的异常: Build info: version: 3.141.59, revision: e82be7d358, time: 2018-11-14T08:25:48 System info: host: DESKTOP-H7TOMMO, ip: 192.168.64.1, os.name: Windows 10, os.arch: amd64, os.version: 10.0, java.version: 1.8.0_131 Driver info: dr…

git 常用操作指令

文章目录 git clonegit configgit addgit commitgit rmgit branch/checkoutgit pull/push git clone git clone 可以将一个远程 Git 仓库拷贝到本地,让自己能够查看该项目,或者进行修改。 拷贝项目命令格式如下:git clone [url] [url] 是你要…