
RocketMQ
文章平均质量分 73
Hamilton_Huan
coder
展开
-
基于Netty的网络调用实现
HTTP是互联网上最受欢迎的协议,与现有的HTTP实现相比,Netty的HTTP实现是相当与众不同的。一个定义良好并具有扩展能力的事件模型可以大大提高事件驱动程序的效率,Netty就具有定义良好的I/O事件模型,它采用严格的层次结构来区分不同的事件类型,Netty也允许在不破坏现有代码的情况下实现自己的事件类型。事件模型是Netty的一个亮点,很多NIO通信框架没有或者仅有有限的事件模型概念,当需要一个新的事件类型的时候常常需要修改已有的代码,有的甚至不允许进行自定义的扩展。二是基于JVM实现的传输层;原创 2023-11-30 09:17:45 · 835 阅读 · 0 评论 -
主从同步机制
Broker在启动的时候,判断自己的角色是否是Slave,是的话就启动定时同步任务,如代码清单12-1所示。代码中的关键词是wakeupAll和waitForFlush,在同步方式下,Master每次写消息的时候,都会等待向Slave同步消息的过程,同步完成后再返回,如代码清单12-7所示。RocketMQ的Broker分为Master和Slave两个角色,为了保证高可用性,Master角色的机器接收到消息后,要把内容同步到Slave机器上,这样一旦Master宕机,Slave机器依然可以提供服务。原创 2023-11-29 09:06:50 · 209 阅读 · 0 评论 -
生产者和消费者的底层类
有些情况下只有一个MQClientInstance对象是不够的,比如一个Java程序需要连接两个RoceketMQ集群,从一个集群读取消息,发送到另一个集群,一个MQClientInstance对象无法支持这种场景。注意,MQClientInstance是通过工厂类被创建的,并不是一个单例模式,有些情况下需要创建多个实例。首先来看一下MQClientInstance类的Start函数,从Start函数中的逻辑能大致了解MQClientInstance类的功能,如代码清单11-15所示。原创 2023-11-28 09:16:40 · 148 阅读 · 0 评论 -
消息的并发处理
如果消费模式是CLUSTERING模式,未消费成功的消息会先被发送回Broker,供这个ConsumerGroup里的其他Consumer消费,如果发送回Broker失败,再调用RECONSUME_LATER,消息消费的Status处理逻辑如代码清单11-10所示。TreeMap里以Message Queue的Offset作为Key,以消息内容的引用为Value,保存了所有从MessageQueue获取到但是还未被处理的消息,读写锁控制着多个线程对TreeMap对象的并发访问。原创 2023-11-22 09:10:12 · 190 阅读 · 0 评论 -
DefaultMQPushConsumer的整体流程
根据消费消息方式的不同,OffsetStore的类型也不同。获取消息的逻辑实现在public void pullMessage(final PullRequest pullRequest)函数中,这是一个很大的函数,前半部分是进行一些判断,是进行流量控制的逻辑(见代码清单11-5);获取的消息返回后,根据返回状态,调用相应的处理方法,如代码清单11-6所示。然后是初始化consumeMessageService,根据对消息顺序需求的不同,使用不同的Service类型,如代码清单11-4所示。原创 2023-11-21 09:38:34 · 275 阅读 · 0 评论 -
NameServer源码解析
对于如何选择可重入和不可重入锁,重点看函数间的调用关系,比如多次获取锁的示例代码,如果这个lock是不可重入的,代码无法正常执行,如代码清单10-7所示。RouteInfoManager中使用的是可重入的读写锁(private final ReadWriteLock lock=new ReentrantReadWriteLock()),我们以deleteTopic函数为例,看一下锁的使用方式,如代码清单10-8所示。本节介绍入口代码的功能,阅读源码的时候,很多人喜欢根据执行逻辑,先从入口代码看起。原创 2023-11-21 09:06:02 · 330 阅读 · 0 评论 -
RocketMQ运维工具
还可以查看每个主题的消息投递状态,消息的路由信息(这个主题的消息会发往哪些Broker,对应Broker的Message Queue信息)。修改这个服务是否使用VIPChannel,取决于你的RocketMQ版本,如果版本小于3.5.8,请设置不使用,否则保持默认值(VIPChannel用于实现读写分离,是3.5.8以后的版本才增加的功能)。消息详情可以展示这条消息的详细内容。生产环境的RocketMQ集群,需要持续运行并且要有较高的稳定性,运维是件重要但有时候很繁琐的事,本节介绍运维工具的相关内容。原创 2023-11-20 10:56:29 · 264 阅读 · 0 评论 -
在SpringBoot中使用RocketMQ
Producer和Consumer的初始化比较慢,不建议每发一个消息或者消费一个消息就启动和注销对应的Object,所以适合把初始化操作代码写到@PostConstruct函数里,把关闭操作代码写到@PreDestroy函数里。更多的配置选项,可以到源码中查找。直接使用的方式比较简单,也足够灵活,但不是很符合Spring风格,Spring Boot对于消息传递,有统一的接口模板,基于这个模板可以对接各种类型的消息通信组件,比如Kafka、RabbitMQ、RocketMQ等。原创 2023-11-20 10:50:08 · 871 阅读 · 0 评论 -
提高Producer的发送速度
正常的read和write队列中,元素按扇区号排序,进行正常的IO合并处理以提高吞吐量。超时的read和write的队列中,元素按请求创建时间排序,如果有超时的请求出现,就放进这两个队列,调度算法保证超时(达到最终期限时间)的队列中的IO请求会优先被处理。在一些对速度要求高,但是可靠性要求不高的场景下,比如日志收集类应用,可以采用Oneway方式发送,Oneway方式只发送请求不等待应答,即将数据写入客户端的Socket缓冲区就返回,不等待对方返回结果,用这种方式发送消息的耗时可以缩短到微秒级。原创 2023-11-17 08:48:05 · 93 阅读 · 0 评论 -
Consumer的负载均衡
以AllocateMessageQueueAveragely策略为例,如果创建Topic的时候,把Message Queue数设为3,当Consumer数量为2的时候,有一个Consumer需要处理Topic三分之二的消息,另一个处理三分之一的消息;负载均衡的分配粒度只到Message Queue,把Topic下的所有Message Queue分配到不同的Consumer中,所以Message Queue和Consumer的数量关系,或者整除关系影响负载均衡结果。原创 2023-11-17 08:45:08 · 961 阅读 · 0 评论 -
在Broker端进行消息过滤
使用Tag方式过滤虽然高效,但是支持的逻辑比较简单,在构造Message的时候,还可以通过putUserProperty函数来增加多个自定义的属性,基于这些属性可以做复杂的过滤逻辑,如代码清单7-1所示。上面代码实现了过滤逻辑,它是根据消息的“SequenceId”这个属性来过滤的,其实不一定要根据消息属性来过滤,也可以根据消息体的内容或其他特征过滤,如代码清单7-3所示。Tag和Key的主要差别是使用场景不同,Tag用在Consumer的代码中,用来进行服务端消息过滤,Key主要用于通过命令行查询消息。原创 2023-11-16 09:18:01 · 702 阅读 · 0 评论 -
RocketMQ消息优先级
TypeC处于第三优先级。如果业务需要AA类型的消息被及时处理,可以把这三种相似类型的消息分拆到两个Topic里,比如AA类型的消息在一个单独的Topic,AB、AC类型的消息在另外一个Topic。第一种是比较简单的情况,如果当前Topic里有多种相似类型的消息,比如类型AA、AB、AC,当AB、AC的消息量很大,但是处理速度比较慢的时候,队列里会有很多AB、AC类型的消息在等候处理,这个时候如果有少量AA类型的消息加入,就会排在AB、AC类型消息后面,需要等候很长时间才能被处理。原创 2023-11-15 08:50:07 · 916 阅读 · 0 评论 -
各种故障对RocketMQ消息的影响
第1种情况属于可控的软件问题,内存中的数据不会丢失。第5、6种情况属于硬件故障,发生第5、6种情况的故障,原有机器的磁盘数据可能会丢失。如果第1种情况出现时有持续运行的Producer,一台Master出故障后,Producer只能向Topic下其他的Master机器发送消息,如果Producer采用同步发送方式,不会有消息丢失。第2、3、4种情况属于软件故障,内存的数据可能丢失,所以刷盘策略不同,造成的影响也不同,如果Master、Slave都配置成SYNC_FLUSH,可以达到和第1种情况相同的效果。原创 2023-11-15 08:46:32 · 689 阅读 · 0 评论 -
RocketMQ动态增减机器
比如TestTopic是现有的一个Topic,因为数据量增大需要扩容,新增的一个Broker机器地址是192.168.0.1:10911,这个时候执行下面的命令:sh./bin/mqadmin updateTopic-b 192.168.0.1:10911-t TestTopic-n 192.168.0.100:9876,结果是在新增的Broker机器上,为TestTopic新创建了8个读写队列。由于业务增长,需要对集群进行扩容的时候,可以动态增加Broker角色的机器。2.动态增减Broker。原创 2023-11-15 08:42:30 · 107 阅读 · 0 评论 -
RocketMQ消息重复问题
消息重复一般情况下不会发生,但是如果消息量大,网络有波动,消息重复就是个大概率事件。比如Producer有个函数setRetryTimesWhenSendFailed,设置在同步方式下自动重试的次数,默认值是2,这样当第一次发送消息时,Broker端接收到了消息但是没有正确返回发送成功的状态,就造成了消息重复。对分布式消息队列来说,同时做到确保一定投递和不重复投递是很难的,也就是所谓的“有且仅有一次”。在鱼和熊掌不可兼得的情况下,RocketMQ选择了确保一定投递,保证消息不丢失,但有可能造成消息重复。原创 2023-11-15 08:34:35 · 187 阅读 · 0 评论 -
RocketMQ的顺序消息
在MessageListenerOrderly的实现中,为每个Consumer Queue加个锁,消费每个消息前,需要先获得这个消息对应的Consumer Queue所对应的锁,这样保证了同一时间,同一个Consumer Queue的消息不被并发消费,但不同Consumer Queue的消息可以并发处理。在数据的读取过程中,可能有多个Consumer,每个Consumer也可能启动多个线程并行处理,所以消息被哪个Consumer消费,被消费的顺序和写入的顺序是否一致是不确定的。原创 2023-11-14 09:44:48 · 189 阅读 · 0 评论 -
消息队列的核心机制
3)为了保证完全的顺序写,需要ConsumeQueue这个中间结构,因为ConsumeQueue里只存偏移量信息,所以尺寸是有限的,在实际情况中,大部分的ConsumeQueue能够被全部读入内存,所以这个中间结构的操作速度很快,可以认为是内存读取的速度。RocketMQ消息的存储是由ConsumeQueue和CommitLog配合完成的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。这就达到了消费端的高可用性。原创 2023-11-14 09:39:03 · 321 阅读 · 0 评论 -
RocketMQ底层通信机制
RocketMQ是基于Netty库来完成RemotingServer和RemotingClient具体的通信实现的,Netty是个事件驱动的网络编程框架,它屏蔽了Java Socket、NIO等复杂细节,用户只需用好Netty,就可以实现一个“网络编程专家+并发编程专家”水平的Server、Client网络程序。在Consumer的源码中,获取消息的底层通信部分同样发送一个RemotingCommand请求,返回的response也是个RemotingCommand类型,如代码清单4-8所示。原创 2023-11-13 13:58:04 · 599 阅读 · 0 评论 -
各个角色间的交互流程
注意最后一步是向NameServer发送注册信息,NameServer完成创建Topic的逻辑后,其他客户端才能发现新增的Topic,相关逻辑在org.apache.rocketmq.namesrv.routeinfo的RouteInfoManager类中的registerBroker函数里,首先更新Broker信息,然后对每个Master角色的Broker,创建一个QueueData对象。具体的创建动作是通过发送命令触发的,如代码清单4-4所示。代码清单4-4 updateTopic的命令。原创 2023-11-13 13:45:56 · 168 阅读 · 0 评论 -
NameServer的作用及功能
BrokerLiveTable存储的内容是这台Broker机器的实时状态,包括上次更新状态的时间戳,NameServer会定期检查这个时间戳,超时没有更新就认为这个Broker无效了,将其从Broker列表里清除。NameServer本身是无状态的,也就是说NameServer中的Broker、Topic等状态信息不会持久存储,都是由各个角色定时上报并存储到内存中的(NameServer支持配置参数的持久化,一般用不到)。从代码可以看出是每10秒检查一次,时间戳超过2分钟则认为Broker已失效。原创 2023-11-10 08:58:10 · 636 阅读 · 0 评论 -
RocketMQ自定义日志输出
首先需要把rocketmq.Client.Log.loadconfig参数设置为false,可以在程序中使用System.setProperty("rocketmq.Client.Log.loadconfig","false")语句,或者在JVM启动时使用-D参数来设置。Log是监控系统状态,排查问题的重要手段,RocketMQ的默认Log存储位置是:${user.home}/Logs/rocketmqLogs,Log配置文件的设置可以通过JVM启动参数、环境变量、代码中的设置语句这三种方式来配置。原创 2023-11-10 08:51:09 · 1350 阅读 · 0 评论 -
如何存储队列位置信息
如果Consumer正常运行后被停止,然后再启动,会接着上次的Offset开始消费,ConsumeFromWhere的设置无效。首先来明确一下Offset的含义,RocketMQ中,一种类型的消息会放到一个Topic里,为了能够并行,一般一个Topic会有多个Message Queue(也可以设置成一个),Offset是指某个Topic下的一条消息在某个Message Queue里的位置,通过Offset的值可以定位到这条消息,或者指示Consumer从这条消息开始向后继续处理。原创 2023-11-10 08:43:17 · 100 阅读 · 0 评论 -
不同类型的生产者
Consumer在消费消息的时候,会根据负载均衡策略,消费被分配到的Message Queue,如果不经过特定的设置,某条消息被发往哪个Message Queue,被哪个Consumer消费是未知的。消息的发送有同步和异步两种方式,上面的代码使用的是异步方式。消息发送的返回状态有如下四种:FLUSH_DISK_TIMEOUT、FLUSH_SLAVE_TIMEOUT、SLAVE_NOT_AVAILABLE、SEND_OK,不同状态在不同的刷盘策略和同步策略的配置下含义是不同的。原创 2023-11-09 10:03:18 · 392 阅读 · 0 评论 -
Push和Pull两种类型的消费者
如果不需要消费某个Topic下的所有消息,可以通过指定消息的Tag进行消息过滤,比如:Consumer.subscribe("TopicTest","tag1||tag2||tag3"),表示这个Consumer要消费“TopicTest”下带有tag1或tag2或tag3的消息(Tag是在发送消息时设置的标签)。如何重复处理某些消息?需要注意的是Offset的保存,要在程序的异常处理部分增加把Offset写入磁盘方面的处理,记准了每个Message Queue的Offset,才能保证消息消费的准确性。原创 2023-11-09 09:59:08 · 323 阅读 · 0 评论 -
RocketMQ常用管理命令
消息的发送和接收都要有对应的Topic,需要向某个Topic发送或接收消息,所以在正式使用RocketMQ进行消息发送和接收前,要先创建Topic,创建Topic的指令是updateTopic,表2-1列出了支持的参数。Broker有很多的配置信息,在Broker启动时,可以通过配置文件来指定配置信息。Topic的路由信息指的是某个Topic所在的Broker相关信息,客户端可以通过NameServer来获取这些信息,本命令一般在调试的时候使用,指令是TopicRoute,表2-7列出了支持的参数。原创 2023-11-09 09:49:24 · 2694 阅读 · 0 评论 -
Java发送/接收消息示例
主要流程是:创建一个DefaultMQProducer对象,设置好GroupName和NameServer地址后启动,然后把待发送的消息拼装成Message对象,使用Producer来发送。接下来看看如何接收消息,也就是使用DefaultMQPush-Consumer类实现的消费者程序,如示例程序2所示。可以用自己熟悉的开发工具创建一个Java项目,加入RocketMQ Client包的依赖,示例程序1的内容发送消息,这个示例代码是以Sync方式发送消息的。原创 2023-11-08 08:53:10 · 354 阅读 · 0 评论 -
RocketMQ多机集群配置和部署
这样一个高可用的RocketMQ集群就搭建好了,还可以在一台机器上启动rocketmq-console,比如在192.168.100.131上启动RocketMQ-console,然后在浏览器中输入地址192.168.100.131:8080,这样就可以可视化地查看集群状态了。现在使用云服务或多网卡的机器比较普遍,Broker自动探测获得的ip地址可能不符合要求,通过brokerIP1=47.98.41.234这样的配置参数,可以设置Broker机器对外暴露的ip地址。原创 2023-11-08 08:48:55 · 926 阅读 · 0 评论 -
RocketMQ的组成部分
一个分布式消息队列中间件部署好以后,可以给很多个业务提供服务,同一个业务也有不同类型的消息要投递,这些不同类型的消息以不同的Topic名称来区分。现实生活中的邮政系统要正常运行,离不开下面这四个角色,一是发信者,二是收信者,三是负责暂存、传输的邮局,四是负责协调各个地方邮局的管理机构。启动RocketMQ的顺序是先启动NameServer,再启动Broker,这时候消息队列已经可以提供服务了,想发送消息就使用Producer来发送,想接收消息就使用Consumer来接收。原创 2023-11-03 13:17:52 · 171 阅读 · 0 评论 -
RocketMQ安装及配置
bin文件夹里含有各种使用RocketMQ的shell脚本(Linux平台)和cmd脚本(Windows平台),比如常用的启动NameServer的脚本mqnamesrv,启动Broker的脚本mqbroker,集群管理脚本mqadmin等;为了快速展示发送和接收消息,本节展示的是用命令行发送和接收消息,实际上就是运行写好的demo程序,后续我们可以参考这些demo来写自己的发送和接收程序。启动单机的消息队列服务比较简单,不需要写配置文件,只需要依次启动本机的NameServer和Broker即可。原创 2023-11-03 09:04:01 · 101 阅读 · 0 评论 -
消息队列的功能作用
数据的产生方只需要把各自的数据写入一个消息队列即可,数据使用方根据各自需求订阅感兴趣的数据,不同数据团队所订阅的数据可以重复也可以不重复,互不干扰,也不必和数据产生方关联。举个例子,如果订单系统每秒最多能处理一万次下单,这个处理能力应对正常时段的下单是绰绰有余的,正常时段我们下单后一秒内就能返回结果。如图1-1所示,当转变成基于消息队列的方式后,系统可用性就高多了,比如物流系统因为发生故障,需要几分钟的时间来修复,在这几分钟的时间里,物流系统要处理的内容被缓存在消息队列里,用户的下单操作可以正常完成。原创 2023-11-02 16:07:41 · 91 阅读 · 0 评论 -
RocketMQ的一些核心概念
RocketMQ的一些核心概念原创 2023-11-02 09:19:33 · 68 阅读 · 0 评论