背景
对于一个Broker来说,可能存在不同业务的数据。假如消费者只关注订单业务,那么它怎么过滤掉非订单业务呢?答案其实很简单:使用Tag或属性进行过滤。
生产者带Tag或属性发送
package com.klcwqy.rocketmq.message.tag;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
public class TagMessageProducer {
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer("test-order-producer-group");
producer.setNamesrvAddr("192.168.8.2:9876;192.168.8.3:9876");
producer.start();
//发送顺序消息:根据业务模式,让同一个事务的消息进同一个MessageQueue
int orderId = 0;
Message message = null;
for (int i = 0; i < 10; i++) {
orderId = i;
//指定Tag
message = new Message("TEST-ORDER-TOPIC", "Tag-A || Tag-B", String.valueOf(orderId).getBytes(RemotingHelper.DEFAULT_CHARSET));
//设置一些属性
message.putUserProperty("item", "TV");
message.putUserProperty("count", "100");
producer.send(message);
}
}
}
消费者使用Tag或属性过滤
package com.klcwqy.rocketmq.message.tag;
import java.util.List;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
public class TagMessageConsume {
public static void main(String[] args) throws Exception {
//创建消费
DefaultMQPushConsumer consume = new DefaultMQPushConsumer("group");
//绑定NameServer
consume.setNamesrvAddr("192.168.8.2:9876;192.168.8.3:9876");
//订阅Topic并使用Tag过滤
consume.subscribe("TEST-ORDER-TOPIC", "Tag-A || Tag-B");
//或订阅Topic并使用sql过滤
//consume.subscribe("TEST-ORDER-TOPIC", MessageSelector.bySql("item = TV and count > 20"));
consume.setMessageModel(MessageModel.CLUSTERING);
//注册监听:顺序消费
consume.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//启动消费者
consume.start();
}
}
RocketMQ支持比较丰富的数据过滤语法,如下所示:
- 数值比较: >, >=,<,< =,BETWEEN,=
- 字符比较:=,<>,IN
- IS NULL 或者 IS NOT NULL
- 逻辑符号: AND, OR, NOT
- 数值,比如:123, 3.1415
- 字符,比如:‘abc’,必须用单引号包裹起来
- NULL,特殊的常量
- 布尔值,TRUE 或 FALSE