RocketMQ 消息过滤详解

🚀 RocketMQ 消息过滤详解

Tag 过滤(Broker 端)|SQL92 属性过滤(Broker 端)|Filter Server(已不推荐)

在 RocketMQ 中,消息过滤是消费者只接收感兴趣消息的关键机制。它允许消费者在订阅时指定条件,避免接收大量无关消息,减轻网络和处理压力。

RocketMQ 提供了多种消息过滤方式,主要包括:

  1. Tag 过滤(轻量级,推荐)
  2. SQL92 属性过滤(灵活,推荐)
  3. Filter Server(旧版,已不推荐)

本文将深入解析这三种过滤机制的原理、使用方式、性能影响及最佳实践。


一、1. Tag 过滤(Broker 端)—— 轻量级标签过滤

✅ 定义:

Tag 是消息的子分类标签,消费者可以在订阅时通过 Tag 表达式只接收特定类型的消息。

🔧 使用方式:

// 发送消息时指定 Tag
Message msg = new Message("ORDER_TOPIC", "CREATE", "创建订单".getBytes());
producer.send(msg);

// 消费者只订阅 CREATE 类型的消息
consumer.subscribe("ORDER_TOPIC", "CREATE");

// 或订阅多个 Tag
consumer.subscribe("ORDER_TOPIC", "CREATE || PAY || CANCEL");

// 订阅所有 Tag
consumer.subscribe("ORDER_TOPIC", "*");

📌 支持的语法:

表达式说明
"CREATE"精确匹配
`"CREATE
"*"通配,订阅所有 Tag

⚠️ 注意:Tag 是字符串匹配,不支持正则。

✅ 工作机制:

  • Broker 端过滤:在 ConsumeQueue 构建时,将 tagsCode(Tag 的哈希值)写入
  • 消费者拉取时,Broker 根据 tagsCode 快速过滤,只返回匹配的消息

✅ 优点:

优势说明
高性能基于哈希值过滤,速度快
低开销不需要额外计算
简单易用开发者熟悉,语义清晰

❌ 限制:

问题说明
只能基于 tags 字段无法根据消息体或其他属性过滤
不支持复杂条件age > 18

🎯 适用场景:

  • 按业务类型过滤(如 CREATE, PAY, REFUND
  • 简单的分类订阅

二、2. SQL92 属性过滤(Broker 端)—— 灵活的表达式过滤

✅ 定义:

基于 SQL92 标准子集,消费者可以使用 SQL 表达式对消息的 用户属性(User Properties) 进行过滤。

🔧 使用方式:

(1)发送消息时设置属性
Message msg = new Message("ORDER_TOPIC", "TAGA", "订单数据".getBytes());
msg.putUserProperty("orderType", "VIP");
msg.putUserProperty("amount", "500");
msg.putUserProperty("city", "beijing");
producer.send(msg);
(2)消费者使用 SQL 表达式订阅
// 只消费 VIP 且金额大于 100 的订单
consumer.subscribe("ORDER_TOPIC", 
    MessageSelector.bySql("orderType = 'VIP' AND amount > 100"));

// 支持 OR、IN、BETWEEN、>、<、= 等
consumer.subscribe("ORDER_TOPIC", 
    MessageSelector.bySql("city IN ('beijing', 'shanghai')"));

✅ 工作机制:

  • Broker 端执行 SQL 过滤
  • 消息的 UserProperty 被提取并参与计算
  • 只将满足条件的消息返回给消费者

✅ 优点:

优势说明
灵活强大支持复杂条件组合
基于属性可根据业务字段动态过滤
Broker 端执行减少网络传输和消费者压力

⚠️ 注意事项:

问题说明
性能低于 Tag 过滤需要解析 SQL 和计算表达式
只能使用 putUserProperty 设置的属性不能过滤 Body 内容
需要开启 broker 配置enablePropertyFilter=true

🛠️ Broker 配置(broker.conf):

# 开启 SQL 属性过滤功能
enablePropertyFilter=true

⚠️ 默认关闭,生产环境需手动开启。

🎯 适用场景:

  • 动态路由(如按用户等级、地区、金额)
  • A/B 测试消息分发
  • 灰度发布

三、3. Filter Server(已不推荐)—— 旧版客户端过滤

✅ 历史背景:

在早期版本中,RocketMQ 支持通过 Filter Server 实现复杂的过滤逻辑(如基于消息体的过滤)。

🔧 工作机制:

Producer → 发送消息到 Broker
   ↓
Consumer → 向 Filter Server 注册过滤逻辑(Java Class)
   ↓
Filter Server 从 Broker 拉取消息
   ↓
执行过滤逻辑(如解析 JSON 判断字段)
   ↓
将匹配的消息推送给 Consumer

❌ 为什么被废弃?

问题说明
安全风险需上传 Java 类,存在代码注入风险
运维复杂需独立部署 Filter Server 集群
性能差多跳传输,延迟高
不支持容器化难以在 Kubernetes 等环境部署

🚫 Filter Server 已从 4.0 版本起被标记为“不推荐”,官方建议使用 SQL92 替代。

✅ 现代替代方案:

  • SQL92 属性过滤:推荐用于大多数场景
  • 消费者端过滤:在 MessageListener 中手动判断(适合简单逻辑)
  • 外部流处理引擎:如 Flink + RocketMQ,实现复杂规则引擎

四、三种过滤方式对比总结

特性Tag 过滤SQL92 属性过滤Filter Server
过滤位置Broker 端Broker 端Filter Server
性能⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
灵活性低(仅 Tag)高(SQL 表达式)极高(任意逻辑)
安全性低(代码注入)
是否推荐✅ 强烈推荐✅ 推荐❌ 已废弃
配置要求enablePropertyFilter=true需部署 Filter Server
适用场景简单分类动态条件已淘汰

五、最佳实践建议

实践说明
✅ 优先使用 Tag 过滤简单、高效、安全
✅ 复杂条件使用 SQL92 属性过滤开启 enablePropertyFilter
✅ 发送消息时合理设置 putUserProperty为过滤提供数据支持
❌ 避免使用 Filter Server已过时,有安全风险
✅ 消费者端可做二次过滤如幂等判断、业务校验
✅ 避免在 SQL 中使用复杂函数影响 Broker 性能
✅ 监控过滤后的消费量确保逻辑正确

六、常见问题排查

问题可能原因解决方案
SQL 过滤无效enablePropertyFilter=falsebroker.conf 中开启
Tag 过滤不生效表达式错误(如空格)使用 `
消费者收不到消息过滤条件太严格检查 SQL 或 Tag 配置
Broker CPU 高大量 SQL 过滤优化条件或改用 Tag
消息体无法过滤SQL92 不支持 Body将关键字段放入 UserProperty

✅ 总结

过滤方式核心思想一句话总结
Tag 过滤轻量标签,快速匹配“按标签分类,简单高效”
SQL92 属性过滤灵活表达式,动态路由“像查数据库一样过滤消息”
Filter Server旧版复杂过滤“已被淘汰,切勿使用”

🚀 最终建议:

  • 80% 场景用 Tag 过滤
  • 20% 复杂场景用 SQL92 属性过滤
  • 永远不要用 Filter Server

掌握这两种现代过滤机制,你就能在性能、灵活性、安全性之间取得最佳平衡,构建高效的消息订阅系统。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值