redis再战之IO网络传输演变与区别《二》

【Redis】『2』NIO在redis中的应用和演变 关于I/O多路复用(事件驱动),首先要理解的是,操作系统为你提供一个功能,当你的某个socket可读或可写的时候,它可以给你一个通知。这样当配合非阻塞的socket使用时,只有当系统通知我哪个描述符可读了,我才去执行read操作,可以保证每次read都能读到有效数据而不做纯返回或无用功,写操作类似,操作系统的这个功能是通过select/poll/epoll/kqueue之类的系统调用函数来实现,这些函数都可以见识多个描述符的读写就绪状况,这样,多个描述符的I/O操作都能在一个线程内并发交替的顺序完成,这就叫 阅读详情

BIO、NIO、Epoll发展历程以及原理回顾

BIO原理与缺陷

在这里插入图片描述
Linux有OS内核,内核会有很多的Client连接,这些连接就是文件描述符(fd8,fd9),程序/进程/线程可以从kernel中read这些描述符获得数据。
在BIO时期,当Client1想要发送数据给Server,首先要先把数据通过fd8(假设)发送给kernel,再由Server进程1 read(fd8)得到数据进行计算处理,处理的时候进程1不能做别的事情,是一个阻塞的状态,这个时候如果Client2也来数据了,Server需要再开启一个进程2才能处理Client2发送过来的数据。

这样就引发很多问题:
JVM开辟一个线程的成本为1M,造成了内存的浪费。
线程多了CUP调度会有压力。
如果在只有一个CPU的情况下,CPU在调度进程1的时间片里,数据没到,进程1会block。这个时候如果进程2的数据包到了,但是CPU的时间片在处理进程1,还没有轮到进程2,所以进程2需要等待进程1CPU时间片结束后才能得到处理。

NIO的原理与缺陷

为了解决BIO的问题,kernel发生了改变,诞生了同步非阻塞NIO。
在这里插入图片描述
这里kernel的改变是指建立连接后socket对应的fd是nonblock(非阻塞,不必等read数据完成后才能做其他事),那么就可以使用一个线程,在这个线程里可以写一个while循环遍历这些fd(文件描述符),检查哪些fd有数据到达。

需要注意的问题是:

同步:遍历和处理数据都是一个线程来完成的。
非阻塞:指的是socket I/O非阻塞,不阻塞线程而导致后面的代码无法执行。
优点:同步非阻塞NIO,通过修改内核fd非阻塞的方式,可以使用一个线程完成对数据的读取,减少了线程的创建和CUP切换线程所带来的的成本。
缺点:轮询发生在用户空间,如果有1000个fd,轮询一次需要调用1000次kernel的成本依然很大(用户态到内核态的切换过于频繁)。

同步非阻塞NIO 到 多路复用NIO

在这里插入图片描述
为了解决同步非阻塞NIO调用内核过于频繁的问题,kernel又发生了改变。
在socke非阻塞的基础上,kernel添加了新的OS调用select。select如何工作呢?就是Client发送数据给Server的进程会建立fd(文件描述符),进程收到多少描述符都会传递给select,由select监控这些fd是否有数据包到达。之前同步非阻塞NIO轮询检查数据到达是发生在用户态,而 多路复用NIO 是把检查轮询的工作转移到了kernel。select监控到有fd并且把这些fd从新发送给Server进程,Server进程遍历这些fd查看哪些标记为有数据到达,根据这些有数据到达的fd调用read(fd)读取数据。

优点:相较于同步非阻塞NIO,减少了调用kernel调用的频率。
缺点:fd相关数据在用户态和内核态之间传递其实是一个copy的过程,并且server要遍历查看标记哪些fd有数据,还是会造成资源的损耗。

多路复用NIO 到 epoll

在这里插入图片描述
在epoll的模型中,用户空间进程会先创建epoll的fd,只要外界有连接到进程,进程就会把和外界连接的fd写给epoll的fd,然后内核的epoll会准备一个mmap的映射,就是用户态和内核态的fd对应数据位置做了一个映射,mmap的本质是给用户态和内核态建立一个共享空间,这个共享空间里有一个红黑树的数据结构和一个链表的数据结构,epoll再把收到的fd存到这个共享空间的红黑树,内核检测红黑树中的fd哪个有数据了,就把这个fd放到链表中。用户空间进程调用wait()等待,只要Client那边有数据了,wait就可以返回变成不阻塞从链表中取出fd,然后用户空间的进程可以直接调用read(fd)读取数据就可以了。

select poll和epoll的区别

select的几大缺点:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024

poll实现

poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制。poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。

epoll

epoll既然是对select和poll的改进,就应该能避免上述的三个缺点。那epoll都是怎么解决的呢?在此之前,我们先看一下epoll和select和poll的调用接口上的不同,select和poll都只提供了一个函数——select或者poll函数。而epoll提供了三个函数,epoll_create,epoll_ctl和epoll_wait,epoll_create是创建一个epoll句柄;epoll_ctl是注册要监听的事件类型;epoll_wait则是等待事件的产生。
对于第一个缺点,epoll的解决方案在epoll_ctl函数中。每次注册新的事件到epoll句柄中时(在epoll_ctl中指定EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝。epoll保证了每个fd在整个过程中只会拷贝一次。
对于第二个缺点,epoll的解决方案不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd(利用schedule_timeout()实现睡一会,判断一会的效果,和select实现中的第7步是类似的)。
对于第三个缺点,epoll没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。

总结:

(1)select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。
(2)select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。

(2024,DDPM,DDIM,流匹配,SDE,ODE)扩散:基础教程 本文的目标是尽可能简单地教授扩散。第一节介绍扩散的基本原理。第二节和第三节展示如何构建随机和确定性扩散采样器。第四部分介绍了密切相关的流匹配,可看作是扩散的推广。​第五节,强调实践中最重要的一些设计选择,包括采样器、噪声时间表和参数化方法。 阅读详情

相关推荐

大模型的安全发展与安全治理

2022 年底,OpenAI 推出的 ChatGPT 在文本生成领域实现了重大突破,引领了大模型技术的发展方向,推动了各式各样的基座大模型及行业大模型的发展,并逐步向多模态和具身化方向迅速演进。显然,大模型展现出的强大能力为人工智能通用化揭开了序幕。然而,大模型技术的安全性也面临着生成内容的安全性、伦理道德等重大挑战。只有积极确保大模型的安全性,才能更有效地推动其持续发展,进而更好地应对大模型技术变革所带来的机遇与挑战。

qq_41432686的博客 2582

Redis的IO模式详解

redis的底层io模式详细解释,io多路复用epoll

一个有信仰的技术人 1976

VS2022配置Qt6

VS2022配置QT教程

Life is a struggle ! 6358

Redis:Redis的IO模型

因为多线程并不一定就代表线程越多速度越快,再多线程的场景下,我们不得不去考虑针对共享变量的管理,也就是说针对并发所需要进行的处理往往会导致额外的开销或者说通过互斥锁等机制让并行变串行,因此增加线程并未让系统的吞吐率变高,反而因为加入了同步的机制,往往造成程序难于维护和调试。redis网络框架调用epollo机制,就不会出现上面所说的阻塞点的情况的产生,因为redis不会阻塞在一个特定的连接/监听套接字上,所以不会因为一个客户端的请求而堵塞其他客户端的请求,提高了并发性。耗时的操作包括以下几种。

张豫湘的博客 799

python解析通达信dat与blk数据文件【附源码】

本文介绍了一个完整的通达信金融数据解析器项目,该项目攻克了通达信专有二进制文件格式解析的技术难题。项目采用模块化架构,从基础二进制解析到增强数据分类,最终实现智能语义化列名生成,形成完整的数据处理链路。核心技术包括自适应编码检测、智能数据类型推断和基于业务规则的语义化处理,解决了逆向工程、多编码兼容性等挑战。项目成果显著,解析成功率达100%,数据可读性大幅提升,开发效率提高50%,为量化交易、可视化分析等场景提供了可靠数据支持。该方案不仅具备技术创新性,更具有实际工程应用价值,为金融数据分析领域提供了可复

qq_36224726的博客 2687

从零开始:手把手教你做转录组与代谢组的联合分析(含R代码)

本文详细介绍了转录组与代谢组联合分析的全流程,包括数据准备、预处理、差异分析及可视化方法,并提供了实用的R代码示例。通过多组学整合分析,研究者可以更全面地理解生物过程,适用于疾病机制和药物开发等医学研究领域。

weixin_29306317的博客 436

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

整个Redis事件驱动框架的主体逻辑就是一个主线程的死循环,在循环中,当前线程调用epoll_wait进行监听,获取有事件就绪的socket,然后放入一个队列,所有socket都放入队列后,会遍历队列中的socket进行事件分派。如果是建立连接事件,则调用socket的accept()函数建立连接获取另一个socket,把该socket注册到epoll实例中,如果是有数据达到,则调用socket的read()函数读取数据,如果是有数据需要写出,则调用socket的write()函数。

weixin_43889578的博客 1626

科研人必备!用WisPaper搭建个人文献知识库的完整指南(附Zotero联动技巧)

本文详细介绍了如何利用WisPaper搭建高效的个人文献知识库,包括文件命名标准化、文件夹结构设计、语义搜索技巧及与Zotero的深度联动方法。通过智能标签系统和知识图谱功能,科研人员可以快速定位关键文献,提升研究效率。特别适合需要管理大量学术文献的研究者。

weixin_30823001的博客 266

Redis原理 - IO详解

能监听的 FD 最大不超过 1024 个每次 select 都需要把所有要监听的 FD 都拷贝到内核空间每次都要遍历所有 FD 来判断就绪状态poll 利用链表解决了 select 中监听 FD 上限的问题,但是依然要遍历所有的 FD ,如果监听较多,性能会下降基于 epoll 实例中的红黑树保存要监听的 FD ,理论上无上限,而且增删改查效率都非常高,性能不会随监听的 FD 数量增多而产生显著的下降。

一个编程爱好者的博客 1903

【本体】Protege高效批量导入实例(Individuals)的自动化实践

本文详细介绍了在Protege中高效批量导入实例(Individuals)的自动化实践方法。通过分析Protege本体文件结构,提供Python脚本示例,帮助用户快速处理大规模数据导入,显著提升知识图谱构建效率。特别适合需要处理数千个实例的医疗、制药等领域应用。

weixin_30275415的博客 408

【学习系列】SAP RAP 29:如何创建Application Jobs(下)

本文介绍了在SAP系统中通过API创建和使用Application Jobs的方法。主要内容包括:1) 创建RAP应用并通过Action调用API创建Jobs;2) 使用事件驱动方式异步更新Job状态;3) 通过URL跳转到标准日志页面;4) 使用Custom Entity获取Job日志;5) 演示遗留接口IF_APJ_DT_EXEC_OBJECT和IF_APJ_RT_EXEC_OBJECT的使用。文章提供了详细的代码示例,展示了如何通过CL_APJ_RT_API=>SCHEDULE_JOB调度作业,

DeveloperMrMeng的博客 373

redis IO多路复用机制

redis IO多路复用机制

水w的博客 3040

【Windows Server 2019】存储服务器的配置和管理——iSCSI的安装和配置(下)

博文介绍了如何使用Windows 10 和 ESXi 验证iSCSI服务器部署成功以及如何管理iSCSI服务 。

VMware, Windows, Linux, Cisco, Container, Kubernetes, Kali 7999

Netty入门(二)——网络传输

Netty底层原理解析:从五种I/O模型到高性能实现 本文深入剖析了Netty高性能网络通信的底层原理。首先介绍了阻塞I/O、非阻塞I/O、I/O多路复用等五种I/O模型,重点分析了epoll的优势。其次详细解读了Reactor线程模型及其在Netty中的实现方式,包括EventLoop和EventLoopGroup的工作机制。针对网络通信中的TCP拆包粘包问题,提供了定长报文、分隔符报文等解决方案。最后阐述了Netty的编解码器机制,包括Encoder/Decoder分类及自定义协议设计要点。Netty通

记不住所以写下来 856

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

【Redis】多路复用IO、Reactor模型

目录一、UnixIO的五种类型非阻塞IO事件轮询(多路复用)附. Java中的线程模型 Redis是个单线程程序。因为它所有的数据都存在内存中,所有的运算都是内存级别的运算。那么既然是单线程,如何处理并发的客户端连接? 一、UnixIO的五种类型 一个输入操作通常包括两个阶段: 等待数据准备好:等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。 从内核向进程复制数据:把数据从内核缓冲区复制到应用进程缓冲区。 一般情况下有5种类型: (同步)阻塞式 I/O 应用进程被阻塞,直到数

sun_tantan的博客 1405

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Redis常见性能问题

通常我们会将含有较大数据或含有大量成员、列表数的Key称之为大Key。value是STRING类型,它的值超过5MBvalue是ZSET、Hash、List、Set等集合类型时,它的成员数量超过1w个上述的定义并不绝对,主要是根据value的成员数量和大小来确定,根据业务场景确定标准。如果一个 key 的访问次数比较多且明显多于其他 key 的话,那这个 key 就可以看作是hotkey(热 Key)。

SevenCoding的博客 870

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Socket.IO WebTransport架构解析:下一代网络传输协议深度实现

Socket.IO作为现代实时通信领域的领先解决方案,近期正式集成了WebTransport协议支持,为开发者提供了基于HTTP/3和QUIC协议的下一代网络传输技术。本文将深入解析Socket.IO WebTransport的技术架构实现细节,探讨其在分布式系统中的应用价值,并提供基于实际源码的技术实践指南。 ## 技术架构深度解析 WebTransport协议基于HTTP/3和QUIC协议

gitblog_00005的博客 602

NoSQL之 Redis配置与优化

正常情况下,大部分的访问请求应该时先被redis缓存响应,在redis那里得不到响应的小部分访问请求才会去请求MySQL数据库获取数据,这样MySQL数据库的负载压力会非常小,能够正常稳定工作。6)开启lazy-free机制(lazyfree-lazy-* yes),将删除过期key的操作放到后台线程执行,减少大量的删除操作对redis主进程的阻塞。持久化保存的文件占用空间更大,恢复速度更慢,性能影响更大,AOF文件重写期间在fork子进程时也会阻塞redis主进程,且IO压力更大。

abandon的博客 992

Redis协议与异步方式

假如开始有2个消费者,一个消费者突然挂掉了,另外一个消费者依然能收到消息,但是如果刚挂掉的消费者重新连上后,在断开连接期间的消息对于该消费者来说彻底丢失了;MULTI 开启事务,事务执行过程中,单个命令是入队列操作,直到调用 EXEC 才会一起执行;):事务的前后,所有的数据都保持一个一致的状态,不能违反数据的一致性检测;原子性:事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败;脚本的执行是原子性的;另外,redis 停机重启,pubsub 的消息是不会持久化的,所有。

Faya__的博客 1352

Redis 持久化的奥秘:主线程、子进程与后台线程的区别及潜在阻塞风险

例如,对于 10GB 的 Redis 进程,需要复制大约 20MB 的内存页表,因此 fork 操作耗时与进程总内存量息息相关。对于高流量的 Redis 实例(OPS 可达 5 万以上),如果 fork 操作耗时在秒级别,将拖慢 Redis 几万条命令的执行,对线上应用延迟影响非常明显。它负责Redis的大部分核心功能,包括网络通信、命令处理等。一个进程可以包含多个线程,线程之间共享进程的资源,但每个线程有自己的栈和寄存器上下文。一个进程启动后,如果没有创建额外的线程,这样的进程一般称为主进程或主线程。

搬砖的小熊猫的博客 1354

Redis主从同步

因为slave原本也是一个master,有自己的replid和offset,当第一次变成slave,与master建立连接时,发送的replid和offset是自己的replid和offset。不过,旧的数据只要是绿色的,说明是已经被同步到slave的数据,即便被覆盖了也没什么影响。master判断发现slave发送来的replid与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。slave与master的offset之间的差异,就是salve需要增量拷贝的数据了。

weixin_44275670的博客 1926

【死磕 Redis】----- 理解 pipeline 管道

原文:https://www.topjava.cn/category/1391389927996002304 『chenssy』 在前面博客中小编提到过 Redis 性能瓶颈主要是网络,主要原因就在于 Redis 执行命令的时间通常在微妙级别。正常情况下,我们执行一条 Redis 命令流程要经过如下几个步骤: 客户端发送 Redis 命令,阻塞等待 Redis 应答 Redis 接收到命令,执行命令 应答,客户端收到响应信息 其中 1 、3 称之为一次 RTT(Round Trip Time)。.

chenssy 的技术博客 626

redis 6.0之后它的主线程是多线程吗?为什么要这样设计?事务、Lua脚本的支持有什么区别?管道和lua脚本又有什么区别?本篇带你来了解。

之前跟某某居公司的高级开发有交流过Redis现在是多线程还是单线程,其实我觉得聊这种八股文问题没啥意思,毕竟他又没有说明,他问题前提是问的主线程是否为单线程。因为Redis 在 2.6 版本,会启动 2 个后台线程,分别处理关闭文件、AOF 刷盘这两个任务;所以这时候起redis就不是单线程了,不过我知道他的意思还是想问主线程是怎么回事。那么我给出我的答案,主线程到现在仍然是单线程。然后这位兄弟就着急了,redis 6.0版本之后处理业务线程也变成多线程了。

qq_25156781的博客 303

redis协议与异步方式

redis网络层中,假设有三个client与服务器建立连接,reactor会管理对应的连接,通过事件循环不断的处理连接给服务器发送的数据,现在只关注数据包处理的流程,这里有三个管道,车子比做网络线程,网络线程不断地从管道中取数据包,分割数据包,decode,compute,encode,最后发送到client端;微观抽象的redis网络,由io多路复用+非阻塞io组成,有io检测和io操作的职责,有异步事件处理流程,先注册事件,在事件循环中处理事件;a是原子性,c是一致性,i是隔离性,d是持久性;

qq_36472482的博客 189

redis序列化和java序列化的区别

但是,在Java中使用Redis时,你可能会使用像Jedis或Lettuce这样的库,这些库提供了序列化和反序列化的工具或钩子,以便你可以更容易地在Java对象和Redis字符串之间转换。当你想在Redis中存储Java对象时,你需要将这些对象序列化为某种格式(如JSON、XML、二进制等),然后将这些序列化后的数据作为字符串存储在Redis中。Java序列化是将一个Java对象的状态转换为字节流,以便它可以被写入到持久化存储中(如文件或数据库)或者在网络中传输到另一个运行Java的虚拟机上。

2302_79741013的博客 539

redis rdb aof区别_Redis之持久化RDB与AOF

点击上方Java资料社区,选择“置顶公众号”优质文章,第一时间送达引言如果您是初学Redis,建议先阅读上两篇文章"初识Redis"、"springBoot使用Lettuce整合Redis",如果你想了解作者的话可以阅读"关于我,一位00后程序员";上两篇文章聊到了初步认识Redis以及springBoot对Redis的整合,我们知道Redis存储之所以速度快,是因为数据存在内存中,那么...

weixin_39772352的博客 62
上一篇: redis再战之基础常识和安装《一》
下一篇: redis再战之value数据类型实操《三》
漂吧
博客等级 码龄8年 15粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值