tag 的使用场景:不同的消费组,订阅同一 topic 不同的 tag,拉取不同的消息并消费。在 topic 内部对消息进行隔离。

producer 发送消息,指定 tag

Message msg = new Message("topic-zhang" /* Topic */,
"TagA" /* Tag */,
"key-zhang",
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
);
SendResult sendResult = producer.send(msg);

consumer 订阅 topic,指定 tag

consumer.subscribe("topic-zhang", "TagA||TagB||TagC");

broker 存储 consumer 订阅的 tag 信息

// org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData
private Set<String> tagsSet = new HashSet<String>();
private Set<Integer> codeSet = new HashSet<Integer>();

broker 计算 tag 的 hashCode,直接取字符串的 hashcode 值

// org.apache.rocketmq.store.CommitLog#checkMessageAndReturnSize
long tagsCode = 0;
String tags = propertiesMap.get(MessageConst.PROPERTY_TAGS);
if (tags != null && tags.length() > 0) {
tagsCode = MessageExtBrokerInner.tagsString2tagsCode(MessageExt.parseTopicFilterType(sysFlag), tags);
} public static long tagsString2tagsCode(final TopicFilterType filter, final String tags) {
if (null == tags || tags.length() == 0) { return 0; } return tags.hashCode();
}

broker 存储消息 tag 的 hashcode 值:

consumeQueue 中一个 entry 占 20 字节:8字节 commitLog 物理偏移,4字节消息大小,8字节 tag 的 hashCode 值

consumer 拉取消息时,broker 根据 conusmer 提供的 offset 去遍历 consumeQueue,检查 tag 的 hashcode 值,是否满足 consumer 的订阅信息,来对消息进行过滤

// org.apache.rocketmq.store.DefaultMessageStore#getMessage
if (messageFilter != null
&& !messageFilter.isMatchedByConsumeQueue(isTagsCodeLegal ? tagsCode : null, extRet ? cqExtUnit : null)) {
if (getResult.getBufferTotalSize() == 0) {
status = GetMessageStatus.NO_MATCHED_MESSAGE;
} continue;
} // org.apache.rocketmq.broker.filter.ExpressionMessageFilter#isMatchedByConsumeQueue
public boolean isMatchedByConsumeQueue(Long tagsCode, ConsumeQueueExt.CqExtUnit cqExtUnit) {
if (null == subscriptionData) {
return true;
} if (subscriptionData.isClassFilterMode()) {
return true;
} // by tags code.
if (ExpressionType.isTagType(subscriptionData.getExpressionType())) { if (tagsCode == null) {
return true;
} if (subscriptionData.getSubString().equals(SubscriptionData.SUB_ALL)) {
return true;
} return subscriptionData.getCodeSet().contains(tagsCode.intValue());
} else {
// no expression or no bloom
if (consumerFilterData == null || consumerFilterData.getExpression() == null
|| consumerFilterData.getCompiledExpression() == null || consumerFilterData.getBloomFilterData() == null) {
return true;
} // message is before consumer
if (cqExtUnit == null || !consumerFilterData.isMsgInLive(cqExtUnit.getMsgStoreTime())) {
log.debug("Pull matched because not in live: {}, {}", consumerFilterData, cqExtUnit);
return true;
} byte[] filterBitMap = cqExtUnit.getFilterBitMap();
BloomFilter bloomFilter = this.consumerFilterManager.getBloomFilter();
if (filterBitMap == null || !this.bloomDataValid
|| filterBitMap.length * Byte.SIZE != consumerFilterData.getBloomFilterData().getBitNum()) {
return true;
} BitsArray bitsArray = null;
try {
bitsArray = BitsArray.create(filterBitMap);
boolean ret = bloomFilter.isHit(consumerFilterData.getBloomFilterData(), bitsArray);
log.debug("Pull {} by bit map:{}, {}, {}", ret, consumerFilterData, bitsArray, cqExtUnit);
return ret;
} catch (Throwable e) {
log.error("bloom filter error, sub=" + subscriptionData
+ ", filter=" + consumerFilterData + ", bitMap=" + bitsArray, e);
}
} return true;
}

rocketMQ 消息的 tag的更多相关文章

  1. RocketMQ 消息队列单机部署及使用

    转载请注明来源:http://blog.csdn.net/loongshawn/article/details/51086876 相关文章: <RocketMQ 消息队列单机部署及使用> ...

  2. RocketMQ消息轨迹-设计篇

    目录 1.消息轨迹数据格式 2.记录消息轨迹 3.如何存储消息轨迹数据 @(本节目录) RocketMQ消息轨迹主要包含两篇文章:设计篇与源码分析篇,本节将详细介绍RocketMQ消息轨迹-设计相关. ...

  3. rocketMq消息的发送和消息消费

    rocketMq消息的发送和消息消费 一.消息推送 public void pushMessage() { String message = "推送消息内容!"; try { De ...

  4. RocketMQ(消息重发、重复消费、事务、消息模式)

    分布式开放消息系统(RocketMQ)的原理与实践 RocketMQ基础:https://github.com/apache/rocketmq/tree/rocketmq-all-4.5.1/docs ...

  5. rocketMq 消息偏移量 Offset

    消息偏移量 Offset queue0 offset 0   0-20  offset 4  20-40 纠错:每条消息的tag对应的HashCode. queue1 offset 1  0-20   ...

  6. 基于Jmeter实现Rocketmq消息发送

    在互联网企业技术架构中,MQ占据了越来越重要的地位.系统解耦.异步通信.削峰填谷.数据顺序保证等场景中,到处都能看到MQ的身影. 而测试工程师在工作中,也经常需要和mq打交道,比如构造测试数据,触发某 ...

  7. rocketmq消息及流程

    1.为什么用mq 优势 主要有3个: 应用解耦(降低微服务之间的关联). 异步提速(微服务拿到mq消息后同时工作). 削峰填谷(可以消息堆积) 劣势 系统可用性降低(MQ一旦宕机整个系统不可用) 复杂 ...

  8. 一张图进阶 RocketMQ - 消息发送

    前 言 三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片链接,关于 RocketMQ 你只需要记住这张图!觉得不错的话,记得点赞关注哦. [重要]视频在 B 站同步更新,欢 ...

  9. MQ系列5:RocketMQ消息的发送模式

    MQ系列1:消息中间件执行原理 MQ系列2:消息中间件的技术选型 MQ系列3:RocketMQ 架构分析 MQ系列4:NameServer 原理解析 在之前的篇章中,我们学习了RocketMQ的原理, ...

随机推荐

  1. json文件处理四个函数

    import json # json.dumps(json_dict,ensure_asscii = False)函数的使用,将字典转化为字符串 ensure_ascii=False将Unicode编 ...

  2. opengl学习-利用模板测试勾画物体轮廓中出现的一个问题

    我在学习OpenGL模板测试勾画物体轮廓的时候,出现了这个问题: 这个出现的原因就是,改变摄像机的时候,每次绘制,上次绘制中模板缓冲区的数据没有清除的原因.也就是在while循环开始的时候,glCle ...

  3. java8学习之收集器用法详解与多级分组和分区

    收集器用法详解: 在上次已经系统的阅读了Collector收集器的Javadoc对它已经有一个比较详细的认知了,但是!!!它毕境是只是一个接口,要使用的话还得用它的实现类,所以在Java8中有它进行了 ...

  4. GO (待更新)

    日期20190531,GO AND TOOLS FOR HOME 0  环境搭建 https://golang.org/dl/ Install the Go tools If you are upgr ...

  5. 使用cordova调用相机在相机中添加蒙版

    变态的需求,要在cordova调起得相机上加入一拍照的轮廓,在cordova的插件中拿不到拍照的方法,起初选用UIImagePickerController的cameraOverlayView属行,结 ...

  6. mybatis-plus generator使用

    pom配置 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus- ...

  7. iptables内网访问外网 ε=ε=ε=(~ ̄▽ ̄)~

    介绍 iptables概述: netfilter/iptables : IP信息包过滤系统,它实际上由两个组件netfilter 和 iptables 组成. netfilter/iptables 关 ...

  8. Python 正则表达式Ⅲ

    re.match与re.search的区别 re.match只匹配字符串的开始,如果字符串开始https://www.xuanhe.net/不符合正则表达式,则匹配失败,函数返回None:而re.se ...

  9. yum 安装 mongodb

    1 .添加阿里源 vi /etc/yum.repos.d/mongodb.repo [mongodb-org] name=MongoDB Repository baseurl=http://mirro ...

  10. 在linux 下配置firewalld

    查看firewalld 是否开始与运行 以下两种方式都可以 systemctl status firewalld.service firewall-cmd --state 查看所有打开的端口 以下两种 ...