腾讯云消息队列CMQ版对接使用完全指南:从入门到生产实践
1. 消息队列CMQ版概述
腾讯云消息队列CMQ版(Cloud Message Queue)是基于腾讯自研消息引擎的分布式消息队列系统,为分布式部署的不同应用之间或一个应用的不同组件之间提供基于消息的可靠异步通信机制。消息被持久化存储在高可靠、高可用的CMQ队列中,多进程可以同时读写且互不干扰。CMQ广泛应用于金融交易、订单处理、电商秒杀等对可靠性和可用性有较高要求的业务场景,在腾讯的充值系统中用于对交易模块、发货部分、结算系统进行异步解耦和削峰填谷。
需要特别提醒的是,根据腾讯云官方公告,旧版消息队列CMQ产品正在下线过程中,2026年8月31日将正式下线并停止服务。目前腾讯云主推的是TDMQ CMQ版,本文介绍的内容均基于TDMQ CMQ版。如果用户仍在使用旧版CMQ,建议尽快按照官方迁移指南完成资源迁移。
CMQ的核心价值体现在以下几个方面:消息被持久化保存在队列中,即使接收者因断电、宕机或CPU负载过高等原因暂时不可用,消息也能在接收者恢复后被成功消费;生产一次的数据可以被多个消费场景同时消费,实现数据多次复用;CMQ支持多进程同时读写,收发互不干扰,无需各应用或组件始终处于运行状态。
需要先登录腾讯云控制台,点击:腾讯云控制台,还没有账号,点击:注册后再关联,已有账号点击:登录后再关联
2. 控制台操作指南
2.1 创建队列
在TDMQ CMQ版控制台的队列服务 > 队列页面中,单击页面左上角的新建按钮即可创建一个消息队列。创建队列时需要指定以下核心属性:
- 队列名称:队列的唯一标识,不超过64个字符,必须以字母为首字符,剩余部分可包含字母、数字和横划线。创建成功后无法修改,且不允许创建大小写同名队列。
- 消息生命周期:消息在队列中的最长存活时间,取值范围60秒到15天,默认4天。
- 消息接收长轮询等待时间:消费消息时默认等待接收消息的时间,取值范围200毫秒到30秒。
- 取出消息隐藏时长:消息被消费者获取后的不可见时间,取值范围1秒到12小时,默认30秒。
- 消息最大长度:允许发送到该队列的消息体最大长度,取值范围1KB到64KB,默认64KB。
- 堆积消息数量上限:单个队列最大消息堆积个数,上限为1亿条。
- 消息回溯:开启后可以回溯已消费并删除的消息,可回溯周期需小于等于消息生命周期。
2.2 创建主题与订阅
主题模型采用发布-订阅模式,主题是消息发布的单位,订阅者从主题接收消息。创建主题后,需要为主题添加订阅者,订阅者可以选择一个队列来接收发布的消息。主题的核心属性包括消息最大长度(1KB到1024KB,默认64KB)和消息最长存活时间(固定86400秒)。
3. 队列模型与主题模型
CMQ提供两种消息模型:队列模型和主题模型。
3.1 队列模型
队列模型是最基础的消息模式,生产者将消息发送到队列,消费者从队列中拉取消息进行消费。这里的分布式队列与数据结构中的FIFO队列有所不同,分布式队列不会保证严格的先进先出顺序。队列相当于一个高性能、高容量、高可靠的消息容器,支持多生产者多消费者并发读写。队列模型适用于点对点的消息通信场景,如订单处理、任务分发等。
3.2 主题模型
主题模型类似于设计模式中的发布-订阅模式。生产者将消息发布到主题,CMQ将消息主动推送给主题下的所有订阅者。主题模型支持两种推送格式:JSON格式(HTTP请求Body包含消息正文和属性信息)和SIMPLIFIED精简格式(HTTP请求Body仅为消息正文,msgId等信息在HTTP Header中传递)。主题模型适用于一对多的消息广播场景,如日志分发、事件通知等。
4. SDK接入详解
TDMQ CMQ版目前支持Java、Python、PHP及C++四种语言的SDK。同时提供基于HTTP协议和TCP协议两种接入方式。本文以Python SDK为例进行详细说明。
4.1 准备工作
使用SDK前需要获取以下信息:
- SecretId和SecretKey:云API密钥,登录访问管理控制台,在访问密钥 > API密钥管理页面复制。
- NameServerAddress(API调用地址):在TDMQ CMQ版控制台的队列服务 > API请求地址处复制。
API调用地址分为公网地址和内网地址。强烈建议部署在腾讯云上的服务使用内网域名,因为内网不会产生流量费用。不同地域的API调用地址会有所不同。
4.2 Python SDK安装与配置
首先从GitHub下载CMQ Python SDK:
git clone https://github.com/tencentyun/cmq-python-sdk.gitSDK默认为Python2版本,如需Python3版本可切换至Python3分支。将SDK文件引入项目后,即可开始编写代码。
4.3 Python SDK发送消息
以下是使用Python SDK发送消息的完整代码示例:
import os
import sys
import logging
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)) + "/..")
from cmq.account import Account
from cmq.queue import Message
from cmq.cmq_exception import CMQExceptionBase
# 腾讯云账户密钥
secretId = '您的SecretId'
secretKey = '您的SecretKey'
# CMQ服务调用地址(建议使用内网地址)
nameServerAddress = 'https://cmq-gz.public.tencenttdmq.com'
# 初始化Account对象
# 注意:Account类对象不是线程安全的,多线程使用时需要每个线程单独初始化
my_account = Account(nameServerAddress, secretId, secretKey, debug=True)
my_account.set_log_level(logging.DEBUG)
# 指定队列名称
queue_name = 'my_test_queue'
my_queue = my_account.get_queue(queue_name)
try:
# 构造消息
msg_body = "Hello CMQ! This is a test message."
msg = Message(msg_body)
# 发送消息
re_msg = my_queue.send_message(msg)
print("Send Message Succeed! MessageBody:%s MessageID:%s" % (msg_body, re_msg.msgId))
except CMQExceptionBase as e:
print("Send Message Fail! Exception:%s\n" % e)发送消息时还可以设置延迟参数,使消息在指定时间后才对消费者可见。
4.4 Python SDK消费消息
消费消息的代码实现如下:
from cmq.account import Account
from cmq.cmq_exception import CMQExceptionBase
secretId = '您的SecretId'
secretKey = '您的SecretKey'
nameServerAddress = 'https://cmq-gz.public.tencenttdmq.com'
my_account = Account(nameServerAddress, secretId, secretKey, debug=True)
queue_name = 'my_test_queue'
my_queue = my_account.get_queue(queue_name)
try:
# 消费消息,pollingWaitSeconds为长轮询等待时间
recv_msg = my_queue.receive_message(polling_wait_seconds=10)
print("Receive Message Succeed! MessageBody:%s MessageID:%s ReceiptHandle:%s" %
(recv_msg.msg_body, recv_msg.msg_id, recv_msg.receipt_handle))
# 消费成功后需要删除消息
my_queue.delete_message(recv_msg.receipt_handle)
print("Delete Message Succeed!")
except CMQExceptionBase as e:
print("Receive Message Fail! Exception:%s\n" % e)ReceiveMessage操作会将消息状态变为inactive,inactive时间由队列的visibilityTimeout属性决定。消费者需要在visibilityTimeout时间内消费成功并调用DeleteMessage接口删除消息,否则消息会重新变为active状态,可以被再次消费。这意味着CMQ保证消息至少被消费一次,但业务侧需要自行实现幂等性逻辑来处理可能的重复消费。
4.5 批量操作
CMQ支持批量发送和批量消费,批量发送最多支持16条消息。批量操作可以显著提升吞吐量:
# 批量发送消息
messages = [Message("message1"), Message("message2"), Message("message3")]
re_msg_list = my_queue.batch_send_message(messages)
# 批量消费消息
recv_msg_list = my_queue.batch_receive_message(num_of_msg=10, polling_wait_seconds=10)
# 批量删除消息
handle_list = [msg.receipt_handle for msg in recv_msg_list]
my_queue.batch_delete_message(handle_list)5. TCP SDK接入
除了HTTP方式的SDK,CMQ还提供了基于TCP协议的SDK。TCP协议相比HTTP具有以下优势:
- 更少的计算资源:HTTP每次请求都需要签名鉴权,TCP仅在建立连接时鉴权一次
- 更安全的客户端线程:TCP客户端线程安全,多个线程可共享连接
- 更高效的传输效率:相同客户端下拥有更高的吞吐量和QPS
- 更丰富的特性支持:TCP支持CMQ最新的分布式事务消息特性
TCP SDK目前支持公网访问以及同地域私有网络CVM内网访问方式。使用时需要配置NameServer地址、SecretID和SecretKey。TCP SDK的Demo工程可从GitHub下载。
6. 高级特性
6.1 延迟消息
延迟消息是指消息发送到队列后,在设置的延迟时间后才对消费者可见。发送消息时通过DelaySeconds参数设置延迟时间,取值范围0到3600秒(最长1小时)。需要注意的是,每个队列处于飞行状态(in-flight)的消息数限制为2万条。此外,消息的TTL(消息生命周期)从消息发送时间开始计算,如果延迟时间大于TTL,消息将在延迟期间被删除。
6.2 事务消息
事务消息解决了消息生产者本地事务处理成功与消息发送成功两者的一致性问题,实现了生产者本地事务与消息发送的原子性。事务消息仅通过TCP方式实现。其工作流程为:生产者向MQ服务端发送消息,服务端将消息持久化成功后向生产者返回ACK确认,此时消息为半消息(暂不能投递)。生产者执行本地事务,根据事务执行结果决定提交或回滚半消息。微信红包系统就引入了CMQ事务消息来避免分布式事务带来的系统开销。
6.3 死信队列
死信队列用于处理无法正常消费的消息。在控制台新建队列时可以开启死信队列功能,需要指定:
- 死信队列名称:指定某队列作为当前队列的死信队列,必须是同地域、同账号下的队列
- 死信策略:触发死信的方式,包括消息被多次消费未删除(需设置最大接收次数,范围1-1000)或TTL过期(需设置最大未消费过期时间,范围300-43200秒)
一个队列只能绑定一个死信队列,如果死信队列已被其他队列绑定,则不能直接删除。死信队列通过云API创建时需在请求参数中配置DeadLetterQueueName、Policy和MaxReceiveCount等字段。
7. 监控与告警
CMQ提供了丰富的监控指标和告警功能。配置告警的步骤如下:
- 登录腾讯云可观测平台控制台
- 在左侧导航栏选择告警配置 > 告警策略,单击新建
- 监控类型选择云产品监控,策略类型选择TDMQ告警 > CMQ
- 选择需要配置告警策略的TDMQ CMQ版资源
- 设置告警规则和告警通知模板
常见的监控指标包括队列的消息堆积数、生产消息速率、消费消息速率、消息延迟等。CMQ还可以与云函数SCF集成实现消息的自动触发处理,与云日志服务CLS集成实现日志的实时写入和分析。
8. 计费与成本优化
TDMQ CMQ版采用按量计费模式,主要计费项包括:
- 队列/主题资源占用费:按队列或主题数量计费,计费周期为天。一个自然日内任何时刻创建的资源,即使使用时长不足24小时,也按一天计费。中国大陆地域(广州、上海、南京、北京、成都)为0.5元/个/日。
- API请求费用:根据发送和接收消息的API请求数量计费
成本优化建议:
- 优先使用同地域CVM内网访问,避免公网下行流量费用
- 合理设置消息生命周期,避免过期消息长期占用存储
- 使用批量发送和批量消费接口减少API请求次数
- 对于不需要立即消费的消息使用延迟消息特性,避免队列瞬时堆积
9. 常见问题与解决方案
消息堆积:可能由消费者处理速度慢或服务器性能不足导致,解决方案包括增加消费者数量、提高消费者处理能力或增加服务器资源。
消息重复:CMQ保证消息至少消费一次,业务侧需通过幂等性逻辑保证消息不会重复处理。
拉取延迟增加:切换到新版CMQ后可能出现消息拉取时间变长(10-20秒),常见于消息量不大且消费者不多的场景,原因是新版分布式架构中拉取消息轮询各节点的随机性在消息量少时更为明显。
10. 总结
腾讯云TDMQ CMQ版作为一款成熟的分布式消息队列服务,通过队列模型和主题模型满足了不同场景下的异步通信需求。本文从控制台操作、SDK接入、高级特性到监控运维进行了全面介绍,提供的Python代码示例可直接用于生产实践。需要注意的是,旧版CMQ即将在2026年8月31日下线,用户应及时完成迁移。在实际使用中,建议根据业务特点合理选择消息模型、充分利用内网地址节省成本、配置完善的监控告警体系保障服务稳定性。
常见问题解答
问:CMQ的队列名称有什么命名规则?
答:队列名称不超过64个字符,必须以字母为首字符,剩余部分可包含字母、数字和横划线(-),在单个地域同一账号下唯一,创建成功后无法修改。
问:消费消息后为什么要删除消息?
答:ReceiveMessage操作将消息状态变为inactive,在visibilityTimeout时间内消费者需调用DeleteMessage删除消息。如果超时未删除,消息会重新变为active状态并可被再次消费。
问:延迟消息的延迟时间最大是多少?
答:延迟时间通过DelaySeconds参数设置,取值范围0到3600秒,最长1小时。需注意延迟时间不能超过消息的TTL,否则消息会在延迟期间被删除。
问:CMQ支持哪些编程语言的SDK?
答:TDMQ CMQ版目前支持Java、Python、PHP及C++四种语言的SDK。
问:内网地址和公网地址有什么区别?
答:内网地址仅限腾讯云同一地域内访问,不产生流量费用且延迟更低;公网地址可从任意网络访问,但会产生公网下行流量费用。
问:旧版CMQ什么时候停止服务?
答:腾讯云消息队列CMQ旧版将于2026年8月31日正式下线并停止服务,用户应及时完成资源迁移。





