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. linux下测试web访问及网络相关的命令

    curl命令 curl是linux系统命令行下用来简单测试web访问的工具. curl -xip:port www.baidu.com    -x可以指定ip和端口,省略写hosts,方便实用 -I  ...

  2. matplotlib:python数据处理三剑客之一

    1.基本使用 import numpy as np import matplotlib.pyplot as plt import pandas as pd # 生成一系列x x = np.linspa ...

  3. Ansible安装部署和常用命令,及其主机清单inventory(二)

    1.ansible的安装方式 1.1使用yum源安装 yum install ansible -y 1.2使用rpm包安装 https://dl.fedoraproject.org/pub/epel/ ...

  4. Java入门指南-04 顺序、分支、循环

    顺序结构 从上至下,依次执行 if 语句在 Java 里,用 if 语句来实现“当满足 XXX 条件时,执行 YYY”这样的逻辑判断.例如,在使用共享单车时需要检查人的年纪.如果在 12 岁以下,则禁 ...

  5. Linux编译阻塞型驱动遇到'TASK_NORMAL' undeclared (first use in this function)问题解决办法

    http://blog.csdn.net/qq_16405157/article/details/49281793

  6. 关于ORACLE的串行化隔离级别--来自ORACLE概念手册

    为了描述同时执行的多个事务如何实现数据一致性,数据库研究人员定义了被 称为串行化处理(serializability)的事务隔离模型(transaction  isolation model).当所有 ...

  7. :last-child的坑-CSS3选择器

    CSS3选择器之:last-child - Eric 真实经历 最近开发项目的时候发现了一个这么多年忽略的问题,和大家分享一下.项目使用的是Antd组件库,有一个搜索框是这样的: 为了保证下拉框的内容 ...

  8. hiho #1308 : 搜索二·骑士问题

    #1308 : 搜索二·骑士问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:小Ho你会下国际象棋么? 小Ho:应该算会吧,我知道每个棋子的移动方式,马走日象 ...

  9. 【winform-窗体快捷键】定义功能窗体快捷键,非全局

    这里的快捷键并非系统全局快捷键.仅是普通的当窗体在焦点内发生.有很多种方法,这里列举几种项目中使用到的方法. Alt+*(一般控件快捷键) 这个比较简单,只需为该控件的Text属性声明时加上”(&am ...

  10. 【leetcode】LCP 2. 分式化简

    题目如下: 有一个同学在学习分式.他需要将一个连分数化成最简分数,你能帮助他吗? 连分数是形如上图的分式.在本题中,所有系数都是大于等于0的整数. 输入的cont代表连分数的系数(cont[0]代表上 ...