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. 三,k8s集群的应用入门

    目录 kubernetes集群简单应用 kubectl常用命令: 创建pod service创建 测试其他pod通过series访问nginx 测试手动变更nginx对应的pod的ip pod和ser ...

  2. Reservoir Computing: Harnessing a Universal Dynamical System

    原文连接:https://sinews.siam.org/Details-Page/reservoir-computing-harnessing-a-universal-dynamical-syste ...

  3. windows下双击可运行的Java软件打包方案(转)

    出处: http://www.cnblogs.com/shiyangxt/ 刚开始学Java的时候,挺郁闷的,写出来的java类文件,需要dos下编译,然后再dos下运行看效果.这使初学者常常 觉得麻 ...

  4. spring-data-neo4j 4.2.4release文档概要

    Neo4j是一种开源的NoSQL图数据库,将数据以图(把一个个实体当作节点,连接节点的边表示节点间的关系)的形式保存,Neo4j也支持ACID事务管理.关系型数据库数据访问采用的是ORM(对象关系映射 ...

  5. Python核心技术与实战——十九|一起看看Python全局解释器锁GIL

    我们在前面的几节课里讲了Python的并发编程的特性,也了解了多线程编程.事实上,Python的多线程有一个非常重要的话题——GIL(Global Interpreter Lock).我们今天就来讲一 ...

  6. Python前端HTML

    一.web标准介绍 web标准: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web标准规范的分类:结构标准.表现标准.行为标准. 结构:html.表示: ...

  7. C++:std::map的遍历

    for (auto &kv : myMap) { count<<kv.first<<" has value "<<kv.second&l ...

  8. LA 2797

    题目链接 题意:训练指南283页: #include <iostream> #include <cstdio> #include <cstring> #includ ...

  9. 【Vue】input textarea自动滚动到输入处

    由于我这里要把接口返回的日志不断地新增到textarea里,想实现自动滚动日志的效果. 1.首先定一个textarea类型的input组件 <el-input id="textarea ...

  10. Linux iptables 防火墙设置

    1.查看防火墙iptables -L -niptablesb -L -n --line-number  显示规则行号看到 INPUT ACCEPT, FORWARD ACCEPT , OUTPUT A ...