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

redis的多路复用模式
redis使用模型有:select、poll、epoll。这里简单讲二种。
应用对外提供服务的过程
一个应用程序, 想对外提供服务, 一般都是通过建立套接字监听端口来实现, 也就是socket。
应用对外提供服务的过程:
- 创建套接字
- 绑定端口号
- 开始监听
- 当监听到连接时, 调用系统read去读取内容,但是读取操作是阻塞的。
select
问题:如果主线程处理read,就不能接收其他连接了, 所以只能开新的线程去处理这个事情。而且read操作是调用系统函数, 需要进行进程的切换, 从用户进程切换到系统进程,连接少还好,连接多的话,无疑降低了性能。
解决方案:用户线程批量将要查询的连接发给操作系统,这个过程只发生一次进程的切换,用户线程告诉操作系统,需要哪些数据, 它遍历查找,然后将结果返回给用户线程,这就是select。
操作系统接收到一组文件描述符,然后批量处理这些文件描述符,有顺序的循环检查有没有数据,然后返回结果。无论是监听端口还是建立了连接,程序拿到的都是一个文件描述符,将这些文件描述符批量查询就是了。

epoll
问题:有10万个连接,其中有数据的只有一个,那就回有9999次无效的操作,每次查询都要把所有的都传过去, 10万个就要传10万。
解决方案:直接知道哪些连接是有数据的,然后操作系统通知用户线程,那个连接是可以直接拿到数据的,用户线程就直接通过这个连接去读数据就好了,不需要遍历,这就是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。

过程一:数据未就绪
多个客户端并发请求时,用户线程发起请求的时候,首先会将socket监听列表添加到select中,让select调用操作系统的API,这个过程就是从用户态到内核态,由于当前请求是交给了操作系统去处理,现在的用户线程这时候就空闲了,可以重新接收新的客户端请求。
操作系统等待select调用,当数据到达时,select函数被激活,操作系统将select函数的结果socket监听结果为可读,返回给用户线程,告诉用户线程这个连接可以读取数据了,这个时候用户线程才正式发起read请求,读取数据,这个读取数据的过程也是非阻塞的。
过程二:数据就绪
read 函数的效果是,如果没有数据到达时(到达网卡并拷贝到了内核缓冲区),立刻返回一个错误值(-1),而不是阻塞地等待。只有当操作系统告诉用户线程数据已经准备就绪的时候,数据从内核缓冲区拷贝到用户缓冲区才通知用户进程调用完成,返回结果,这个过程是阻塞的。

对于用户线程来说,它可以注册多个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学习路线图
P6学习路线图
P7学习路线图
P8学习路线图

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