QQ好友状态,QQ群友状态,究竟是推还是拉?

状态同步,有好友状态的同步,有群友状态的同步,有的需要实时同步,有的能够容忍延时。任何脱离业务的架构设计都是耍流氓,不同场景下,状态同步,究竟是推送还是拉取呢?
用户的在线状态,分为客户端状态(端),服务端状态(云)两种形态。
 
什么是服务端状态?
服务端状态,主要分为在线online和离线offline,不同的状态,对于不同的业务处理流程可能不同。例如对于消息的处理:
(1)服务端状态在线,直接投递给用户;
(2)服务端状态离线,直接存储离线消息,等用户下一次登录拉取;
 
如何实时更新服务端状态?
用户uid-A登录时,会修改用户的服务端状态为在线
QQ好友状态,QQ群友状态,究竟是推还是拉?
用户uid-A登出时,会修改用户的服务端状态为离线

QQ好友状态,QQ群友状态,究竟是推还是拉?
经常的,服务端会将用户的服务端状态存储在高可用的缓存集群里。
 
什么是客户端状态?
不同的产品,会有不同的客户端状态,例如隐身、离线、忙碌、勿扰等,这些状态大多是产品功能需求。
画外音:微信,在设计之初,就摒弃了用户端状态这个概念。
 
后文为了方便描述,不妨设待讨论的是QQ这种拥有客户端状态的产品,并假设客户端状态也只有在线和离线两种状态,后文统一称为“用户状态”。
 
如何获取好友的状态?
uid-A登录时,先去数据库拉取自己的好友列表,再去缓存获取所有好友的状态。
QQ好友状态,QQ群友状态,究竟是推还是拉?
 
用户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的在线好友。

QQ好友状态,QQ群友状态,究竟是推还是拉?
推送的优势是:实时。
 
缺点是:当在线好友量很大时,任何一个用户状态的改变,会扩散成N个实时通知,这个N叫做“消息风暴扩散系数”。假设一个IM系统平均每个用户有200个好友,平均有20%的好友在线,那么消息风暴扩散系数N=40,这意味着,任何一个状态的变化会变成40个推送请求。
 
群友状态的一致性,和好友状态的一致性相比,复杂在哪里?可不可以采用实时推送?
群这个业务场景大伙也非常之熟悉,你能够加入若干群(例如20个),假设平均每个群有200人,即你会有4000个群友。
 
理论上群友状态也可以通过实时推送的方式实现,以保证实时性。进一步讨论之前,先一起估算下这个业务场景下的“消息风暴扩散系数”。
 
假设平均每个用户加了20个群,平均每个群有200个用户,依然假设20%的用户在线,那么为了保证群友状态的实时性,每个用户登录,就要将自己的状态改变通知发送给20*200*20%=800个群友,N=800,意味着,任何一个状态的变化会变成800个推送请求。如果说好友状态实时推送,消息风暴扩散系数N=40尚可以接受,那么群友状态实时推送,N=800则是灾难性的。此类业务往往采用轮询拉取的方式,获得群友的状态。
 
轮询拉取群友状态也会给服务器带来过大的压力,还有什么优化方式?
群友的数据量太大,虽然每个用户平均加入了20个群,但实际上并不会每次登录都进入每一个群。不采用轮询拉取,而采用按需拉取,延时拉取的方式,在真正进入一个群时才实时拉取群友的在线状态,是既能满足用户需求(用户感觉是状态是实时、一致的,但其实是进入群才拉取的),又能降低服务器压力。这是一种常见方法。
 
总结
状态的实时性与一致性是一个较难解决的技术问题,不同的业务实现方式不同,一般来说
(1)好友状态同步,是采用推送的方式同步;
(2)群友状态同步,由于消息风暴扩散系数过大,一般采用拉取的方式同步;
(3)群友状态同步,还能采用按需拉取的优化方式,进一步降低服务端压力;
(4)“消息风暴扩散系数”是指一个消息发出时,变成N个消息的扩散系数,这个系数一定程度上决定了技术采用推送还是拉取;
画外音:群消息的推送,也存在“消息风暴扩散系数”的问题。
知道为什么,一个微信群最多500人了吧

发布者:糖太宗,转载请注明出处:https://www.qztxs.com/archives/science/technology/6787

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年5月15日 下午9:23
下一篇 2022年5月15日 下午9:24

相关推荐

  • 除了解析域名,DNS还能干吗?

    一个http请求,典型的执行流程是怎么样的呢? 可以看到,典型流程为: (1)客户端请求dns-server,发起域名解析; (2)dns-server返回域名对应的外网ip(1.2.3.4); (3)客户端通过外网ip(1.2.3.4),访问反向代理; (4)反向代理通过内网ip(192.168.x.x),将请求分发给web-server; (5)web-...

    2022年5月14日
    1500
  • 惊叹!世界上最漂亮的排序算法!

    直奔主题,世界上“最漂亮”的排序算法,只有6行。 void stooge_sort(int arr[], int i, int j){          if (arr[i]>arr[j]) swap(arr[i], arr[j]);          if (i+1>=j) return;            int k=(j-i+1)/3;...

    2022年5月11日
    2500
  • 修改正在运行的docker容器的端口映射

    0x00 前言 在创建容器时,只有自己本地使用,端口映射127.0.0.1 后面有同事也需要用这个,想要修改正在运行的容器的端口映射   0x01 修改端口映射 1. 确定修改容器的CONTAINER ID 1 2 3 # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NA...

    技术 2022年6月1日
    2400
  • 究竟为啥总在凌晨上线,如何进行无损发布

    为什么很多互联网公司升级系统,选择在晚上上线? 美名其曰,晚上上线,对用户影响最小。   为什么会对用户产生影响? 很多人认为,系统升级往往需要重启,重启的过程中,正在访问的用户会访问失败。   例如,如果升级的是web-server: 如上图,重启ip1上的tomcat时,tomcat上或许有1000个http请求正在处理,这些请求就会失败。   又例如,...

    2022年5月15日
    4000
  • frida hook 简单使用

    拿到一份APP渗透测试报告,里面有一个运行日志残留(中危),该日志中保留大量运行日志,其中包含了一些敏感信息,攻击者可以根据该日志获取应用运行的信息,为进一步攻击做准备 我对APP客户端测试比较初级,残留日志我一般会使用adb logcat打印一下或者在程序目录下翻一翻。并没有发现日志中存在敏感信息,问了下测试的工程师,是通过源代码分析找到相关日志类,hoo...

    技术 2022年6月13日
    3000

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信