redis网络架构及单线程模型

Redis网络架构及单线程模型 问题: 1.Redis网络层基础组件主要包括哪几部分? 2.什么是Redis的单线程模型? 3.Redis怎样接收网络连接? Redis网络基础架构 网络编程离不开Socket,网络I/O模型最常用的无非是同步阻塞、同步非阻塞、异步阻塞、异步非阻塞,高性能网络服务器最常见的线程模型也就是基于EventLoop模式的单线程模型。我们看看Redis的网络架构是怎么样的: R... 阅读详情

一、网络基础架构

这里解释下上图涉及的组件,Redis网络层基础组件主要包括四个部分:

1)EventLoop事件轮询器,这部分实现在AE里面。

2)提供Socket句柄事件的多路复用器,这部分分别对于不同平台提供了不同的实现,比如epoll和select可以用于Linux平台、kqueue可以用于苹果平台、evpoll可以用于Solaris平台,这里并没有看到iocp,也就是Redis对于Windows支持并不是很好。

3)包括网络事件处理器实现的networking,这部分主要包括两个重要的事件处理器:acceptTcpHandler和acceptCommonHandler。

4)处理网络比较底层的部分,比如网络句柄创建、网络的读写等。

二、单进程单线程模型

要理解Redis的单线程模型,我们先抛出一些问题,当我们有多个客户端同时去跟Redis Server建立连接,之后又同时对某个key进行操作,这个过程中发生了什么呢?会不会有并发问题?这些问题先丢在这了,我们看看Redis启动初始化的过程中会做什么事情,这里尽量省略了与本文无关的部分:

1)初始化Redis Server参数,这部分代码通过initServerConfig实现。

2)初始化Redis Server,这部分代码在initServer里面。

3)启动事件轮询器。

对,这里我们就把Redis的启动部分简化为三步,跟网络操作有关的主要在第二步和第三步里面,来看看initServer里面发生了什么:

initServer流程

Redisç½ç»æ¶æååçº¿ç¨æ¨¡å

initServer里面首先创建了一个EventLoop,然后监听Server的IP对应的端口号,假设我们监听的是 127.0.0.1:3333 这个IP:端口对,我们得到的一个Server Socket句柄,最后通过createFileEvent将我们得到的Server Socket句柄和我们关心的网络事件mask注册到EventLoop上面。EventLoop是什么呢,我们看看它的定义:
 

typedef struct aeEventLoop {
    int maxfd;   /* highest file descriptor currently registered */
    int setsize; /* max number of file descriptors tracked */
    long long timeEventNextId;
    time_t lastTime;     /* Used to detect system clock skew */
    aeFileEvent *events; /* Registered events */
    aeFiredEvent *fired; /* Fired events */
    aeTimeEvent *timeEventHead;
    int stop;
    void *apidata; /* This is used for polling API specific data */
    aeBeforeSleepProc *beforesleep;
} aeEventLoop;

上面我们关注的主要是两个东西:events和fired。他们分别是两个数组,events用于存放被注册的事件以及相应的句柄,fired用于存放当EventLoop线程从多路复用器轮询到有事件的句柄的时候,EventLoop线程会把它放入fired数组里面,然后处理。

Redisç½ç»æ¶æååçº¿ç¨æ¨¡å

我用上面的示意图描述createFileEvent做的事情,就是将Server Socket句柄和关心的事件mask以及当事件产生的时候的事件处理器accptHandler生成一个aeFileEvent注册到EventLoop的events的数组里面,当然在这之前会首先将事件注册到多路复用器上,也就是epoll、kqueue等这些组件上。事件注册完之后需要对多路复用器进行轮询,来分离我们关心切发生的事件,那就是最后一步,启动事件轮询器。

接收网络连接

上面的步骤完成了服务端的网络初始化,而且事件轮询器已经开始工作了,事件轮询器做什么事情呢,就是不断轮询多路复用器,看看之前注册的事件有没有发生,如果有发生,则将会将事件分离出来,放入EventLoop的fired数组中,然后处理这些事件。

很显然,上面注册的事件是客户端建立连接这个事件,因此当有两个客户端同时连接Redis服务器的时候,事件轮询器会从多路复用器上面分离出这个事件,同时调用acceptHandler来处理。acceptHandler做的事情主要是accept客户端的连接,创建socket句柄,然后将socket句柄和读事件注册到EventLoop的events数组里面,不一样的是对于客户端的事件处理器是readQueryClient。

上面示意图表示了acceptHandler处理客户端连接,得到句柄之后再将这个句柄注册到多路复用器以及EventLoop上的示意图。之后再同样再处理下一个客户端的连接,这些都是串行的。

事件轮询

上面接收客户端这部分其实都发生在事件轮询的主循环里面:

void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
        aeProcessEvents(eventLoop, AE_ALL_EVENTS);
    }
}

Redis会不断的轮询多路复用器,将网络事件分离出来,如果是accept事件,则新接收客户端连接并将其注册到多路复用器以及EventLoop中,如果是查询事件,则通过读取客户端的命令进行相应的处理,这一切都是单线程,顺序的执行的,因此不会发生并发问题。

三、高性能单线程模型

根据官方的测试结果《How fast is Redis?》来看,在操作内存的情况下,CPU 并不能起到决定性的作用,反而可能带来一些其他问题。比如锁,CPU 切换带来的性能开销等。这一点我们可以根据官方的测试报告,提供的数据来证明。而且官方提供的数据是可以达到100000+的QPS(每秒内查询次数),这个数据并不比采用单进程多线程 Memcached 差!所以在基于内存的操作,CPU 不是 Redis 瓶颈的情况下,瓶颈在网络 I/O 上面,我们一般提供较好的网络环境就可以提升Redis的吞吐量,比如提高网络带宽,除此之外还可以通过合并命令提交批处理请求来代替单条命令一次次请求从而减少网络开销,提高吞吐量。

好了,说完单线程设计后,我们再来讨论讨论单线程的设计为什么能支持高并发?原因基本有以下几点:

第一,我们请求 Redis 更多的是操作内存。直接操作内存就很快啊,数据存在内存中,类似于 HashMap。HashMap 的优势就是查找和操作的时间复杂度都是 O(1)。

第二,单线程,没有 CPU 上下文切换带来的开销问题。而且上面也说了,内存操作和 CPU 的多核影响不大。直接采用单线程,就不用考虑各种锁,与之相关的加锁,解锁,死锁等问题就不复存在了。

第三,多路 IO 复用。这个后面我会具体的来讲讲它。能谈到这一点说明对 Redis 有一定的理解。这涉及到基于操作系统的网络 IO 模型。Reactor 网络模式,epoll,poll,select,kqueue 等多路复用 IO。

第四,依赖第二点。由于是单线程的,所以就存在一个顺序读写问题。大家可以比较以下,随机读写和顺序读写的速度。

第五,Redis 的数据结构,是经过专门的研究和设计的。所以操作起来简单且快。

第六,Redis 自己构建了VM 机制 。因为一般的调用系统函数,会浪费一定的时间。

综合以上内容,Redis 才有单线程,高性能的特点。

最后,再说一点,Redis 是单进程和单线程的设计,并不是说它不能多进程多线程。比如备份时会 fork 一个新进程来操作;再比如基于 COW 原理的 RDB 操作就是多线程的。

多路复用IO模型中,会有一个线程(Java中的Selector)不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。
 

IO多路复用模型使用了Reactor设计模式实现了这一机制。Reactor模式有三种实现方式:

每个客户端发起连接请求都会交给acceptor,acceptor根据事件类型交给线程handler处理,注意acceptor 处理和 handler 处理都在一个线程中处理,所以其中某个 handler 阻塞时, 会导致其他所有的 client 的 handler 都得不到执行, 并且更严重的是, handler 的阻塞也会导致整个服务不能接收新的 client 请求(因为 acceptor 也被阻塞了). 因为有这么多的缺陷, 因此单线程Reactor 模型用的比较少.

Reactor多线程模式

有专门一个线程, 即 Acceptor 线程用于监听客户端的TCP连接请求.

客户端连接的 IO 操作都是由一个特定的 NIO 线程池负责. 每个客户端连接都与一个特定的 NIO 线程绑定, 因此在这个客户端连接中的所有 IO 操作都是在同一个线程中完成的.

客户端连接有很多, 但是 NIO 线程数是比较少的, 因此一个 NIO 线程可以同时绑定到多个客户端连接中.

五种I/O模型介绍

IO 多路复用是5种I/O模型中的第3种,对各种模型讲个故事,描述下区别:

故事情节为:老李去买火车票,三天后买到一张退票。参演人员(老李,黄牛,售票员,快递员),往返车站耗费1小时。

1.阻塞I/O模型

老李去火车站买票,排队三天买到一张退票。

耗费:在车站吃喝拉撒睡 3天,其他事一件没干。

2.非阻塞I/O模型

老李去火车站买票,隔12小时去火车站问有没有退票,三天后买到一张票。

耗费:往返车站6次,路上6小时,其他时间做了好多事。

3.I/O复用模型

1.select/poll

老李去火车站买票,委托黄牛,然后每隔6小时电话黄牛询问,黄牛三天内买到票,然后老李去火车站交钱领票。 

耗费:往返车站2次,路上2小时,黄牛手续费100元,打电话17次

2.epoll

老李去火车站买票,委托黄牛,黄牛买到后即通知老李去领,然后老李去火车站交钱领票。 

耗费:往返车站2次,路上2小时,黄牛手续费100元,无需打电话

4.信号驱动I/O模型

老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李,然后老李去火车站交钱领票。 

耗费:往返车站2次,路上2小时,免黄牛费100元,无需打电话

5.异步I/O模型

老李去火车站买票,给售票员留下电话,有票后,售票员电话通知老李并快递送票上门。 

耗费:往返车站1次,路上1小时,免黄牛费100元,无需打电话

1同2的区别是:自己轮询

2同3的区别是:委托黄牛

3同4的区别是:电话代替黄牛

4同5的区别是:电话通知是自取还是送票上门

具体原理可查询:https://blog.youkuaiyun.com/wxy941011/article/details/80274233

https://blog.youkuaiyun.com/weixin_43892898/article/details/88644594

Redis 核心原理深度解析:从架构到实现 Redis 作为高性能内存数据库的标杆,其设计原理蕴含着对性能、可靠性和扩展性的深度优化。理解 Redis 的核心原理,不仅能帮助开发者合理使用其功能,更能在性能调优、故障排查和架构设计中占据主动。本文将从数据结构、单线程模型、持久化、网络架构、内存管理等核心模块展开,结合底层实现与代码示例,揭示 Redis 高效运行的本质。Redis 的核心原理是其高性能、高可靠性的基石,从单线程与 IO 多路复用的巧妙结合,到数据结构与持久化的精心设计,每个模块都体现了对性能和实用性的极致追求。 阅读详情

相关推荐

20_来聊聊redis的线程模型吧?为啥单线程还能有很高的效率?.zip

https://mp.youkuaiyun.com/console/uploadResources?spm=1011.2124.3001.4171

5.Redis之常用数据结构&单线程模型

redis 能够使用 单线程模型 很好的工作,原因主要在于 redis 的核心业务逻辑, 都是短平快的~~不太消耗 cpu 资源也就不太吃多核了!数据库对于数据的插入删除査询....都有更复杂的功能支持, 这样的功能势必要花费更多的开销比如,针对插入删除,数据库中的各种约束,都会使数据库做额外的工作,redis 每个基本操作,都是短平快的~~ 就是简单操作一下内存数据,不是什么特别消耗 cpu 的操作.就算搞多个线程,也提升不大~~redis 干的活少,提供的功能相比于 mysql 也是少了不少~~

m0_47017197的博客 566

读《认知科学导论》(萨伽德) 总结

1. 作者的写作思路 本书是建立在对心智的理解采用表征与计算的方式。对心智表征-计算的理解方式是与计算机的本质相联系。计算机本质上是一个符号系统,符号系统包含两个部分,一个是符号,另一个是建立在符号上的操作。对心智采用表征-计算的方式理解,很容易与计算机建立起类比关系。同时人们在探索人工智能领域采用表征-计算方式已经取得了无数辉煌的成就,故表征-计算式现在研究的主流方法。 本书的有两个部分组成

xiaoqiangXX的专栏 3450

redis架构

一.redis竞品对比 存储 数据结构 持久化 集群可用性 网络模型 线程模型 redis 支持value是string,list,hash,set,zset 是 主从,redis cluster无中心分布式集群 非阻塞IO 单线程 无锁 memcache 只支持string 否 需要自行开发 基于twemproxy做 主从集群 非阻

zhaozhenzuo的专栏 5859

从接线到组态:手把手教你搞定PROFIBUS-DP与PA的混合网络搭建(基于西门子TIA Portal)

本文详细介绍了PROFIBUS-DP与PA混合网络的搭建方法,基于西门子TIA Portal平台,从硬件选型、网络架构设计到组态配置和现场调试,提供了一套完整的实战指南。重点解析了DP/PA耦合器的使用、地址映射策略及网络诊断技巧,帮助工程师高效构建高可靠性的工业自动化网络。

weixin_32103009的博客 301

告别踩坑!S32K3xx芯片上RTD-SDK的DFLASH与FEE模块配置全流程(基于S32DS)

本文详细解析了在NXP S32K3xx系列MCU上配置RTD-SDK的DFLASH与FEE模块的全流程,基于S32DS开发环境。从Cache配置、Mem_43_InFls模块设置到MemAcc模块的三种调用模式,提供了实战代码示例和常见问题排查表,帮助开发者高效完成存储管理配置,避免常见错误。

weixin_42653691的博客 268

Redis的架构模式

单机版 特点:简单 问题: 1、内存容量有限 2、处理能力有限 3、无法高可用。 主从复制 Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。 特点: 1、

hellozhxy的博客 1848

别再用Excel画波特图了!用LTspice免费仿真软件,5分钟搞定电路传递函数分析

本文介绍了如何利用LTspice免费仿真软件高效绘制波特图,解决传统Excel绘图效率低、精度不足的问题。通过详细的操作步骤和实战案例,展示LTspice在电路传递函数分析中的自动化计算、专业级精度和完整特性展示等优势,帮助工程师快速完成频率响应分析。

weixin_42524226的博客 461

技术分享 | Redis 集群架构解析

作者:贲绍华爱可生研发中心工程师,负责项目的需求与维护工作。其他身份:柯基铲屎官。本文来源:原创投稿*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。一、集群架构的一些基本概念当我们只使用一台 Redis 实例也就是 Single 架构时,需要考虑一些非常实际的问题,如:单节点一但宕机则业务停摆、单节点的容量不可能是无限制的、性能同样存在瓶颈等......集群架构模式最...

杨建荣的学习笔记 491

linux 驱动 - pinctrl子系统

分析总结 pinctrl 子系统框架结构,平台 mtk6771 内核版本 kernel-4.4 , 本文所有的分析均基于此版本。

sty01z的博客 1557

LibTV本地部署:AI漫剧创作完整解决方案与实战指南

如果你正在关注AI漫剧创作这个赛道,可能会发现一个有趣的现象:市面上的AI视频工具要么功能单一,要么云端服务昂贵且存在内容审核风险。而今天要介绍的LibTV本地部署方案,或许能为你打开一扇新的大门。 这个方案的核心是Seedance2.0与豆包AI的本地化集成,它真正解决的是创作者对内容自主权、成本控制和创作效率的三重需求。与红果、抖音等平台提供的标准化AI工具相比,本地部署意味着你可以完全掌控生成过程,不受平台规则限制,更重要的是——所有数据都在本地,不存在内容泄露风险。 1. 这篇文章真正要解决的问题

weixin_28745309的博客 520

Redis 网络架构及单线程模型

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34153893的博客 96

知识图谱中的 Ontology(本体论)

本文的部分图片和内容来自中国科学院自动化研究所刘康老师的课件 Ontology(本体论) Ontology 是(特定领域)信息组织的一种形式,是领域知识规范的抽象和描述,是表达、共享、重用知识的方法。 Ontology 是知识体系构建的关键技术,知识图谱是一种人工智能技术,它的关键在于让计算机能够处理人类的知识。然而,人类脑海中的知识通常是直觉性的,我们无法将这种直觉性的知识直接输入给计算机,On...

P01son的博客 2万+

Redis网络模型分析:从单线程到多线程的网络架构演进

Redis网络模型经历了从单线程到多线程的演进。Redis 1.x-5.x采用单线程+IO多路复用模型,通过epoll/kqueue实现事件驱动,适合一般并发场景。Redis 6.0+引入多线程IO(IO线程池)但保留单线程命令处理,主线程负责协调,提升高负载场景下的处理能力。伪代码展示了单线程模型的实现:通过Selector监听事件,包括连接建立、读写处理等,所有操作都在单线程中完成。这种架构简单可靠,但扩展性受限。多线程模型通过线程池分担网络IO压力,同时保持命令执行的原子性,实现了性能与可靠性的平衡。

m0_75126572的博客 1195

机器人视觉联动精度优化:从±2mm到±0.02mm,产线级手眼标定全实战

2025年我接东莞长安Type-C接口分拣项目的时候,就是栽在了手眼标定上:实验室里标定完精度±0.5mm,一到产线直接掉到±2mm,机器人10次有3次抓不住,2000多件Type-C接口直接报废,还撞坏了2套汇川SCARA机器人的吸盘,本来45天的工期拖了3个月,不仅没赚到钱,还倒贴了几万块。手眼标定从来不是简单的跑个demo、算个矩阵就完事了,它是一个系统工程:从硬件选型、安装固定、相机标定、标定流程、算法优化、环境控制、重复验证,每一个环节都会影响最终的联动精度。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 384

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【Redis技术探索】「底层架构原理」探索分析服务系统的网络架构和线程模型

网络编程离不开Socket,网络I/O模型最常用的无非是,高性能网络服务器最常见的线程模型也就是。

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。 803

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

redis单线程与分布式锁

Redis网络基础架构 网络编程离不开Socket,网络I/O模型最常用的无非是同步阻塞、同步非阻塞、异步阻塞、异步非阻塞,高性能网络服务器最常见的线程模型也就是基于EventLoop模式的单线程模型。我们看看Redis的网络架构是怎么样的: Redis基础组建结构 这里解释下上图涉及的组件,Redis网络层基础组件主要包括四个部分:     EventLoop事件轮训器,

u010154380的专栏 1429

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【Redis】原理-网络模型

本文介绍了Linux I/O模型的基础知识,重点分析了用户空间与内核空间的区别以及四种I/O模型的工作原理。主要内容包括:1)用户空间和内核空间的划分及权限差异;2)I/O读写过程中缓冲区的使用;3)详细讲解阻塞I/O、非阻塞I/O、I/O多路复用三种模型的工作流程;4)深入分析select、poll、epoll三种多路复用实现方式的优缺点;5)特别说明epoll的水平触发和边缘触发两种模式的区别。文章通过图示和代码示例,系统性地阐述了Linux系统中I/O操作的核心机制,为理解高性能网络编程提供了理论基础

qq_39166045的博客 1014

Redis的单线程模型

我们在学习Redis的过程中都说Redis快,redis是单线程的,但是我们有没有想过单线程的Redis为什么会这么快呢? 确实,Redis在6.0之前都是单线程模型,这主要指的是Redis的网络IO和键值对的读写都是由一个线程来完成的,这也是Redis提供键值存储服务的主要流程。但是相对于Redis中其他的功能,比如持久化、集群等确是由额外的线程执行的。相比较单线程,我们经常会听到一个说法,为了提高性能和效率,使用多线程可以增加系统吞吐率、增加系统的扩展性。的确在合理分配资源的情况下,可以增加系统中处理请

m0_37561303的博客 268

redis 的单线程和内部的网络模型

redis 通过使用IO多路复用来提升网络性能的,它支持很多种的实现方式,在Linux 上实现主要是前面讲三种(select , poll, epoll),但是 redis 不仅只在Linux上使用,其他系统上也是使用的,所以redis 在他们的实现之上,再次做了一次封装,对外直接提供一些接口 API, 他的大概流程,也是和web 的相似的, 这里是函数 调用的是api 对应的源码:...

qq_52252193的博客 450

解析Linux网络模型与Redis的高性能网络架构

基于Linux网络模型,解析Redis的高性能实现

BUPTZhanggg的博客 708
上一篇: SpringBoot注解详解
下一篇: spring-boot — 指定类日志单独输出到某一个日志文件中
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值