系统通知
广义系统通知,有1对1的通知,以及一对多的通知,有相对实时的业务通知,以及能够容忍一定延时的系统通知。
系统对1的通知
典型业务,计数类通知:
- 有10个美女添加了你为好友
- 有8个好友私信了你
需要实时
- 登录时拉取,增量推送
- 一旦有消息丢失,网页端的计数会一直不一致
不需要实时
- 只有在链接跳转,或者刷新网页时,才重新拉取最新的通知
系统对多的通知
弹窗新闻
需求
- 同一天,用户登录弹出的新闻是相同的(很多业务符合这样的场景),不同天新闻则不一样(但所有用户都一样)
- 每天第一次登录弹出新闻,当天的后续登录不出新闻
数据结构
- 弹窗新闻表
t_msg(msg_id, date, msg_content) - 用户信息表
t_user(user_id, user_info, …) - 用户收到的新闻弹窗
t_user_msg(user_id, msg_id, date)
推送
- 将t_user_msg里对于所有user_id推送插入一个msg_id,表示未读
- 在user每天第一次登录的时候,将当天的msg_id拉取出来,并删除,表示已读
- 在user每天非第一次登录的时候,就拉取不到msg_id于是不会再次弹窗
拉取
- 在user每天第一次登陆时,将当天的msg_id拉取出来,并插入t_user_msg,表示已读
- 在user每天非第一次登陆时,则会插入t_user_msg失败,则说明已读
优化
- 在t_user表加一列,表示用户最近拉取的弹窗时间
- 在user每天第一次登录时,将当天的msg_id拉取出来,并将last_msg_date修改为今天
- 在user每天非第一次登录时,发现last_msg_date为今天,则说明今天已读
弹窗广告
需求
-每天会对一批在线用户推送相同的弹窗广告
解决方案
- for循环批量推送
- keepalive请求拉取
- 避免雪崩
状态同步
可简化为在线和离线两种状态
获取好友状态
uid-A登录
先去数据库拉取自己的好友列表,再去缓存获取所有好友的状态
登录拉取状态
好友状态改变时如何同步
拉取
向服务器轮询拉取全部好友的状态,例如每1分钟一次
- 时延
- 低效
推送
uid-B状态改变时(由登录、登出等动作触发),服务端不仅要在缓存中修改uid-B的状态,还要将这个状体改变的通知推送给uid-B的在线好友
状态推送
- 优势:实时
- 缺点:当在线好友量很大时,任何一个用户状态的改变,会扩散成N个实时通知,这个N叫做“消息风暴扩散系数”。假设一个IM系统平均每个用户有200个好友,平均有20%的好友在线,那么消息风暴扩散系数N=40,这意味着,任何一个状态的变化会变成40个推送请求。
群友状态改变时如何同步
假设平均每个用户加了20个群,平均每个群有200个用户,依然假设20%的用户在线,那么为了保证群友状态的实时性,每个用户登录,就要将自己的状态改变通知发送给2020020%=800个群友,N=800,意味着,任何一个状态的变化会变成800个推送请求。
- 按需拉取,延时拉取:在真正进入一个群时才实时拉取群友的在线状态
总结
- 好友状态同步,是采用推送的方式同步
- 群友状态同步,由于消息风暴扩散系数过大,一般采用拉取的方式同步
- 群友状态同步,还能采用按需拉取的优化方式,进一步降低服务端压力
- “消息风暴扩散系数”是指一个消息发出时,变成N个消息的扩散系数,这个系数一定程度上决定了技术采用推送还是拉取
网友评论