加餐 | JMQ的Broker是如何异步处理消息的?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
JMQ消息队列的异步消息处理流程设计是本文的重点。文章详细介绍了消息生产的流程,包括消息的接收、解析、复制和写入磁盘等步骤,并强调了设计中的异步思想。通过图示和详细描述,展示了消息处理流程的各个环节和线程之间的协作关系。此外,文章突出强调了设计中的优化措施,包括异步设计、缓存设计、无锁设计等,以及对相关技术点的深入理解和合理使用的重要性。作者鼓励读者在学习这些知识点时,不仅要记住和应用,更要深刻理解技术背后的思想,并能在实际设计和开发中灵活运用。总体而言,本文通过对JMQ消息队列异步处理流程的深入剖析,为读者提供了丰富的技术知识和设计思路,对于想要深入了解消息队列技术和提升技术水平的读者具有很高的参考价值。
《消息队列高手课》,新⼈⾸单¥59
全部留言(61)
- 最新
- 精选
- 包明Requests Queue 内存级的 怎么做到不丢请求?
作者回复: 你要明白一件事儿,客户端发来一条数据,直到服务端返回给客户端发送成功,这段时间内,数据是允许丢失的。 数据丢失后,客户端收不到发送成功响应,自然会重试。
2019-08-26467 - 青舟https://github.com/qingzhou413/geektime-mq-rpc.git 使用netty作为网络库,server和client的io线程数都是1,笔记本4核标压2.3G时间2.3秒。
作者回复: 👍👍👍
2019-08-24327 - ub8老师,文中提到的 “我们把回复响应这个需要等待资源的操作,也异步放到其他的线程中去执行。”;这个是怎么实现的呢? ResponseThread ,和 RequestThread 是如何对应上的?
作者回复: 一般简单常用的做法都是在处理request的线程中执行业务逻辑,然后把response返回。 其实从网络层面来看,Request和Response只是客户端和服务端互相发送的两段数据,和服务端处理用什么线程完全没有关系。 Request和Response如何对应,这个取决于网络传输协议是怎么设计的。这个我们在课程中讲过。 在服务端实现中,可以接受到Request之后,进行异步处理,异步处理完成之后,无论在什么线程中,只要能拿到处理结果构建出Response,通过网络发给客户端就可以了。
2019-12-14414 - linqw老师有个疑问,帮忙解答下哦,在上面的那个流程图中,WriteThread是单线程从请求队列中获取到消息然后把消息放到journal Cache,开启ReplicationThread、FlushThread进行处理,能否把WriteThread做成分配器了,mq只要保证topic下的队列有序就可以,同一个队列的消息由WriteThread分配给同一个线程进行处理,线程池的形式,线程池中的每个工作线程内部都有个集合保存消息,如果前面没有同一个队列的消息,分配给最空闲的线程进行执行,那这样的话,WriteThread只要分配消息,比如可以对发送过来的消息中要保存的队列属性值进行hash,然后根据hash值判断线程池中的所有线程的消息集合是否有相同队列的消息,有的话分配给同一个线程执行,没有的话最空闲的线程执行,mysql的binlog同步也是有几种这种策略,并发的同步sql,刚开始是基于库,同一个库的sql分配到一个线程执行同步,不同库进行并发,后来是基于redo log的组提交形式,能组提交的sql可以并发的同步,再后来是WRITESET,根据库名、表名、索引(主键和唯一索引)计算hash进行分发策略。
作者回复: 这个流程中处理的数据已经是被分配过的,单个队列的数据。
2019-08-258 - 吾皇万岁万岁万万岁请问老师,JMQ在follower节点响应后,就给生产者发送确认消息,此时如果leader节点故障,数据还在JournalCache里面,拿是不是可以认为这部分数据丢失?
作者回复: 不会丢,因为数据已经复制到了从节点上,leader宕机后,会重新选举出新的leader(也就是之前的某个follower),这个新leader上是有原leader上的全部数据的。
2019-08-2468 - 李冲借用老师的的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-2627 - 李心宇🦉老师好,我对JMQ的broker接收生产者请求并写入消息的流程有个疑问。 在处理完数据落盘和多节点数据复制之后,要给生产者回复响应了,这时候broker如何能找到生产者呢?我理解是第一步生产者发送请求建立的TCP连接句柄没有释放,最后再通过这个连接句柄来write响应。这样的话,还是每个连接在得到响应之前不能释放需要占用一个线程啊。请问是怎么做到在第一步接收响应阶段只需要很少的线程的?是不是利用异步非阻塞,在线程里设置大量的协程来处理请求?
作者回复: 你的大部分理解都没问题,有一个小问题是,维持一个TCP连接并不一定需要占用一个线程。只有在这个连接上执行收发数据的时候,才需要占用线程。收到请求处理完,把请求交给其它线程处理后,当前线程就可以释放了。直到响应生成后,这段时间只维持TCP连接是不需要占用任何线程的。
2019-10-2335 - Martinhttps://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-2025 - 南辕北辙把老师的代码看了n遍,再用java的原生nio实现了一遍,理解了老师的用心良苦。前二章序列化与网络协议那块的知识,对应代码对于struct的构造,四字节的总长度,四字节的序号,以及变长内容,然后二个大爷在接受到数据以后也是根据这个协议进行取数据。也就对应了序列化以及协议都是自定义的!!二个大爷都懂该怎么从二进制的数据中,提取出对话。
作者回复: 恭喜你学到了😄
2019-08-2643 - 刘天鹏老师的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-2623