为了账号安全,请及时绑定邮箱和手机立即绑定

发消息的时候选择queue的算法有哪些?

标签:
JQuery

一、说明

分为两种,一种是直接发消息,client内部有选择queue的算法,不允许外界改变。还有一种是可以自定义queue的选择算法(内置了三种算法,不喜欢的话可以自定义算法实现)。

public class org.apache.rocketmq.client.producer.DefaultMQProducer {
    // 只发送消息,queue的选择由默认的算法来实现
    @Override
    public SendResult send(Collection<Message> msgs) {}
    
    // 自定义选择queue的算法进行发消息
    @Override
    public SendResult send(Collection<Message> msgs, MessageQueue messageQueue) {}
}

二、源码

1、send(msg, mq)

1.1、使用场景

有时候我们不希望默认的queue选择算法,而是需要自定义,一般最常用的场景在顺序消息,顺序消息的发送一般都会指定某组特征的消息都发当同一个queue里,这样才能保证顺序,因为单queue是有序的。

对顺序消息不明白的请看我之前的顺序消息文章。

1.2、原理剖析

内置了三种算法,三种算法都实现了一个共同的接口:

org.apache.rocketmq.client.producer.MessageQueueSelector

  • SelectMessageQueueByRandom

  • SelectMessageQueueByHash

  • SelectMessageQueueByMachineRoom

  • 要想自定义逻辑的话,直接实现接口重写select方法即可。

很典型的策略模式,不同算法不同实现类,有个顶层接口。

1.2.1、SelectMessageQueueByRandom

public class SelectMessageQueueByRandom implements MessageQueueSelector {
    private Random random = new Random(System.currentTimeMillis());
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        // mqs.size():队列的个数。假设队列个数是4,那么这个value就是0-3之间随机。
        int value = random.nextInt(mqs.size());
        return mqs.get(value);
    }
}

so easy,就是纯随机。

mqs.size():队列的个数。假设队列个数是4,那么这个value就是0-3之间随机。

1.2.2、SelectMessageQueueByHash

public class SelectMessageQueueByHash implements MessageQueueSelector {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        int value = arg.hashCode();
        // 防止出现负数,取个绝对值,这也是我们平时开发中需要注意到的点
        if (value < 0) {
            value = Math.abs(value);
        }
        // 直接取余队列个数。
        value = value % mqs.size();
        return mqs.get(value);
    }
}

so easy,就是纯取余。

mqs.size():队列的个数。假设队列个数是4,且value的hashcode是3,那么3 % 4 = 3,那么就是最后一个队列,也就是四号队列,因为下标从0开始。

1.2.3、SelectMessageQueueByMachineRoom

public class SelectMessageQueueByMachineRoom implements MessageQueueSelector {
    private Set<String> consumeridcs;
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        return null;
    }
    public Set<String> getConsumeridcs() {
        return consumeridcs;
    }
    public void setConsumeridcs(Set<String> consumeridcs) {
        this.consumeridcs = consumeridcs;
    }
}

没看懂有啥鸟用,直接return null; 所以如果有自定义需求的话直接自定义就好了,这玩意没看出有啥卵用。

1.2.4、自定义算法

public class MySelectMessageQueue implements MessageQueueSelector {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        return mqs.get(0);
    }
}

永远都选择0号队列,也就是第一个队列。只是举个例子,实际看你业务需求。

1.3、调用链

org.apache.rocketmq.client.producer.DefaultMQProducer#send(Message msg, MessageQueueSelector selector, Object arg)
->
org.apache.rocketmq.client.producer.DefaultMQProducer#send(Message msg, MessageQueueSelector selector, Object arg)
->
org.apache.rocketmq.client.producer.DefaultMQProducer#send(Message msg, MessageQueueSelector selector, Object arg, long timeout)
->
org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl#sendSelectImpl(xxx)
->
mq = mQClientFactory.getClientConfig().queueWithNamespace(selector.select(messageQueueList, userMessage, arg));
->
selector.select(messageQueueList, userMessage, arg)
->
org.apache.rocketmq.client.producer.MessageQueueSelector#select(final List<MessageQueue> mqs, final 


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消