QQ状态同步究竟是推还是拉?

开发 开发工具
前面两篇讲即时通讯核心技术的文章:《微信为什么不丢消息?》、《http如何像tcp一样实时的收消息?》。反馈还可以,故继续即时通讯这一个系列吧,今天聊聊即时通讯中的“状态”。

前面两篇讲即时通讯核心技术的文章

《微信为什么不丢消息?》

《http如何像tcp一样实时的收消息?》

反馈还可以,故继续即时通讯这一个系列吧,今天聊聊即时通讯中的“状态”。

需求缘起

“在线状态一致性”(好友在线状态,群友在线状态)是即时通讯领域较难解决的一个技术问题,如何精准实时的获得好友、群友的在线状态,是今天将要探讨的话题。

好友状态一致性

问题一:用户uid-A登录时,如何获取自己全部好友的在线状态?

回答:

(1)服务器要存储所有用户的在线状态(往往存储在保证高可用的缓存集群里) -> 保证状态可查

(2)用户状态实时变更,任何用户登录时,需要将服务端自己的在线状态置为online;任何用户登出时,需要将服务端自己的状态置为offline -> 保证服务端状态存储的一致性与实时性

(3)uid-A登录时,先去数据库拉取自己的好友列表,再去缓存获取所有好友的在线状态 -> 保证登录时好友状态获取的一致性与实时性

问题二:用户uid-A的好友uid-B状态改变时(由登录、登出、隐身等动作触发),uid-A如何知道这一事件?

方案一:uid-A向服务器轮询拉取uid-B(其实是自己的全部好友)的状态,例如每1分钟一次

缺点:

(1)如果uid-B的状态改变,uid-A获取不实时,可能有1分钟时延

(2)如果uid-B的状态不改变,uid-A会有大量无效的轮询请求,占用服务器资源

方案二:uid-B状态改变时(由登录、登出、隐身等动作触发),服务器不仅在缓存中修改uid-B的状态,还要将这个状体改变的通知推送给uid-B的在线反向好友(反向好友是指:加了uid-B为好友的人,而不是uid-B的好友,这个细节要注意)

优点:

(1)实时

缺点:

(2)当在线好友量很大时,任何一个用户状态的改变,会扩散成N个实时通知,这个N叫做“消息风暴扩散系数”。

假设一个im系统平均每个用户有200个反向好友,平均有20%的反向好友在线,那么消息风暴扩散系数N=40,这意味着,任何一个状态的变化会变成40个推送请求。

群友状态一致性

问题三:群友状态一致性有什么不同,和好友状态一致性相比复杂在哪里?为什么不能采用实时推送?

回答:理论上群友状态也可以通过实时推送的方式实现,以保证实时性。但实际上,群友状态一般都是采用拉取的方式获得,因为群友状态“消息风暴扩散系数”N实在太大,全部实时获取系统往往承受不了

假设平均每个用户加了20个群,平均每个群有200个用户,依然假设20%的用户在线,那么为了保证群友状态的实时性,每个用户登录,就要将自己的状态改变通知发送给20*200*20%=800个群友,N=800,意味着,任何一个状态的变化会变成800个推送请求。

XXX系统使用的是群友状态推送,不存在的这样的问题?那很可能是,XXX系统的用户量和活跃度还不够高吧。

问题四:轮询拉取群友状态也会给服务器带来过大的压力,还有什么优化方式?

回答:群友的数据量太大,虽然每个用户平均加入了20个群,但实际上并不会每次登录都进入每一个群。不采用轮询拉取,而采用按需拉取,延时拉取的方式,在真正进入一个群时才实时拉取群友的在线状态,是既能满足用户需求(用户感觉是状态是实时、一致的,但其实是进入群才拉取的),又能降低服务器压力。这是一种常见方法。

关于更多按需拉取,延时拉取的讨论,可移步《微信为啥这么省流量》。

延伸讨论:系统消息/开屏广告的推送与拉取

问题五:系统消息/开屏广告一般采用推送还是拉取?

回答:不考虑APP端的push(APP端的push,不需要启动APP,不依赖client与server之间的TCP长连接),个人强烈建议系统消息/开屏广告这类消息采用“拉取”的方式,原因是:

  1. 这类业务对消息的实时性往往要求不高
  2. 如果集中推送,“消息风暴扩散系数”过大,容易引发系统抖动;而拉取的方式,可以摊平这个抖动,用户登录时均匀的发起请求
  3. 如果集中推送,往往不在意用户是否“在线”,往往会造成大量离线垃圾消息;而拉取的方式,保证只有在线的用户才会收到请求

有不同的建议,欢迎评论讨论。

总结与建议

状态的实时性与一致性是一个较难解决的技术问题,不同的业务接受度,不同的数据量并发量在线量,实现方式不同,个人建议的方式是:

  1. 好友状态,如果对实时性要求较高,可以采用推送的方式同步;如果实时性要求不高,可以采用轮询拉取的方式同步
  2. 群友的状态,由于消息风暴扩散系数过大,可以采用按需拉取延时拉取的方式同步
  3. 系统消息/开屏广告等对实时性要求不高的业务,可以采用拉取的方式获取消息
  4. “消息风暴扩散系数”是指一个消息发出时,变成N个消息的扩散系数,这个系数与业务及数据相关,一定程度上它的大小决定了技术采用推送还是拉取

文章转载自微信公众号“架构师之路“

 

责任编辑:未丽燕 来源: 架构师之路
相关推荐

2020-12-22 21:24:45

在线状态服务端状态状态同步

2021-01-05 09:23:49

网页端消息

2021-01-08 08:22:17

消息数据结构开发

2011-02-28 09:51:43

内省

2018-07-05 16:15:26

缓存数据cache miss

2012-08-20 10:34:07

软件开发开发软件

2010-06-28 14:47:45

云计算

2016-11-10 21:00:49

消息存储数据

2019-04-26 13:55:02

Istio微服务架构

2009-05-06 16:10:17

Java传值引用

2019-10-21 13:58:22

爬虫互联网程序员

2011-02-16 16:13:40

Debian

2020-05-06 18:32:37

人工智能AI制药

2019-02-14 10:10:11

系统厂商芯片

2020-05-07 10:53:04

人工智能技术开发

2017-08-16 09:13:27

2018-05-30 15:29:56

2020-06-11 09:18:34

动静分离架构架构设计开发

2021-09-02 08:24:27

pod EvictedKubernetes

2010-08-24 09:19:59

点赞
收藏

51CTO技术栈公众号