应用场景
- 异步。例如:用户注册后需要发送邮件,当用户注册信息保存到数据库后可以选择发送消息,由消息的接收方来发送邮件,从而实现异步,提高响应时间
- 解耦。例如:电商网站中用户下单后需要扣减库存。当保存订单后发送消息到mq,库存系统去监听mq,从而实现与库存系统的解耦
- 削峰填谷。例如:在流量激增的场景下(秒杀等业务),可以将请求写入消息队列,由消费者慢慢消费
- 消息通信
-
部署架构
RocketMQ的部署架构主要分为NameServer,Broker,Producer和Consumer。
当Broker(MasterBroker、SlaveBroker)启动时,会向NameServer集群中的每一个NameServer注册,并每隔30s向NameServer发送心跳。每个NameServer都存了所有Broker的信息
- 生产者从NameServer中拉取路由信息,通过长连接将消息发送到MasterBroker中
- 消费者先从NamsServer中拉取路由信息,从MasterBroker或SlaveBroker中拉取消息(具体由MasterBroker决定)
消息发送及消费
- 生产者从NameServer中拉取Topic的源信息,其中包含了每个Topic有几台Broker以及有几个队列
- 生产者根据负载均衡策略选择需要将消息发送到哪台Broker的哪个队列中
- 消费者从对应的队列中拉取消息进行消费。但是如果一个Topic下有2个队列,但是有3台Consumer,那么其中一台是无法消费消息的
Broker消息存储
当broker收到消息后是将消息在CommitLog文件中顺序添加(超过1G会创建新文件),同时每个队列会对应一个ConsumeQueue,每个ConsumeQueue会记录消息的物理地址
同步刷盘
当消息发送到broker时,强制broker必须将消息存入磁盘。对性能有影响,一般金融业务会使用
异步刷盘
当消息发送到broker时,broker先将消息存储在内存中,后由os线程将数据刷入磁盘。如果数据在内存中还未被写入磁盘时,broker宕机会导致数据丢失
事务型消息
生产者先向RocketMQ发送一个half消息(不会被消费者消费),然后执行数据库操作,根据数据库操作结果commit或rollback消息。如果commit或rollback的消息丢失的话RocketMQ会等待一段执行后查询Producer该消息的状态,然后再决定commit还是rollback
顺序消息
下图中,Producer生产了2条消息(消息1先发出),其中消息1会发送到Consume Queue1,对应Consumer1消费,消息2会发送到Consume Queue2,由Consumer2消费。但是由于Consumer1目前负载比较高,导致消息2先与消息1消费,对于消息有先后顺序的数据来说,会导致数据错乱。所以顺序消息的本质是将有先后顺序的消息发送到同一个队列中。
当生产者发送消息的时候需要提供一个保证顺序的字段,例如:如果id一致的消息应该保证顺序执行,那么我们就通过id%队列数,从而找到这条消息对应的Consume Queue。但是需要注意如果消费失败需要返回SUSPEND_CURRENT_QUEUE_MOMENT状态
常用参数设置
os参数
vm.overcommit_memory
0:中间件向系统申请内存时,如果系统内存够会分配,如果内存不够,就拒绝申请 1:所有物理内存都允许分配给中间件 一般都设置为1 2:内核允许分配超过所有物理内存和交换空间总和的内存
vm.max_map_count
中间件系统可以开启的线程数量,默认65535 一般设计为655350
vm.swappiness
将部分不活跃的进程放入磁盘上的swap分区。尽量还是使用物理内存,这个值应设小一点,例如10
ulimit
用来控制linux上的最大文件连接数,默认1024。可以适当放大一些
