消息队列高手课
李玥
美团高级技术专家
52199 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
进阶篇 (21讲)
消息队列高手课
15
15
1.0x
00:00/00:00
登录|注册

加餐 | JMQ的Broker是如何异步处理消息的?

利用进阶篇知识开发简单的RPC框架
实现消息队列必备的技术知识
消息队列原理和使用方法
提出改进意见
优化空间
实现双工通信
使用专有序列化方法
使用异步设计
优化性能
实现高性能的异步网络通信
异步发送响应
无锁设计
使用写缓存
异步设计
使用专门线程发送响应
刷盘和复制异步执行
使用缓存Journal Cache
WriteThread处理消息
入口处理请求
6组线程拆分大流程
每秒处理超过100万次请求
给消费者发送消息
接收生产者消息
案例篇
进阶篇
基础篇
思考题
参考实现
作业要求
重要优化点
异步设计思想
优化后的消息生产流程
Broker核心流程
消息队列高手课
俩大爷的思考题
JMQ的Broker异步处理消息
课程设计思路
JMQ的Broker是如何异步处理消息的?

该思维导图由 AI 生成,仅供参考

你好,我是李玥。
我们的课程更新到进阶篇之后,通过评论区的留言,我看到有一些同学不太理解,为什么在进阶篇中要讲这些“看起来和消息队列关系不大的”内容呢?
在这里,我跟你分享一下这门课程的设计思路。我们这门课程的名称是“消息队列高手课”,我希望你在学习完这门课程之后,不仅仅只是成为一个使用消息队列的高手,而是设计和实现消息队列的高手。所以我们在设计课程的时候,分了基础篇、进阶篇和案例篇三部分。
基础篇中我们给大家讲解消息队列的原理和一些使用方法,重点是让大家学会使用消息队列。
你在进阶篇中,我们课程设计的重点是讲解实现消息队列必备的技术知识,通过分析源码讲解消息队列的实现原理。希望你通过进阶篇的学习能够掌握到设计、实现消息队列所必备的知识和技术,这些知识和技术也是设计所有高性能、高可靠的分布式系统都需要具备的。
进阶篇的上半部分,我们每一节课一个专题,来讲解设计实现一个高性能消息队列,必备的技术和知识。这里面每节课中讲解的技术点,不仅可以用来设计消息队列,同学们在设计日常的应用系统中也一定会用得到。
前几天我在极客时间直播的时候也跟大家透露过,由我所在的京东基础架构团队开发的消息队列 JMQ,它的综合性能要显著优于目前公认性能非常好的 Kafka。虽然在开发 JMQ 的过程中有很多的创新,但是对于性能的优化这块,并没有什么全新的划时代的新技术,JMQ 之所以能做到这样的极致性能,靠的就是合理地设计和正确地使用已有的这些通用的底层技术和优化技巧。我把这些技术和知识点加以提炼和总结,放在进阶篇的上半部分中。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

JMQ消息队列的异步消息处理流程设计是本文的重点。文章详细介绍了消息生产的流程,包括消息的接收、解析、复制和写入磁盘等步骤,并强调了设计中的异步思想。通过图示和详细描述,展示了消息处理流程的各个环节和线程之间的协作关系。此外,文章突出强调了设计中的优化措施,包括异步设计、缓存设计、无锁设计等,以及对相关技术点的深入理解和合理使用的重要性。作者鼓励读者在学习这些知识点时,不仅要记住和应用,更要深刻理解技术背后的思想,并能在实际设计和开发中灵活运用。总体而言,本文通过对JMQ消息队列异步处理流程的深入剖析,为读者提供了丰富的技术知识和设计思路,对于想要深入了解消息队列技术和提升技术水平的读者具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《消息队列高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(61)

  • 最新
  • 精选
  • 包明
    Requests Queue 内存级的 怎么做到不丢请求?

    作者回复: 你要明白一件事儿,客户端发来一条数据,直到服务端返回给客户端发送成功,这段时间内,数据是允许丢失的。 数据丢失后,客户端收不到发送成功响应,自然会重试。

    2019-08-26
    4
    67
  • 青舟
    https://github.com/qingzhou413/geektime-mq-rpc.git 使用netty作为网络库,server和client的io线程数都是1,笔记本4核标压2.3G时间2.3秒。

    作者回复: 👍👍👍

    2019-08-24
    3
    27
  • ub8
    老师,文中提到的 “我们把回复响应这个需要等待资源的操作,也异步放到其他的线程中去执行。”;这个是怎么实现的呢? ResponseThread ,和 RequestThread 是如何对应上的?

    作者回复: 一般简单常用的做法都是在处理request的线程中执行业务逻辑,然后把response返回。 其实从网络层面来看,Request和Response只是客户端和服务端互相发送的两段数据,和服务端处理用什么线程完全没有关系。 Request和Response如何对应,这个取决于网络传输协议是怎么设计的。这个我们在课程中讲过。 在服务端实现中,可以接受到Request之后,进行异步处理,异步处理完成之后,无论在什么线程中,只要能拿到处理结果构建出Response,通过网络发给客户端就可以了。

    2019-12-14
    4
    14
  • linqw
    老师有个疑问,帮忙解答下哦,在上面的那个流程图中,WriteThread是单线程从请求队列中获取到消息然后把消息放到journal Cache,开启ReplicationThread、FlushThread进行处理,能否把WriteThread做成分配器了,mq只要保证topic下的队列有序就可以,同一个队列的消息由WriteThread分配给同一个线程进行处理,线程池的形式,线程池中的每个工作线程内部都有个集合保存消息,如果前面没有同一个队列的消息,分配给最空闲的线程进行执行,那这样的话,WriteThread只要分配消息,比如可以对发送过来的消息中要保存的队列属性值进行hash,然后根据hash值判断线程池中的所有线程的消息集合是否有相同队列的消息,有的话分配给同一个线程执行,没有的话最空闲的线程执行,mysql的binlog同步也是有几种这种策略,并发的同步sql,刚开始是基于库,同一个库的sql分配到一个线程执行同步,不同库进行并发,后来是基于redo log的组提交形式,能组提交的sql可以并发的同步,再后来是WRITESET,根据库名、表名、索引(主键和唯一索引)计算hash进行分发策略。

    作者回复: 这个流程中处理的数据已经是被分配过的,单个队列的数据。

    2019-08-25
    8
  • 吾皇万岁万岁万万岁
    请问老师,JMQ在follower节点响应后,就给生产者发送确认消息,此时如果leader节点故障,数据还在JournalCache里面,拿是不是可以认为这部分数据丢失?

    作者回复: 不会丢,因为数据已经复制到了从节点上,leader宕机后,会重新选举出新的leader(也就是之前的某个follower),这个新leader上是有原leader上的全部数据的。

    2019-08-24
    6
    8
  • 李冲
    借用老师的的go源码经过读,写,去掉锁3次演进,分别在金山云ECS(2核4G)上跑到3.1/2.4/1.4秒的样子。 最终的文件:https://github.com/lichongsw/algorithm/blob/master/duplex_communication_optimization_3_no_write_lock.go

    作者回复: 👍👍👍

    2019-11-26
    2
    7
  • 李心宇🦉
    老师好,我对JMQ的broker接收生产者请求并写入消息的流程有个疑问。 在处理完数据落盘和多节点数据复制之后,要给生产者回复响应了,这时候broker如何能找到生产者呢?我理解是第一步生产者发送请求建立的TCP连接句柄没有释放,最后再通过这个连接句柄来write响应。这样的话,还是每个连接在得到响应之前不能释放需要占用一个线程啊。请问是怎么做到在第一步接收响应阶段只需要很少的线程的?是不是利用异步非阻塞,在线程里设置大量的协程来处理请求?

    作者回复: 你的大部分理解都没问题,有一个小问题是,维持一个TCP连接并不一定需要占用一个线程。只有在这个连接上执行收发数据的时候,才需要占用线程。收到请求处理完,把请求交给其它线程处理后,当前线程就可以释放了。直到响应生成后,这段时间只维持TCP连接是不需要占用任何线程的。

    2019-10-23
    3
    5
  • Martin
    https://github.com/MartinDai/mq-in-action/blob/master/src/main/java/com/doodl6/mq/MeetInRpc.java 基于netty4实现的,Macbook pro 2015款 13寸 测试差不多4.2秒左右,老师帮忙看看哪里还可以有优化空间吗

    作者回复: 👍👍👍正确写出这个程序差不多就是这个耗时。

    2019-09-20
    2
    5
  • 南辕北辙
    把老师的代码看了n遍,再用java的原生nio实现了一遍,理解了老师的用心良苦。前二章序列化与网络协议那块的知识,对应代码对于struct的构造,四字节的总长度,四字节的序号,以及变长内容,然后二个大爷在接受到数据以后也是根据这个协议进行取数据。也就对应了序列化以及协议都是自定义的!!二个大爷都懂该怎么从二进制的数据中,提取出对话。

    作者回复: 恭喜你学到了😄

    2019-08-26
    4
    3
  • 刘天鹏
    老师的writeTo函数没必要加锁吧,用一个局部缓冲把lengthByte serialBytes payloadBytes拼装好再一起发送应该就可以了 我把我的大爷改成双工的,多线程的,可以打包发送的,现在大爷还只有一张嘴一个耳朵(一个socket连接) 可能是没有逻辑处理的负担,多线程没啥改变 打包发送有一定的改进,1次3条数据 14s 现在100万次胡同碰面,8.66s(公司的i7) https://gist.github.com/liutianpeng/d9330f85d47525a8e32dcd24f5738e55

    作者回复: 如果是多个线程并发向同一个socket中写数据,这个锁是必须加的。 比如,A线程发送“123456”,B线程发送“abcd”,如果不加锁,对端收到的可能就成了“12abc345d6”,这种数据是对端是没法解析的。

    2019-08-26
    2
    3
收起评论
显示
设置
留言
61
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部