【RocketMQ】原理分析:Producer消息发送模式、分发规则

1.消息发送模式

1.1 同步发送

同步消息发送模式就是说消息发送出去后,producer会等到broker回应后才能继续发送下一个消息

在这里插入图片描述

DefaultMQProducer producer = new DefaultMQProducer("my_producer_group");
producer.send(message); // 同步发送

返回的SendResult有四种状态:SEND OK(成功),FLUSH_DISK_TIMEOUT(刷盘超时),FLUSH_SLAVE_TIMEOUT(同步超时),SLAVE_NOT_AVAILABLE,

1.2 异步发送

异步发送是指发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

在这里插入图片描述

MQ 的异步发送,需要用户实现异步发送回调接口(SendCallback)。消息发送方在发送了一条消息后,不需要等待服务器响应即可返回,进行第二条消息发送。发送方通过回调接口接收服务器响应,并对响应结果进行处理

DefaultMQProducer producer = new DefaultMQProducer("my_producer_group");
producer.send(msg, new SendCallback() {    
    @Override // 成功回调
    public void onSuccess(SendResult sendResult) {    
        System.out.printf("%s%n",sendResult);  
    }    
    @Override // 失败回调
    public void onException(Throwable throwable) {     
        throwable.printStackTrace();  
    } 
});

1.3 单向发送

单向(Oneway)发送特点为发送方只负责发送消息,不等待服务器回应且没有回调函数触发,即只发送请求不等待应答.效率最高

在这里插入图片描述

DefaultMQProducer producer = new DefaultMQProducer("my_producer_group");
producer.sendOneway(msg);

1.4 顺序发送

在kafka中,消息可以通过自定义分区策略来实现消息的顺序发送,实现原理就是把同一类消息都发送到相同的分区上。

在RocketMQ中,是基于多个Message Queue来实现类似于kafka的分区效果。如果一个Topic 要发送和接收的数据量非常大, 需要能支持增加并行处理的机器来提高处理速度,这时候一个Topic 可以根据需求设置一个或多个Message Queue。Topic 有了多个Message Queue 后,消息可以并行地向各个 Message Queue 发送,消费者也可以并行地从多个Message Queue 读取消息并消费。

扫描二维码关注公众号,回复: 12741917 查看本文章

2.分发规则

2.1 默认规则

通过自定义发送策略来实现消息只发送到同一个队列,因为一个Topic 会有多个Message Queue ,如果使用Producer 的默认配置,这个Producer 会轮流向各个Message Queue 发送消息。Consumer 在消费消息的时候,会根据负载均衡策略,消费被分配到的Message Queue。

2.2 自定义

如果不经过特定的设置,某条消息被发往哪个Message Queue ,被哪个Consumer 消费是未知的。如果业务需要我们把消息发送到指定的Message Queue 里,比如把同一类型的消息都发往相同的 Message Queue。那是不是可以实现顺序消息的功能呢?

和kafka一样,rocketMQ也提供了消息路由的功能,我们可以自定义消息分发策略,通过实现 MessageQueueSelector,来实现自己的消息分发策略

DefaultMQProducer producer = new DefaultMQProducer("my_producer_group");
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {    
    @Override   
    public MessageQueue select(List<MessageQueue> list, Message message, Object o) {   
        int key=o.hashCode();     
        int size = list.size(); // 当前topic的消息队列数
        int index = key%size;   // 目标队列索引   
        return list.get(index); // list.get(0);   
    }
},"key_"+i);
  •  

猜你喜欢

转载自blog.csdn.net/qq_33762302/article/details/114859111