[即时通讯] 分布式系统-用户在线状态管理

2020-05-20

分布式系统,用户连接到不同的物理设备,在不同的进程里工作。

独立进程在处理一些用户关系性比较强的业务时(例如用户在线状态),涉及多个进程交互,逻辑要比单服复杂很多。对于较小体量的系统,我们仍然希望寻求一种简单的交互方式。


1. 解耦

分布式系统,每个服务节点可以相互通信,我们希望,节点间尽量解耦,显然 B 图的逻辑更加清晰。

通信解耦


2. 架构

添加 redis 进行数据共享,减少业务节点间的通信。

分布式架构

节点类型 描述
gate 接入服务集群,负责客户端接入和客户端业务协议的路由。
logic 逻辑服务集群,负责客户端业务功能实现。
redis cluster 负责数据(限时)缓存,方便不同类型节点服务共享数据。

gate 写数据,logic 读数据。

用户的实时在线状态被分散保存在多个 gate 服务上。gate 服务将用户在线状态实时同步到 redis 集群。

当 logic 服务处理群聊时,我们需要获得当前群组所有成员的在线状态,这时候无须遍历 gate 服务进行获取,通过 redis 获取即可。


3. Session

逻辑服务节点直接从 redis 上获取数据,可谓简单粗暴,这样 redis 负载可能会成为一个新的问题。特别是活跃的大群,每次发送消息,都要从 redis 取出大量的用户在线状态数据,这不是一个明智做法。

我们可以把进程内存利用起来 —— Session。这样虽然不能保证 Session 里的数据与 redis 同步,也一定程度上减轻了 redis 的负载(可以根据具体的业务,设置 Session 的有效时间。)

为了增强 Session 数据一致性,这样要求上游服务路由过来的同一个用户请求,应该尽可能落在同一个节点进程上处理(这里涉及到一些路由算法,例如:一致性哈希算法)。


那些原来离线,后面上线的用户,没有实时发送的消息,将被保存为离线消息,并通过其它策略定时对离线消息进行 推送

缓存


4. 小结

在现实生活里,无论多牛X的系统,也无法保证服务端与客户端的用户在线状态 强一致

因为网络是有延迟的,例如用户在坐地铁,地铁过隧道,没有任何网络信号了,这种场景,其实用户已经断网了,服务端无法马上感知到用户掉线。所以一般的应用都是 推拉 结合,即便服务推送数据失败,当客户端重新连接上来后能主动拉取到延时的数据。