Redis原理 - Redis网络模型

这篇具有很好参考价值的文章主要介绍了Redis原理 - Redis网络模型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

原文首更地址,阅读效果更佳!

Redis原理 - Redis网络模型 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-netword-model.html

思考

Redis 到底是单线程还是多线程?

  • 如果仅仅针对 Redis 的核心业务部分(命令处理部分),则是单线程
  • 如果针对 Redis 整体,那么就是多线程

在 Redis 的版本迭代过程中,在两个重要的时间节点上引入了多线程的支持:

  • Redis v4.0:引入多线程异步处理一些耗时较长的任务,例如异步删除命令 unlike
  • Redis v6.0:在核心网络模型中引入多线程,进一步提高对多核 CPU 的利用率

为什么Redis要选择单线程?

  • 抛开持久化不谈,Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。
  • 多线程会导致过多的上下文切换,带来不必要的开销
  • 引入多线程会面临线程安全问题,必然要引入线程锁这样的安全手段,实现复杂度增高,而且性能也会大打折扣

#网络模型

Redis 通过 IO 多路复用来提高网络性能,并且支持各种不同的多路复用实现,并且将这些实现进行封装,提供了统一的高性能事件库 API 库 AE:

  • ae_epoll
  • ae_evport
  • ae_kqueue
  • ae_select(通用)

这是 Redis 中四种实现方式,根据不同的操作系统,选择不同的实现。

具体的 API 主要有以下几个:

  • aeApiCreate:创建多路复用程序,比如 epoll_create
  • aeApiResize
  • aeApiFree
  • aeApiAddEvent:注册 FD ,比如 epoll_ctl
  • aeApiDelEvent:删除 FD
  • aeApiPoll:等待 FD 就绪,比如 epoll_wait
  • aeApiName:select、poll

ae_evport 实现方式中独有的API

  • aeApiLookupPending
  • aeApiAssociate

在ae.c 文件中可以选择使用那种实现方式。

Redis原理 - Redis网络模型

 

#单线程网络模型

Redis 6 以前的网络模型都是单线程的,Redis 单线程网络模型的整个过程:

Redis原理 - Redis网络模型

 

  • 在 aeApiPoll 时,会判断是客户端可读还是服务端可读,调用不同的处理器
  • 当客户端 Client Socket 发起连接请求时,服务端 Server Socket 可读,触发连接应答处理器 tcpAccepthandler
  • 当客户端 Client Socket 发起命令时,客户端可读,触发命令请求处理器 readQueryFromClient
  • 当客户端可写时,会由命令回复处理器进行处理。

核心

本质上就是 IO 多路复用 + 事件派发 的应用。

server socket 不断接收 client socket 的响应,然后根据事件类型的不同,派发给对应的处理器进行处理。

#多线程网络模型

Redis 6.0 版本中引入了多线程,目的是为了提高 IO 读写效率。因此在 解析客户端命令、 写响应结果 时采用了多线程。核心的命令执行、IO 多路复用模块依然是由主线程执行。

通过对单线程网络模型的分析,主要的性能瓶颈在命令的读写处理和命令的响应输出两个方面。

Redis原理 - Redis网络模型

 

故Redis 在命令读处理和命令的响应两个部分引入了多线程。

注意

性能的瓶颈一般情况下都是 IO 的影响或者 网络请求 的影响。文章来源地址https://www.toymoban.com/news/detail-501366.html

#底层实现

  • main
// server.c
int main(
    int argc,
    char **argv
){
    // ...
    // 初始化服务
    initServer();
    // ...
    // 开始监听事件循环
    aeMain(server.el);
    // ...
}
  • initServer
void initServer(void){
    // ...
    // 内部会调用 aeApiCreate(eventLoop),类似epoll_create
    server.el= aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);
    //...

    // 监听TCP端口,创建ServerSocket,并得到FD
    listenToPort(server.port,&server.ipfd)
    // ...

    // 注册 连接处理器,内部会调用 aeApiAddEvent(&server.ipfd)监听FD
    createSocketAcceptHandler(&server.ipfd,acceptTcpHandler)

    // 注册 ae_api_poll 前的处理器
    aeSetBeforeSleepProc(server.el,beforeSleep);
}


  • aeMain
void aeMain(aeEventloop*eventloop){
    eventLoop->stop = 0;
    // 循环监听事件
    while (!eventLoop->stop){
        aeProcessEvents(
            eventLoop,
            AE_ALL_EVENTS | 
            AE_CALL_BEFORE_SLEEP |
            AE_CALL_AFTER_SLEEP);
    }
}
  • aeProcessEvents
int aeProcessEvents(aeEventLoop *eventLoop,int flags){
    // ... 调用前置处理器 beforesleep
    eventLoop->beforesleep(eventLoop);
    // 等待FD就绪,类似 epoll_wait
    numevents = aeApiPoll(eventLoop,tvp);

    for (j = 0; j < numevents; j ++){
        // 遍历处理就绪的 FD,调用对应的处理器
    }
}
  • acceptTcpHandler
void acceptTcpHandler( ... ){
    // ...
    // 接收 socket 连接,获取 FD 
    fd = accept(s,sa,len);

    // ... 
    // 创建 connection ,关联 fd
    connection *conn = connCreateSocket();
    conn.fd = fd;

    // ...
    // 内部调用 aeApiAddEvent(fd,READABLE)
    // 监听 socket 的FD读事件,并绑定读处理器readQueryFromClient
    connSetReadHandler(conn, readQueryFromClient);
}
  • readQueryFromClient
void readQueryFromClient(connection *conn){
    // 获取当前客户端,客户端中有缓冲区用来读和写
    client *c = connGetPrivateData(conn);
    // 获取c->querybuf缓冲区大小
    long int qblen = sdslen(c->querybuf);
    // 读取请求数据到 c->querybuf 缓冲区
    connRead(c->conn,c->Guerybuf+qblen,readlen);
    // 解析缓冲区字符串,转为Redis命令参数存入 c->argv 数组
    processInputBuffer(c);
    // ...
    // 处理 c->argv 中的命令
    processCommand(c);
}
  • processCommand
int processCommand(client *c) {
    // 根据命令名称,寻找命令对应的command,例如 setCommand
    c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr);
    // ...
    // 执行command,得到响应结果,例如ping命令,对应pingCommand
    c->cmd->proc(c);
    // 把执行结果写出,例如ping命令,就返回"pong"给cLient
    // shared.pong是 字符串"pong"的SDS对象
    addReply(c, shared.pong);
}
  • addReply
void addReply(client *c,robj *obj) {
    // 尝试把结果写到 c-buf 客户端写缓存区
    if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != C_OK)
    // 如果c->buf写不下,则写到 c->reply,这是一个链表,容量无上限
    _addReplyProtoToList(c,obj->ptr,sdslen(obj->ptr));
    // 将客户端添加到server.clients_pending_write这个队列,等待被写出
    listAddNodeHead(server.clients_pending_ write,c);
}

到了这里,关于Redis原理 - Redis网络模型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • BLIP2原理解读——大模型论文阅读笔记二

    论文:https://arxiv.org/abs/2301.12597 代码:https://github.com/salesforce/LAVIS/tree/main/projects/blip2 端到端训练视觉语言模型需要大尺度模型及大规模数据,该过程成本大,本文提出方法基于现有高质量视觉模型及语言大模型进行联合训练,为减少计算量及防止遗忘,作者对预训练模型进行

    2024年02月09日
    浏览(45)
  • Visual ChatGPT原理解读——大模型论文阅读笔记四

    论文:https://arxiv.org/abs/2303.04671 代码:https://github.com/microsoft/TaskMatrix 如图所示,用户上传一张黄花的图像并输入一个复杂的语言指令“请根据该图像的预测深度生成一朵红花,然后逐步使其像卡通一样”。 在交互管理器的帮助下,Visual ChatGPT 开始了相关视觉基础模型的执行

    2024年02月09日
    浏览(42)
  • DALL-E2原理解读——大模型论文阅读笔记五

    论文:https://cdn.openai.com/papers/dall-e-2.pdf 项目:https://openai.com/dall-e-2 利用CLIP提取的文本特征,级联式的生成图片。第一阶段通过prior将文本特征与图像特征进行对齐,第二阶段用扩散模型将视觉特征转化为生成图片。整体来看,DALL-E2就是CLIP与扩散模型的结合,因此作者也将其

    2024年02月11日
    浏览(45)
  • 网络安全标准实践指南——网络数据安全风险评估实施指引(原文+解读下载)

    为指导网络数据安全风险评估工作,发现数据安全隐患,防范数据安全风险,依据《中华人民共和国网络安全法》《中华人民共和国数据安全法》《中华人民共和国个人信息保护法》等法律法规,参照数据安全相关国家标准, 全国信息安全标准化技术委员会在组织编制国家标

    2024年02月16日
    浏览(47)
  • 【论文阅读】Weighted Boxes Fusion(WBF)模型融合原理解读

    论文地址:https://arxiv.org/pdf/1910.13302.pdf 代码地址:GitHub - ZFTurbo/Weighted-Boxes-Fusion: Set of methods to ensemble boxes from different object detection models, including implementation of \\\"Weighted boxes fusion (WBF)\\\" method. 【 原理 】 (1)将所有获得的候选框按得分进行降序排列; (2)选取得分最高的候选框

    2024年02月10日
    浏览(45)
  • DSMM数据安全能力成熟度模型及配套实施指南笔记(附原文下载)

    《GBT 37988-2019 信息安全技术 数据安全能力成熟度模型》和《数据安全能力建设实施指南》原文下载链接在文末      2020年3月1日《GBT 37988-2019 信息安全技术 数据安全能力成熟度模型》正式实施,该标准适用于对企业、组织对数据安全能力进行评估和作为数据安全能力建设的

    2024年02月09日
    浏览(39)
  • 【Redis】Redis 高性能IO模型原理

    在面试的时候遇到Redis肯定会问,Redis单线程为什么那么快呀?你可以说下你对IO多路复用的机制嘛。但是仔细一想Redis真的是单线程在运行处理嘛,其实这个单线程主要指的Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求,包括socket读取、解析、执

    2024年02月04日
    浏览(52)
  • 网络协议从入门到底层原理学习(二)—— Mac地址/IP地址

    1、MAC地址 MAC地址(Media Access Control Address)也称为硬件地址或物理地址(Physical Address),它是一个用来确认网络设备位置的位址。在OSI模型中,第三层网络层负责IP地址,第二层数据链路层则负责MAC位址 。MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,

    2024年02月09日
    浏览(39)
  • redis 存储原理与数据模型

    redis 数据库通过 dict 实现映射关系。key 的固定类型是 string,value 的类型有多种。 redis 中 KV 组织是通过字典来实现的;hash 结构当节点超过512 个或者单个字符串长度大于 64 时,hash 结构采用字典实现。 dict 由哈希表 dictht + 哈希节点 dictEntry 组成。哈希表有两个,通常 ht[0] 使

    2024年02月14日
    浏览(34)
  • redis存储原理与数据模型学习笔记

    redis-server 命令处理 网络事件的监听 bio close file 异步关闭大文件 bio aof fsync 异步 aof 刷盘 bio lazy free 异步清理大块内存 io thd * io 多线程 emalloc bg thd jemalloc 后台线程 单线程为什么快? server.h dict.h 注意 dictEntry **ht_table[2]; 怎么从key定位到value? 哈希原理: 数组 + hash(key) % 数组长

    2024年02月10日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包