知识卡片

三种推送模型的权衡

普通读书笔记卡

内容

常见的消息推送模型有三种,各自的适用场景取决于系统对时序性和消息重复消耗的要求。长轮询拉取:早期常见做法是Nginx+Lua+Redis配合长轮询,主要问题是开销比较大、时效性也不好,能做的优化策略不多,目前已经不常用。直接推送:这是[[360消息系统的六大组件架构]]目前采用的模型,消息类型是”消耗型”的,且对同一个用户不允许重复消耗(如果需要多终端各自重复消耗,得把它们抽象成不同用户),好处是实时性好、开销小,消息直接下发给客户端、不需要客户端从接入层到存储层主动拉取;但纯推送模型有个根本性局限——因为系统是异步的,无法精确保证消息之间的时序性,这对纯粹的push通知需求够用,但如果想复用推送系统来做IM这类强调消息顺序的通信场景,就不合适了。推拉结合:对于严格要求时序性、且消息可以重复消耗的系统,通常走这条路——推送系统只负责发通知(附带消息ID等信息),客户端根据推送来的key主动从业务服务器拉取真正的消息内容,如果发现主从同步存在延迟,还可以配合推送的key做延迟拉取策略;同时可以利用消息本身的QoS级别做混合策略,比如”对方正在输入”这类低优先级消息就不需要走主动拉取,直接靠推送本身消耗掉即可。这三种模型的选择本质上是在”实时性/开销”和”时序保证/重复消耗支持”这两组诉求之间做取舍:越靠向纯推送,实时性和开销越占优、但时序性和重复消耗支持越差;越靠向推拉结合,越能满足强时序和重复消耗的需求、但要为额外的拉取环节和主从延迟处理付出更高的架构复杂度。

参考来源

- 位置:《高可用架构(第1卷)》第1章《高可用架构案例精选》"1.4 如何实现支持数亿用户的长连消息系统:Golang高并发案例"节,"1.4.2 消息系统架构介绍"(源文件:_epub-src/OEBPS/Text/Chapter1_4_3.xhtml) - 结论依据:原文说明"直接推送的系统……消息类型是消耗型的,并且对于同一个用户并不允许重复消耗……但纯粹是推送模型有个很大问题,由于系统是异步的,无法精确保证时序性……对于严格要求时序性、消息可以重复消耗的系统,目前也都是走推拉结合的模型",直接支撑本卡片结论。 - 原始内容:推的好处是实时性好、开销小,直接将消息下发给客户端……但纯粹是推送模型有个很大问题,由于系统是异步的,无法精确保证时序性……对于严格要求时序性、消息可以重复消耗的系统,目前也都是走推拉结合的模型。