编辑: 霜天盈月祭 | 2013-06-21 |
但是对于 Consumer不在线的情 况,却有很多值得讨论的场景. 首先,在Consumer 偶然宕机或下线时,Producer 的生产是可以不受影响的,Consumer 上线后,可以继续之前 的消费,此时消息数据不会丢失;
但是如果 Consumer 长期宕机或是由于机器故障无法再次启动,就会出现问题, 即服务端是否需要为 Consumer 保留数据,以及保留多久的数据等等. 采用 Push 方式时,因为无法预知 Consumer 的宕机或下线是短暂的还是持久的,如果一直为该 Consumer 保留自 宕机开始的所有历史消息,那么即便其他所有的 Consumer 都已经消费完成,数据也无法清理掉,随着时间的积 累,队列的长度会越来越大,此时无论消息是暂存于内存还是持久化到磁盘上(采用 Push 模型的系统,一般都是将 消息队列维护于内存中,以保证推送的性能和实时性,这一点会在后边详细讨论),都将对 CMQ 服务端造成巨大 消息队列 CMQ 版权所有:腾讯云计算(北京)有限责任公司 第6 共9页 压力,甚至可能影响到其他 Consumer 的正常消费,尤其当消息的生产速率非常快时更是如此;
但是如果不保留数 据,那么等该 Consumer 再次起来时,则要面对丢失数据的问题. 折中的方案是:CMQ 给数据设定一个超时时间,当Consumer 宕机时间超过这个阈值时,则清理数据;
但这个时 间阈值也并太容易确定. 在采用 Pull 模型时,情况会有所改善;
服务端不再关心 Consumer 的状态,而是采取"你来了我才服务"的方式, Consumer 是否能够及时消费数据,服务端不会做任何保证(也有超时清理时间). 消息队列 CMQ 版权所有:腾讯云计算(北京)有限责任公司 第7 共9页 对于重复消息,最好的方法是消息可重入(消息重复消费对业务无影响).做不到可重入时,需要在消费端去重.
一、重复消息出现的原因 网络异常、服务器宕机等原因都有可能导致消息丢失.CMQ 为了做到不丢消息、可靠交付,采用了消息生产、消费 确认机制. 生产消息确认:生产者向 CMQ 发送消息后,等待 CMQ 回复确认;
CMQ 将消息持久化到磁盘后,向生产者返回确 认成功.否则在生产者请求超时、CMQ 返回失败等情况下,生产者需要向 CMQ 重发消息. 消费者确认:CMQ 向消费者交付消息后,将消息置为不可见;
在消息不可见时间内,消费者使用句柄删除消息.如 果消息未被删除,且不可见时间超时,消息将重新可见. 由于消息确认机制是"至少一次交付(at least once)",在网络抖动、生产者/消费者异常等情况下,就会出现生产 者重复生产、消费者重复消费的情况. 消息去重 最近更新时间:2018-11-26 17:37:04 消息队列 CMQ 版权所有:腾讯云计算(北京)有限责任公司 第8 共9页
二、去重方案 要去重,先要识别重复消息.通常的做法是在生产消息时,业务方在消息体中插入去重key,消费时通过该 去重key 来识别重复消息.去重key 可以是由 组成的唯一值. 只有一个消费者时,您可以将消费过的 去重key 缓存(如KV 等),然后每次消费时检查 去重key 是否已消费过. 去重key 缓存可以根据消息最大有效时间来淘汰.CMQ 提供了队列当前最小未消费消息的时间 (min_msg_time),您可以使用该时间和业务生产消息最大重试时间来确定缓存淘汰时间. 存在多个消费者时,去重key 缓存就需要是分布式的. ? 根据消息最大有效时间,计算 key 过期时间: current_time - max_retention_time - max_retry_time - max_network_time ? 根据 CMQ 最小未消费时间,计算 key 过期时间: min_msg_time - max_retry_time - max_network_time 说明: CMQ 可配置消息最大有效时间为15天,业务可根据实际情况调整. CMQ队列当前最小未消费消息时间,即上图中最远时间点.该时间之前的消息都已经被删除,之后的消息可能未被 删除. 消息队列 CMQ 版权所有:腾讯云计算(北京)有限责任公司 第9 共9页