首页 > IT职业 > IT职场 > 发消息的时候选择queue的算法有哪些?
分为两种,一种是直接发消息,client内部有选择queue的算法,不允许外界改变。还有一种是可以自定义queue的选择算法(内置了三种算法,不喜欢的话可以自定义算法实现)。
public class org.apache.rocketmq.client.producer.DefaultMQProducer {
// 只发送消息,queue的选择由默认的算法来实现
@Override
public SendResult send(Collection msgs) {}
// 自定义选择queue的算法进行发消息
@Override
public SendResult send(Collection msgs, MessageQueue messageQueue) {}
}
有时候我们不希望默认的queue选择算法,而是需要自定义,一般最常用的场景在顺序消息,顺序消息的发送一般都会指定某组特征的消息都发当同一个queue里,这样才能保证顺序,因为单queue是有序的。
对顺序消息不明白的请看我之前的顺序消息文章。
内置了三种算法,三种算法都实现了一个共同的接口:
org.apache.rocketmq.client.producer.MessageQueueSelector
SelectMessageQueueByRandom
SelectMessageQueueByHash
SelectMessageQueueByMachineRoom
要想自定义逻辑的话,直接实现接口重写select方法即可。
很典型的策略模式,不同算法不同实现类,有个顶层接口。
public class SelectMessageQueueByRandom implements MessageQueueSelector {
private Random random = new Random(System.currentTimeMillis());
@Override
public MessageQueue select(List 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之间随机。
public class SelectMessageQueueByHash implements MessageQueueSelector {
@Override
public MessageQueue select(List mqs, Message msg, Object arg) {
int value = arg.hashCode();
// 防止出现负数,取个绝对值,这也是我们平时开发中需要注意到的点
if (value value = Math.abs(value);
}
// 直接取余队列个数。
value = value % mqs.size();
return mqs.get(value);
}
}
so easy,就是纯取余。
mqs.size():队列的个数。假设队列个数是4,且value的hashcode是3,那么3 % 4 = 3,那么就是最后一个队列,也就是四号队列,因为下标从0开始。
public class SelectMessageQueueByMachineRoom implements MessageQueueSelector {
private Set consumeridcs;
@Override
public MessageQueue select(List mqs, Message msg, Object arg) {
return null;
}
public Set getConsumeridcs() {
return consumeridcs;
}
public void setConsumeridcs(Set consumeridcs) {
this.consumeridcs = consumeridcs;
}
}
没看懂有啥鸟用,直接return null; 所以如果有自定义需求的话直接自定义就好了,这玩意没看出有啥卵用。
public class MySelectMessageQueue implements MessageQueueSelector {
@Override
public MessageQueue select(List mqs, Message msg, Object arg) {
return mqs.get(0);
}
}
永远都选择0号队列,也就是第一个队列。只是举个例子,实际看你业务需求。
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 mqs, final
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/3330/viewspace-2797791/ ,如需转载,请注明出处,否则将追究法律责任。