IM 内容分享(十七): IM读写扩散模型

本文探讨了IM系统中的写扩散模型(基于独立信箱的推送)和读扩散模型(共享信箱的拉取),比较了它们在消息处理、存储成本、性能和定制化处理上的特点,以及如何在实际场景中选择合适的模型。
摘要由CSDN通过智能技术生成

目录

一、IM 写扩散模型

二、IM 读扩散模型

三、读写扩散模型

总结文中关键


读写扩散模型,即读扩散和写扩散模型;

读扩散,也叫拉取模型,描述对数据进行读取操作时,有更多的读取动作;

写扩散,也叫推送模型,描述对数据进行写入操作时,有更多的写入动作。

IM 系统的读写扩散模型主要体现在对群消息的处理上,在之前的文章中曾经分析过群消息的处理方式,我们对重点快速复习一下。

假设一个群有三个成员,分别是 uid=101、uid=102 和 uid=103,用户 uid=101 在群里发送消息 “大家好!”,见下图。

那么需要在群消息关系表中保存记录,如下:

也就是,每发送一条群消息,需要站在每个群成员的维度分别保存一条消息记录。这样设计的原因主要有两个:一是为了方便消息的定制化处理(若一个群成员删除了群消息,只是删除了自己的群消息,并不会影响到其他群成员能浏览到该条群消息);二是当群消息数量很大做分库分表时,每一个用户的所有群消息能落在同一张表中,避免对所有数据表的遍历。

一、IM 写扩散模型

上述处理逻辑其实就是 IM 系统的写扩散操作,我们对其抽象出 “写扩散模型”,见下图。

在 IM 的写扩散模型中,每一个群成员都有自己独立的 “信箱”(即消息存储);当产生一条群消息时,需要分别投递(写入)到每个成员的信箱中;每个成员对群消息进行读取时,只需要从自己的信箱中拉取消息即可。

写扩散模型最大的优点就是读取逻辑非常简单,尤其是在大规模用户高并发读取时,避免了锁操作,有较大的性能优势;同时,因为存储隔离,方便了消息的定制化处理。

写扩散模型最大的缺点就是消息的存储成本很大,发送消息操作较为耗时,思考一下,为什么微信群成员数量的上限是 500?同时,写扩散队列在落地实现时有非常高的技术复杂度。

写扩散模型通常应用在群成员数量不高,读多写少的业务场景中。

二、IM 读扩散模型

当一个群成员的数量是 10 或 100 时,我们可以使用 “写扩散模型” 解决方案,当群成员数量是 1000 或 10000 时,写扩散模型会因为冗余写导致非常高的写延时,这肯定是不可取的,此时可以使用 “读扩散模型” 方案,见下图。

在 IM 的读扩散模型中,所有的群成员共享同一个信箱(群消息存储);当产生一条群消息时,只需要将一条群消息记录投递(写入)到信箱中即可;然后所有的群成员从这一个信箱中读取群消息。

看到这里,细心的同学肯定会发出疑问,这样的设计方式,消息的定制化处理怎么做呢?比如:成员 A 删除了一条群消息,这肯定不能影响到其他群成员对这条群消息的浏览。这就是读扩散模型的核心了:需要专门设计一张 “群消息删除表” 来记录删除的群消息id,每个群成员从信箱中读取群消息后,再读取 “群消息删除表”,以此判断该群消息是否展示。

读扩散模型最大的优点就是消息的写入逻辑简单(毕竟只写一条记录即可),消息的存储成本较低,写入的实时性好,没有时延问题。

读扩散模型最大的缺点就是数据的读取逻辑复杂,不仅要读取消息存储表,还要读取其他业务表后进行数据聚合;另外一个非常关键的问题是多用户并发读取时会形成 IO 的热点,造成性能的急剧下降。

读扩散模型通常应用在群成员数量很高,读少写多的业务场景中。

三、读写扩散模型

在 IM 群消息的业务场景中,有一个默认的前提,就是每一个群成员默认订阅了所有的群消息,每一条群消息都会去接收。我们将这个 “订阅” 的前提动作考虑进来,形成完整的读写扩散模型。

读写扩散模型除了 IM 之外,应用更多的是 feed 流场景,比如:微信朋友圈、微博等。

在完整的读写扩散模型中,有【订阅】、【发布】、【取消订阅】等主要的业务动作。

1、订阅

假设一个系统中有 X、Y、Z 三个用户,用户 X 订阅了 用户 Y 和用户 Z,用户 Y 订阅了用户 Z,那么其订阅和被订阅的关系存储,见下图。

订阅与被订阅关系,一般通过双向的 KList 结构来存储。

用户 X 订阅了 Y 和 Z,那么在 “订阅关系” 中,Key 是 X,List 中元素包括 Y 和 Z;用户 Y 订阅了 Z,那么在 “订阅关系” 中,Key 是 Y,List 中元素包括 Z。

在 “被订阅关系” 中,Y 被 X订阅,则 Key 是 Y,List 中元素包括 X;Z 被 X 和 Y 订阅,则 Key 是 Z,List 中元素包括 X 和 Y。

2、发布

假设用户 Z 发布了两条消息:msg1 和 msg2,在不同的扩散模型中,则有不同的存储方式。

在写扩散模型中,处理方式为:

  • 从被订阅关系中,由 Z 获取元素 X 和 Y;

  • 在 “写扩散存储” 中,将两条消息 msg1 和 msg2 分别写入到 X 和 Y 的 KList 结构中,见下图;

  • 用户 X 和 Y 在拉取消息时,直接从 “写扩散存储” 中读取。

在读扩散模型中,处理方式为:

  • 在 “读扩散存储” 中,直接将两条消息 msg1 和 msg2 写入到 Z 的 KList 结构中,见下图;

  • 用户 X 在拉取消息时,首先从 “订阅关系” 中获取其订阅的列表,Y 和 Z;

  • 然后再从 “读扩散存储” 中,分别获取 Y 和 Z 的消息列表后进行聚合。

3、取消订阅

取消订阅操作比较简单,直接从 “订阅关系” 和 “被订阅关系” 的存储列表中删除相关元素,同时根据业务规则,对已经获取的消息是否需要保留进行判断即可。

总结文中关键

  1. IM 写扩散模型中,每产生一条消息,需要分别投递到每个成员的独立信箱中;该模型读取逻辑简单,方便消息的定制化处理,在高并发读时有较大的性能优势;但是该模型的存储成本很大,写扩散队列落地复杂。

  2. IM 读扩散模型中,每产生一条消息,只需写一条记录即可;该模型消息的写入逻辑简单,存储成本低,实时性好;不过数据的读取逻辑复杂,在多用户并发读取时会有 IO 热点问题。

  3. 在完整的读写扩散模型中,有【订阅】、【发布】、【取消订阅】等主要的业务动作;一般通过 KList 结构实现订阅关系、被订阅关系、写扩散存储和读扩散存储。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值