系统通知,居然用拉取?

广义系统通知,有1对1的通知,以及一对多的通知,有相对实时的业务通知,也有能够容忍一定延时的系统通知。任何脱离业务场景的架构设计都是耍流氓,结合具体的场景来看下,这样的一些系统通知,究竟是推还是拉?

 
第一大类:系统对1的通知
典型业务,计数类通知:
(1)有10个美女添加了你为好友;
(2)有8个好友私信了你;
很多业务经常有这类计数通知,通知结果只针对你,这类通知是推送,还是拉取的呢?常见的有这样一些实践:
 
如果业务需求对计数需求需要实时展现,例如微博的加好友计数,假如希望实现不刷新网页,计数就实时变化
(1)登录微博时,会有一个计数的拉取,对网页端的计数进行初始化:
int getCountByType(int countType)
 
(2)在浏览微博的过程中,一旦有人加你为好友,服务端对网页端进行实时推送,告之增加了1个(或者N个)好友:
int addCountByType(int countType, int diff)
这里的思路是,一开始得到初始值,后续推送增量值,由网页端计算最终计数并呈现最终结果。需要注意,针对不同业务,计数变化的差值可增可减。
 
上述方案的坏处是,一旦有消息丢失,网页端的计数会一直不一致,直至再次登录重新初始化计数。这个计算计数可以优化为在服务器直接计算并通知网页端最终的结果,网页端只负责呈现即可,这样网页端的逻辑会变轻。
 
如果业务对此类通知的展现不需要这么实时,完全可以通过拉取:
(1)只有在链接跳转,或者刷新网页时,才重新拉取最新的通知,例如上述计数
int getCountByType(int countType)
这样系统的实现会最简单,需要注意,通知拉取要异步,不要影响主页面的快速返回。
 
系统对1的推送,例如针对1个用户的业务计数推送,计数的变化频率其实非常低,使用cache来存储这些计数能够极大提升系统性能。
 
第二大类:系统对多的通知
系统对多的通知消息,会比系统对1的通知消息复杂一些,以两个场景为例:
(1)QQ登录弹窗新闻;
(2)QQ右下角弹窗广告;
 
先说IM登录弹窗新闻。
这个通知的需求是:
(1)同一天,用户登录弹出的新闻是相同的(很多业务符合这样的场景),不同天新闻则不一样(但所有用户都一样);
(2)每天第一次登录弹出新闻,当天的后续登录不出新闻;
 
不妨设有一个表存放弹窗新闻
t_msg(msg_id, date, msg_content)
有一个表来存放用户信息
t_user(user_id, user_info, …)
有一个表来存放用户收到的新闻弹窗
t_user_msg(user_id, msg_id, date)
 
这里的实现明显不能采用推送的方式:
(1)将t_user_msg里对于所有user_id推送插入一个msg_id,表示未读;
(2)在user每天第一次登录的时候,将当天的msg_id拉取出来,并删除,表示已读;
(3)在user每天非第一次登录的时候,就拉取不到msg_id于是不会再次弹窗;
这个笨拙的方式,会导致t_user_msg里有大量的脏数据,毕竟大部分用户并不会登录。
 
如果改为拉取的方式会好很多:
(1)在user每天第一次登陆时,将当天的msg_id拉取出来,并插入t_user_msg,表示已读;
(2)在user每天非第一次登陆时,则会插入t_user_msg失败,则说明已读,不再进行二次弹窗展现;
这个方式虽然有所优化,但t_user_msg的数据量依然很大
 
还有一种巧妙的方式,去除t_user_msg表,改为在t_user表加一列,表示用户最近拉取的弹窗时间
t_user(user_id, user_info, last_msg_date, …)
这样业务流程会升级为:
(1)在user每天第一次登录时,将当天的msg_id拉取出来,并将last_msg_date修改为今天;
(2)在user每天非第一次登录时,发现last_msg_date为今天,则说明今天已读;
这种方式不再存储消息与用户的笛卡尔关系,数据量会大大减少,是不是有点意思?
 
再说IM右下角弹窗广告。
这个通知的需求是:
(1)每天会对一批在线用户推送相同的弹窗TIPS广告,例如球鞋广告,手机广告等;
画外音:如果1个推送一块钱,5KW用户推送收入就有5KW收入哟,一天推个几次,实现1个亿的小目标居然如此简单。
 
最直观的感受,这是一个for循环批量推送的过程。如果是推送,必须要考虑的问题是,推送限速控制,避免短时间内对系统造成冲击,引发雪崩。
 
能不能用拉取呢?
完全可以,这是一个对实时性要求不太高的场景,用户早1分钟晚1分钟收到这个广告影响不大,其实可以借助IM原本已有的keepalive请求,在请求返回时,告之“有消息拉取”,然后采用拉取的方式拉取广告消息。

这个方案的好处是,由于5KW在线用户的keepalive请求是均匀的,所以可以很均匀的将广告拉取的请求同样均匀的分散到一段时间内,避免5KW集中推送对系统造成冲击。
 
总结
广义系统通知,究竟是推送还是拉取呢?不同业务,不同需求,实现方式不同。
系统对1的通知:
(1)实时性要求高,可以推送;
(2)实时性要求低,可以拉取;
 
系统对N的通知:
(1)登录弹窗新闻,拉取更佳,可以用一个last_msg_date来避免大量数据的存储;
(2)批量弹窗广告,常见的方法是推送,需要注意限速,也可以拉取,以实现请求的均匀分散;
学习,永无止境,希望大家有收获。

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

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

相关推荐

  • Docker 搭建Redis集群环境

    [toc] 一:启动6个Redis容器实例 --privileged=true 获取宿主机root 用户权限 --net host:使用宿主机ip和端口,默认 --cluster-enabled yes:开启redis 集群 --appendonly yes:开启持久化 docker run -d --name redis-node-1 --net host...

    技术 2022年5月9日
    1900
  • WINSpect-基于Powershell的Windows安全审计工具

    0x00 描述 WINSpect是一款基于Powershell的Windows安全审计工具,可用于枚举和识别Windows平台的安全漏洞,以进一步的优化和加固平台的安全防护策略。 0x01 功能 WINSpect将为我们提供审计检查和枚举: 检查已安装的安全产品 检查DLL劫持 检查用户账户控制设置 本地文件系统共享 具有本地组成员身份的域用户和组 注册表a...

    技术 2022年6月2日
    5500
  • QT 连接MySQL数据库打不开

    前提为MySQL重新编译了动态库。动态库是没有问题的 但是当我用QT代码打开MySQL的时候总是大不开。 问题原因是因为我定义QSqlDatabase的时候定义错误 定义成了 QSqlDatabase *db; 正确的定义方式应该是 QSqlDatabase db;

    技术 2022年5月22日
    3700
  • 求解“微信群覆盖”的三种方法:暴力,染色,链表,并查集(文章没火,你有责任)

    这是一篇聊算法的文章,从一个小面试题开始,扩展到一系列基础算法,包含几个部分: (1) 题目简介; (2) 思路一:暴力法; (3) 思路二:染色法; (4) 思路三:链表法; (5) 思路四:并查集法; 除了聊方案,重点分享思考过程。文章较长,可提前收藏。   第一部分:题目简介   问题提出:求微信群覆盖 微信有很多群,现进行如下抽象: (1) 每个微信...

    2022年5月10日
    3200
  • App反编译工具dex2jar、JD-GUI的使用

    如今爬虫的开发离不开从App爬取数据,本文将介绍如何使用dex2jar反编译一个Android App以及使用JD-GUI工具查看App源码。 准备工作 dex2jar下载及安装 可以从https://sourceforge.net/projects/dex2jar/files/下载dex2jar,然后解压既可。 JD-GUI下载及安装 可以从http://...

    2022年5月7日
    36700

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信