Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >如何设计一个消息中心

如何设计一个消息中心

作者头像
出其东门
发布于 2022-12-05 03:00:52
发布于 2022-12-05 03:00:52
2.4K1
举报
文章被收录于专栏:01二进制01二进制

如今的内容型产品,不管提供的是什么类型的内容,在其主功能之外,不可避免的会有另一个十分重要的功能——消息中心。

而无论是信息流、论坛、信箱,还是私聊、群聊、通知,推拉模型是内容型(包括:社交型)产品架构的核心。做出正确选择的关键在于对产品形态和系统组件清晰的认识。

今天我们将重心放在消息中心上,聊一聊如何设计一个消息中心。

需求分析

消息中心通常会有两个功能(如下图所示):

  1. 用户通知(点赞、评论、关注、@等)
  2. 官方通知

接下来我们将会对这两类通知进行一个简单的抽象。

首先,可以确定的是,对于用户通知,每个用户都不一样(我的点赞列表和你的点赞列表肯定是不一样的),因此对于每个人我们都需要维护一个「收件箱」。

当 A 点赞了 B 的内容,后端系统在收到了这一个点赞消息后,会将点赞信息写入 B 的 「收件箱」,并标明这是 A 在 xxx 时点赞的 xxx 内容。这是一个系统将消息 推送 给 B 的过程。

而对于官方通知,每个人(几乎)都是一样的(用户有可能设置了屏蔽,系统也可能指定了发送人群),并且官方通知是由系统自然下发的,因此对于系统来说需要维护一个系统「发件箱」

发件箱维护了官方想给用户的通知,每次打开消息中心时,用户都会主动来系统「拉取」官方最新的消息,并和用户自己的「收件箱」里的官方通知进行比较,以确认是否已读该条通知。这是一个用户主动从系统「拉取」通知的过程。

推拉模型

其实到这里就已经点出了这两个场景背后的一套模型——推拉模型。而之所以在这两种场景选择不同的运行机制,其实背后牵扯到的是读写扩散的问题。

推模型

先看推模型,对于任何一个内容创作者来说,最开心的事情莫过于打开软件会有一堆点赞/评论的小红点。对于大 V 来说,打开 App 查看点赞消息的频率根本比不过别人给你点赞的频率,这是一个很典型的读少写多的场景。每当有一个用户点赞该大 V 时,都会将索引信息(一般为内容 ID、类型、发表时间等索引数据)写到用户的收件箱中。

  • 优点:读很轻。仅需要读取消息列表即可。
  • 缺点:写很重。一旦用户的内容质量很高,可能会收到大量的点赞/评论,会有大量的写入操作。

拉模型

再看拉模型,以官方通知为例,一般官方通知是由运营人员发布的,一个月可能也不会有几条,但是每次用户进入 App 时都会看看是否有新的官方通知进来,这是一个很典型的读多写少的场景。

  • 优点:写很轻,节省空间。系统只需维护一个属于自己的消息列表即可。
  • 缺点:读很重,计算量大。假设可以发送官方通知的生产者较多(例如淘宝里的一系列官方业务),则每次都需要从这些消息生产者里拉取最新的内容。

流程设计

用户通知

对于用户通知,流程设计如下:

对于该流程,有几点需要注意的:

异步发送

当用户出发了点赞/关注/评论行为时,被点赞/评论/关注的用户,其实不需要立即感知,因此也不需要立即将互动信息写入该用户的收件箱中,因此可以考虑以消息队列的方式通知出去,缓解系统压力。

缓存前置

写入消息时,如果直接写入用户收件箱,可能会导致用户在请求消息列表时,将请求全部打到 DB,造成系统故障,因此通常会在更新用户收件箱时双写用户缓存。

官方通知

相较于用户通知,官方通知由于引入官方运营这一角色,操作上会稍微复杂一些(如上图所示),因此整个系统的设计也会稍微复杂一些。

官方运营发送通知到「发件箱」中,「发件箱」中保留所有在线的通知列表。用户查看通知列表时,从官方「发件箱」中获取到未读通知,从自己的「收件箱」中查询历史通知。即:

  1. 运营写发件箱
  2. 用户读发件箱
  3. 用户写收件箱

流程示意图如下

官方运营在运营后台进行通知的编辑和发布,发布的通知更新到数据库中进行持久化存储。(这里选择 mysql 数据库进行数据持久化,下一章节将会提到)

通知发生变更时,会发送通知变更消息。基于该消息更新单条通知的缓存,并更新官方发件箱列表(供前台查询)。

用户查看通知列表时,若为第一页,需要从官方发件箱队列查看是否有未读的通知。

若有未读通知,则和历史通知第一页合并,返回给用户。同时异步写入用户的收件箱中。

持久化方案

说完了核心的业务流程后,接下来要面临的问题就是,数据存在哪?

上文有提到会将官方通知的发件箱利用 mysql 持久化,因为官方通知的数量较少,且官方通知是一个拉模型,重读轻写,压力多半由缓存来扛,所以底层数据存储在 mysql 中并无大碍。

重难点主要在用户的「收件箱」

之前有提过,用户收件箱的逻辑是一个重写轻读的推模型,一旦大 V 的内容更新,他的收件箱可能在一瞬间涌入大量的写流量。另外,对于几个头部大 V 来说,收到几千万的点赞并不是什么难事,每一个点赞信息都要写入到该用户的收件箱中,这就要求了底层存储需要能支持海量数据。

基于以上情景,MySQL 可能并不是一个合适的持久化方案。此时,我们可以尝试使用 HBase

MySQL 与 HBase

MySQL 和 HBase 是我们日常应用中常用的两个数据库,分别解决应用的在线事务问题和大数据场景的海量存储问题。

综合对比

MySQL:是常用的数据库,采用行存储模式,底层是 binlog,用来存储业务数据,数据存储量较小。

HBase:列式数据库,底层是 hdfs,可以存储海量的数据,主要用来存储海量的业务数据和日志数据

从引擎结构看差异

HBase 和 MySQL 的核心差异在于底层的数据结构,HBase 使用 LSM(Log-Structure Merge)树,Innodb 使用 B+树。

LSM 树,即日志结构合并树(Log-Structured Merge-Tree)。其实它并不属于一个具体的数据结构,它更多是一种数据结构的设计思想。

它的核心思路其实非常简单,就是假定内存足够大,因此不需要每次有数据更新就必须将数据写入到磁盘中,而可以先将最新的数据驻留在内存中,等到积累到最后多之后,再使用归并排序的方式将内存内的数据合并追加到磁盘队尾 (因为所有待排序的树都是有序的,可以通过合并排序的方式快速合并到一起)。

LSM 具有批量特性,存储延迟。当写读比例很大的时候(写比读多),LSM 树相比于 B 树有更好的性能。因为随着 insert 操作,为了维护 B 树结构,节点分裂。读磁盘的随机读写概率会变大,性能会逐渐减弱。多次单页随机写,变成一次多页随机写,复用了磁盘寻道时间,极大提升效率。

因此,由引擎结构(B+Tree vs LSM Tree)看到的能力差异:

  1. MySQL:读写均衡、存在空间碎片
  2. HBase:侧重于写、存储紧凑无浪费、Io 放大、数据导入能力强
从架构对比看差异

相比 MySQL,HBase 的架构特点:

  1. 完全分布式(数据分片、故障自恢复)
  2. 底层使用 HDFS(存储计算分离)。

由架构看到的能力差异:

  1. MySQL:运维简单(组件少)、延时低(访问路径短)
  2. HBase:扩展性好、内置容错恢复与数据冗余

总结

本文我们讲述了如何从官方通知和用户通知两个方面切入,设计一个 App 的常见功能——消息中心。但该方案仍然有很多潜在的问题:如果官方通知的来源很多呢?如何解决写扩散带来的成本问题?这些都是值得探索的问题。

事实上,消息中心虽然是一个十分常见的功能,但背后涉及到的东西非常复杂,发布/订阅、推拉模型、读写扩散等问题都会影响到我们的架构设计。

架构设计的过程,就是取舍的过程,而如何取舍,则是一门学问。对于现在纷繁复杂的互联网业务,永远没有最好的架构,只有最适合的架构。

最后,我们抛个问题,朋友圈是推模型还是拉模型?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 01二进制 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
对于官方通知,可能每次的收件人不一样,不单单是官方运营能指定的,可能需要一堆条件结合过滤出来的,这一块如何设计呢?能避免程序员的介入,使官方运营能自主完成
对于官方通知,可能每次的收件人不一样,不单单是官方运营能指定的,可能需要一堆条件结合过滤出来的,这一块如何设计呢?能避免程序员的介入,使官方运营能自主完成
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
feeds流系统设计概述
什么是 Feeds 流? 从用户层面来说, 各种手机 APP 里面, 特别是社交类的, 我们可以看到关注的内容、好友的动态聚合成一个列表(最典型的就是微信朋友圈)都是 feeds 流的一种形式。
leobhao
2024/06/18
7650
feeds流系统设计概述
周末小技 | 开发一个Feeds流系统——写扩散模式
点个关注👆跟腾讯工程师学技术 导语 | 本文主要针对Feeds流进行介绍,将从Feeds流的演变入手,带你一步步了解Feeds流,而后学习如何从开发角度入手,对其进行建模,抽象出Feeds流常见的架构,最终搭建高可用、高扩展、高性能的Feeds流应用。 了解Feeds流 在学习如何开发Feeds流应用前,我们需要先了解什么是Feeds流。 一、什么是Feeds流 Feeds流是一个持续更新并展示给用户的信息流。它将用户主动订阅的若干消息源组合在一起形成内容聚合器,帮助用户持续地获取最新的订阅源内容。所以
腾讯云开发者
2022/12/05
1.5K0
周末小技 | 开发一个Feeds流系统——写扩散模式
Feed 流系统的架构设计方案
本文主要针对 Feed 流进行介绍,将从 Feed 流的演变入手,带你一步步了解 Feed 流,而后学习如何从开发角度入手,对其进行建模,抽象出 Feed 流常见的架构,最终搭建高可用、高扩展、高性能的 Feed 流应用。
腾讯云开发者
2024/11/21
4230
Feed 流系统的架构设计方案
让人欲罢不能的Feed流系统是如何设计的?
差不多十年前,随着功能机的淘汰和智能机的普及,互联网开始进入移动互联网时代,最具代表性的产品就是微博、微信,以及后来的今日头条、快手等。这些移动化联网时代的新产品在过去几年间借着智能手机的风高速成长。
Bug开发工程师
2019/07/12
2.8K0
让人欲罢不能的Feed流系统是如何设计的?
Feed流系统设计
差不多十年前,随着功能机的淘汰和智能机的普及,互联网开始进入移动互联网时代,最具代表性的产品就是微博、微信,以及后来的今日头条、快手等。这些移动化联网时代的新产品在过去几年间借着智能手机的风高速成长。
架构师修炼
2020/11/19
1.3K0
Feed流系统设计
揭秘:微信 / 微博 / 头条 / 快手是如何轻松处理亿级规模的 Feed 流的?
差不多十年前,随着功能机的淘汰和智能机的普及,互联网开始进入移动互联网时代,最具代表性的产品就是微博、微信,以及后来的今日头条、快手等。这些移动互联网时代的新产品在过去几年间借着智能手机的风高速成长。
iMike
2019/09/17
1.5K0
揭秘:微信 / 微博 / 头条 / 快手是如何轻松处理亿级规模的 Feed 流的?
基于时间线的Feed流后台系统设计
| 导语  本文将总结一下常用的基于时间线Feed流的后台存储设计方案。结合具体的业务场景,讲述一下根据实际需求,在基本设计思路上做一些灵活运用。 01 背景介绍 Feed流产品在我们手机APP中几乎无处不在,常见的Feed流比如微信朋友圈、新浪微博、今日头条等。对Feed流的定义,可以简单理解为只要大拇指不停地往下划手机屏幕,就有一条条的信息不断涌现出来。就像给牲畜喂饲料一样,只要它吃光了就要不断再往里加,故此得名Feed(饲养)。 大多数Feed流产品都包含两种Feed流,一种是基于算法推荐,另一种是
腾讯大讲堂
2020/11/09
5.2K0
微服务设计原则——高性能:存储设计
大多数业务都是读多写少,为了提高系统处理能力,可以采用读写分离的方式将主节点用于写,从节点用于读,如下图所示。
恋喵大鲤鱼
2024/08/19
1760
微服务设计原则——高性能:存储设计
IM开发技术分享:浅谈IM系统中离线消息、历史消息的最佳实践
在如今的移动互联网时代,IM类产品已是我们生活中不可或缺的组成部分。像微信、钉钉、QQ等是典型的以 IM 为核心功能的社交产品。另外也有一些应用虽然IM功能不是核心,但IM能力也是其整个应用极其重要的组成部分,比如在线游戏、电商直播等应用。
JackJiang
2022/04/19
2.7K1
IM开发技术分享:浅谈IM系统中离线消息、历史消息的最佳实践
Redis进阶学习05---Feed流,GEO地理坐标的应用,bitmap的应用,HyperLogLog实现UV统计
这部分内容比较简单,没啥难度,因此我不打算进行具体代码实践演示,只是给出完整的解决思路和其中的注意事项
大忽悠爱学习
2022/05/09
7170
Redis进阶学习05---Feed流,GEO地理坐标的应用,bitmap的应用,HyperLogLog实现UV统计
高并发的常用策略
例如广告扣费系统,广告主向自己的账号充钱、设置自己的广告,用户浏览或者点击广告后就需要扣费,这个扣费操作的数量是极大的。
dys
2019/07/31
2K0
高并发的常用策略
Spark内核详解 (2) | Spark之间的通讯架构
Spark 内置的RPC框架前后共有两种架构,一个是在Spark2.0.0中被移除的Akka,一个则是借鉴了Akka 的 Actor 模型的Netty
不温卜火
2020/10/28
1.4K0
Spark内核详解 (2) | Spark之间的通讯架构
大数据技术之_19_Spark学习_06_Spark 源码解析小结
1、spark 一开始使用 akka 作为网络通信框架,spark 2.X 版本以后完全抛弃 akka,而使用 netty 作为新的网络通信框架。 最主要原因:spark 对 akka 没有维护,需要 akka 更新,spark 的发展受到了 akka 的牵制,akka 版本之间无法通信,即 akka 兼容性问题。 2、RpcEnv:RPC 上下文环境,每个 Rpc 端点运行时依赖的上下文环境称之为 RpcEnv。类似于 SparkContext,默认由 NettyRpcEnv 实现,由 NettyRpcEnvFactory 创建 RpcEnv。 3、RpcEndpoint:RPC 端点,Spark 针对于每个节点(Client/Master/Worker)都称之一个 Rpc 端点且都实现 RpcEndpoint 接口,内部根据不同端点的需求,设计不同的消息和不同的业务处理,如果需要发送(询问)则调用 Dispatcher。代理是 RpcEndpointRef。 4、Dispatcher:消息分发器,针对于 RPC 端点需要发送消息或者从远程 RPC 接收到的消息,分发至对应的指令收件箱/发件箱。 5、Inbox:指令消息收件箱,一个本地端点对应一个收件箱,Dispatcher 在每次向 Inbox 存入消息时,都将对应 EndpointData 加入内部待 Receiver Queue 中。 6、OutBox:指令消息发件箱,一个远程端点对应一个发件箱,当消息放入 Outbox 后,紧接着将消息通过 TransportClient 发送出去。 7、TransportClient:Netty 通信客户端,主要负责将相对应的 OutBox 中的数据发送给远程 TransportServer。 8、TransportServer:Netty 通信服务端,主要用于接收远程 RpcEndpoint 发送过来的消息,并把消息传送给 Dispatcher。
黑泽君
2019/05/14
5490
大数据技术之_19_Spark学习_06_Spark 源码解析小结
如何在微信群里发通知?这个方法特别好用
今天,「知晓程序」推荐的小程序「群里有事」,也许能解决这个问题。在这里,你不仅可以发布通知、活动,而且它有一种强大的魔力,吸引大家去查看。
知晓君
2018/08/01
2K0
如何在微信群里发通知?这个方法特别好用
《基于实践,设计一个百万级别的高可用 & 高可靠的 IM 消息系统》
https://xie.infoq.cn/article/4061081a5ce66137a8c021994
后台技术汇
2022/05/28
2K0
《基于实践,设计一个百万级别的高可用 & 高可靠的 IM 消息系统》
基于贝叶斯算法的邮件过滤管理系统的设计和实现(Vue+SpringBoot)
电子邮件在我们日常生活中有着广泛的应用,在注册各类网站时,通常需要发送验证码作为身份验证,邮箱验证和短信验证一样,也是身份验证的一种重要方式。电子邮件的出现可以方便我们的正常收发邮件,但由于垃圾邮件过多,严重影响了人们使用电子邮件的使用体验,人们需要花费更多的时间去过滤没有用的邮件,同时也浪费了网络邮件的电子资源。
Designer 小郑
2023/08/01
7870
基于贝叶斯算法的邮件过滤管理系统的设计和实现(Vue+SpringBoot)
你知道微服务架构中的“发件箱模式”吗
微服务架构如今非常的流行,这个架构下可能经常会遇到“双写”的场景。双写是指您的应用程序需要在两个不同的系统中更改数据的情况,比如它需要将数据存储在数据库中并向消息队列发送事件。您需要保证这两个操作都会成功。如果两个操作之一失败,您的系统可能会变得不一致。那针对这样的情况有什么好的方法或者设计保证呢?本文就和大家分享一个“发件箱模式”, 可以很好的避免此类问题。
程序猿川子
2023/01/09
2780
HBase实践 | 数据人看Feed流-架构实践
Feed流:可以理解为信息流,解决的是信息生产者与信息消费者之间的信息传递问题。 我们常见的Feed流场景有:
王知无-import_bigdata
2019/09/25
2.2K0
HBase实践 | 数据人看Feed流-架构实践
不良邮件过滤系统 毕业设计 JAVA+Vue+SpringBoot+MySQL
基于JAVA+Vue+SpringBoot+MySQL的不良邮件过滤系统,包含了发件箱、收件箱、垃圾箱、回收站、黑名单、白名单和关键词过滤模块,还包含系统自带的用户管理、班级管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,不良邮件过滤系统基于角色的访问控制,给邮件管理员、普通用户使用,可将权限精确到按钮级别,您可以自定义角色并分配权限,系统适合设计精确的权限约束需求。
Designer 小郑
2024/01/26
2190
不良邮件过滤系统 毕业设计 JAVA+Vue+SpringBoot+MySQL
快给你的软件加IM聊天功能!
大部分IM为便于查看历史消息或暂存离线消息,都需对消息进行服务端存储,那怎么存储或暂存。
JavaEdge
2021/02/23
1.7K0
快给你的软件加IM聊天功能!
推荐阅读
相关推荐
feeds流系统设计概述
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文