专栏首页烟草的香味redis的多路复用是什么

redis的多路复用是什么

为了引出多路复用, 我来大胆设想一下技术的发展路程.

前提

一个应用程序, 想对外提供服务, 一般都是通过建立套接字监听端口来实现, 也就是socket. 在这个时候, 应用对外提供服务的过程大概是这样.

  1. 创建套接字
  2. 绑定端口号
  3. 开始监听
  4. 当监听到连接时, 调用系统read去读取内容, 但是读取操作是阻塞的(也就是说,如果主线程处理read,就不能接收其他连接了, 所以只能开新的线程去处理这个事情)

画个丑丑的流程图:

问题分析

这个流程的问题很明显, 会不停的创建线程, 当然, 可以维护一个线程池. 但是线程之间的不停切换也是消耗资源的. 而且也不可能无限的创建线程. 那我如果想一个线程处理呢? 从上面流程图能看的出来, 问题出在阻塞上面. 如果read操作可以立刻返回结果, 如果没有读到数据, 就可以继续处理后边的事情了.

简版

整个简单版本. 主线程维护一个所有连接的列表, 每次循环读取所有列表, 有数据就处理, 没有就跳过.

  1. 创建套接字
  2. 绑定端口号
  3. 开始监听
  4. 监听到连接, 将连接加到连接列表中, 循环读取连接列表中的所有连接, 对有数据的进行处理

画个丑图:

问题分析

现在这样处理貌似是比开线程要好一些了, 但是事实是这样么? 众所周知, 其中的read操作是调用系统函数, 简单说就是要进行进程的切换, 从用户进程切换到系统进程. 连接少还好, 如果有十万个连接, 甚至更多呢? 每次循环都会频繁的调用系统函数, 可能十万次调用, 甚至其中有数据的只有一次, 其余调用都白掉了. 这无疑降低了性能.

其实解决方法说起来也很容易想到. 问题出在系统调用上, 频繁的系统调用导致了问题的出现. 如果能够一次性将需要查询的所有数据都发给系统, 让系统进行查询, 那不就只需要一次切换就可以了么?.

select版本

为了解决上面的问题. 可以批量将待查询的连接发给系统. 出现了select, 这就是说的 多路复用 了. 在系统 中, 无论是监听端口还是建立了连接, 程序拿到的都是一个文件描述符, 将这些文件描述符批量查询就是了.

直接上丑图:

这里和上一个版本相比, 将循环检查交到了系统去做, 只发生一次进程的切换. select 简单说, 就是你告诉系统, 你需要哪些数据, 你同帮你遍历找找, 然后将结果返回给你.

问题分析

这样确实要好上一些, 但是上面的问题还没有完全解决. 比如有10万个连接, 其中有数据的只有一个, 那就回有9999次无效的操作, 虽然这些无效的操作是由系统做的, 但不一样么, 系统做的无效操作, 你应用程序也得等着啊. 而且每次查询都要把所有的需要的都传过去, 10万个就要传10万了, 蓝瘦.

问题出在哪呢? 需要循环遍历, 是因为不知道哪些连接是有数据的, 所以只能一个一个的看. 如果可以不 需要遍历, 直接知道哪些连接是有数据的, 然后直接拿到数据返回就好了.

epoll

跟上一个版本相比, 现在不通过批量查询的方式了, 而是通过回调的方式. 简单说, 建立一个需要回调的连接, 将需要监听的文件描述符都扔给他, 当有新数据到达时, 会返回给你.

上丑图:

看着是不是有点晕了? 其实它和select版本的区别简单来说, epoll是将你需要监听的列表交给系统维护, 这样当有新数据来的时候, 系统知道这是你要的, 等你下次来拿的时候, 直接给你了, 少去了上面的系统遍历. 同时, 也没有select查询时那一大堆参数, 每次都只调用一次进行绑定即可.

那系统是怎么知道新数据的到来呢? 这里靠的是事件中断, 忘得差不多了, 回头再看看.

epoll 简单说就是, 你告诉系统, 你需要哪些数据, 然后等着, 有数据了系统就通知你, 然后你去读.


以上select, epoll是两种多路复用的技术, 当然, 还有多路复用还有其他的.

据说redis的多路复用对系统方法进行了封装, 不过我还没看, 再议!!!

本文分享自微信公众号 - 烟草的香味(hujing-bc),作者:胡靖哥哥

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java并发性和多线程

    例如一个应用程序需要从本地文件系统中读取和处理文件的情景. 比方说, 从磁盘读取一个文件需要5s, 处理一个文件需要2s. 那么处理两个文件就需要:

    烟草的香味
  • Java集合之LinkedHashMap源码分析

    LinkedHashMap是HashMap的一个子类, 它通过重写父类的相关方法, 实现自己的功能. 它保留插入的顺序. 如果需要输出和输入顺序相同时, 就选用...

    烟草的香味
  • 23种设计模式之迭代器模式

    其实, 现在基本上所有的高级语言都实现了迭代器, 基本上跟很少有项目再独立写迭代器了.

    烟草的香味
  • 央视放话了,国产系统PK掉Windows系统!

    在央视经济频道《对话》栏目中,现场有其中一段非常有意思的对比,将国产系统与国外系统经行速度测试,而所谓的国外系统就是我们常用的Windows系统。

    哲洛不闹
  • RegExp正则匹配模式汇总

     正则表达式提供另一种强大的文本搜索和处理方式,对于正则表达式,不同语言有着不同的实现,JavaScript采用的Perl5的语法。对于极少数匹配模式是简单的全...

    okaychen
  • 您HTML5的article标签吗

    HTML5引入了多个新的元素使我们可以更加细致的描述页面与文本的结构,这些元素的运用也使我们的文档页面更加简洁、易读,同时也可以让我们的搜索引擎更好的理解页面的...

    算法与编程之美
  • 数组的剖析

    C语言中数组是十分重要的一种结构,数组采用的是连续存储的方式,下面通过反汇编的方式来解析编译器对数组的操作。

    Masimaro
  • 分布式架构的演进

    系统架构演化历程-初始阶段架构 ? 初始阶段 的小型系统 应用程序、数据库、文件等所有的资源都在一台服务器上通俗称为LAMP特征:应用程序、数据库、文件等所有的...

    Java高级架构
  • 神速Hash

    面试官: 聊聊HashMap的底层实现 理解HashMap底层,首先应该理解Hash函数,今天我们聊聊什么是Hash函数以及Hash函数的设计 查找速度的困扰 ...

    用户1260737
  • MailSploit:30多种邮件客户端存在电邮身份伪造漏洞

    近日,德国安全研究员 Sabri Haddouche发现30多种邮件客户端中存在漏洞,可以让任意用户伪造身份发送欺诈邮件并绕过反欺诈保护机制(如 DMARC 等...

    FB客服

扫码关注云+社区

领取腾讯云代金券