CSDN博主:【java_wxid】
CSDN博主:点击【Java廖志伟】
CSDN社区:点击【幕后大佬】
码云:点击【互联网Java工程师知识扫盲】

我是🌟廖志伟🌟,一名🌕Java开发工程师🌕、📝Java领域优质创作者📝、🎉CSDN博客专家🎉、🌹幕后大佬社区创始人🌹。拥有多年一线研发经验,研究过各种常见框架中间件的底层源码,对于大型分布式微服务、三高架构(高性能高并发高可用)有过实践架构经验。

🍊博主:java_wxid
🍊博主:Java廖志伟
🍊社区:幕后大佬



本文内容:

多路复用


redis面试知识点

redis的多路复用模式

redis使用模型有:select、poll、epoll。这里简单讲二种。

应用对外提供服务的过程

一个应用程序, 想对外提供服务, 一般都是通过建立套接字监听端口来实现, 也就是socket。
应用对外提供服务的过程:

  1. 创建套接字
  2. 绑定端口号
  3. 开始监听
  4. 当监听到连接时, 调用系统read去读取内容,但是读取操作是阻塞的。

select

问题:如果主线程处理read,就不能接收其他连接了, 所以只能开新的线程去处理这个事情。而且read操作是调用系统函数, 需要进行进程的切换, 从用户进程切换到系统进程,连接少还好,连接多的话,无疑降低了性能。

解决方案:用户线程批量将要查询的连接发给操作系统,这个过程只发生一次进程的切换,用户线程告诉操作系统,需要哪些数据, 它遍历查找,然后将结果返回给用户线程,这就是select。

操作系统接收到一组文件描述符,然后批量处理这些文件描述符,有顺序的循环检查有没有数据,然后返回结果。无论是监听端口还是建立了连接,程序拿到的都是一个文件描述符,将这些文件描述符批量查询就是了。

select

epoll

问题:有10万个连接,其中有数据的只有一个,那就回有9999次无效的操作,每次查询都要把所有的都传过去, 10万个就要传10万。

解决方案:直接知道哪些连接是有数据的,然后操作系统通知用户线程,那个连接是可以直接拿到数据的,用户线程就直接通过这个连接去读数据就好了,不需要遍历,这就是epoll。

建立一个需要回调的连接, 将需要监听的文件描述符都扔给操作系统,当有新数据到达时,会直接返回给用户线程。用户线程将监听的列表交给操作系统维护,这样当有新数据来的时候,操作系统知道这是你要的,等你下次来拿的时候,直接给你了,少去了上面的遍历。

epoll

多路复用的定义

“多路”指的是多个网络连接,“复用”指的是复用同一个线程。

采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)。

多路复用的举例

redis 需要处理 3 个 IO 请求,同时把 3 个请求的结果返回给客户端,所以总共需要处理 6 个 IO 事件, 由于 Redis服务端对于命令的处理是单线程的,同一时间只能处理一个 IO 事件。于是 redis 需要在合适的时间暂停对某个 IO 事件的处理,转而去处理另一个 IO 事件, 这样 redis 就好比一个开关,当开关拨到哪个 IO 事件这个电路上,就处理哪个 IO 事件,其他 IO 事件就暂停处理了。这就是IO多路复用技术。用一句话总结就是,一个客户端建立好连接后,就可以立刻等待新的客户端连接,而不用阻塞在原客户端的 read 请求上。

多路复用的实现

select, poll, epoll 都是I/O多路复用的具体的实现。epoll性能比其他几者要好。redis中的I/O多路复用的所有功能通过包装常见的select、epoll、evport和kqueue这些I/O多路复用函数库来实现的。 redis的io模型主要是基于epoll实现的,不过它也提供了 select和poll的实现,默认采用epoll。

多路 I/O 复用技术

过程一:数据未就绪

多个客户端并发请求时,用户线程发起请求的时候,首先会将socket监听列表添加到select中,让select调用操作系统的API,这个过程就是从用户态到内核态,由于当前请求是交给了操作系统去处理,现在的用户线程这时候就空闲了,可以重新接收新的客户端请求。

操作系统等待select调用,当数据到达时,select函数被激活,操作系统将select函数的结果socket监听结果为可读,返回给用户线程,告诉用户线程这个连接可以读取数据了,这个时候用户线程才正式发起read请求,读取数据,这个读取数据的过程也是非阻塞的。

过程二:数据就绪

read 函数的效果是,如果没有数据到达时(到达网卡并拷贝到了内核缓冲区),立刻返回一个错误值(-1),而不是阻塞地等待。只有当操作系统告诉用户线程数据已经准备就绪的时候,数据从内核缓冲区拷贝到用户缓冲区才通知用户进程调用完成,返回结果,这个过程是阻塞的。
read函数
对于用户线程来说,它可以注册多个socket监听,然后不断地调用select读取,操作系统找到用户线程需要的连接,这个连接里面监听到有用户线程所需要的数据,就会激活socket把结果返回给用户线程。


总结

以上就是今天要讲的内容,还希望各位读者大大能够在评论区积极参与讨论,给文章提出一些宝贵的意见或者建议📝,合理的内容,我会采纳更新博文,重新分享给大家。

🙏四连 关注🔎点赞👍收藏⭐️留言📝

感谢大家的支持,用心写博文分享给大家,你的支持(🔎点赞👍收藏⭐️留言📝)是对我创作的最大帮助。
🍊微信公众号:南北踏尘
🍊主页地址:java_wxid
🍊社区地址:幕后大佬

给读者大大的话

我本身是一个很普通的程序员,放在人堆里,除了与生俱来的🌹盛世美颜🌹、所剩不多的发量,就剩下180的大高个了。就是我这样的一个人,默默坚持写博文也有好多年了,有句老话说的好,🌕牛逼之前都是傻逼式的坚持🌕。希望自己可以通过大量的作品,时间的积累,个人魅力、运气和时机,可以打造属于自己的🌟技术影响力🌟。同时也希望自己可以成为一个🎄懂技术🎄,🎄懂业务🎄,🎄懂管理🎄的综合型人才,作为项目架构路线的总设计师,掌控全局的🌕团队大脑🌕,技术团队中的🍊绝对核心🍊是我未来几年不断前进的目标。


提示:以下都是资源分享,求个一键三连。

面试资料

福利大放送,🎉欢迎关注🔎点赞👍收藏⭐️留言📝,拜托了🙏,这对我真的很重要。
点击:面试资料
提取码:2021

200套PPT模板

福利大放送,🎉欢迎关注🔎点赞👍收藏⭐️留言📝,拜托了🙏,这对我真的很重要。
点击:200套PPT模板
提取码:2021

提问的智慧

福利大放送,🎉欢迎关注🔎点赞👍收藏⭐️留言📝,拜托了🙏,这对我真的很重要。
点击:提问的智慧
提取码:2021

Java开发学习路线

名称链接
JavaSE点击: JavaSE
MySQL专栏点击: MySQL专栏
JDBC专栏点击: JDBC专栏
MyBatis专栏点击: MyBatis专栏
Web专栏点击: Web专栏
Spring专栏点击: Spring专栏
SpringMVC专栏点击: SpringMVC专栏
SpringBoot专栏点击: SpringBoot专栏
SpringCould专栏点击: SpringCould专栏
Redis专栏点击: Redis专栏
Linux专栏点击: Linux专栏
Maven3专栏点击: Maven3专栏
Spring Security5专栏点击: Spring Security5专栏
更多专栏更多专栏,请到 java_wxid主页 查看

P5学习路线图
p5学习路线图P6学习路线图
P6学习路线图P7学习路线图
P7学习路线图P8学习路线图
P8学习路线图

以上四张图详细介绍了作为Java开发工作者所需要具备的知识技能,同学们学废了嘛,有想法系统学习的同学可以私聊我,🎉欢迎关注🔎点赞👍收藏⭐️留言📝。
🍊博主:java_wxid
🍊博主:Java廖志伟
🍊社区:幕后大佬

posted on 2021-12-04 09:00  我是廖志伟  阅读(336)  评论(0)    收藏  举报

南北踏尘