乐趣区

关于即时通讯:im即时通讯开发聊天消息的同步和存储

IM 全称是『Instant Messaging』,中文名是即时通讯。在这个高度信息化的挪动互联网时代,生存中 IM 类产品曾经成为必备品,比拟有名的如钉钉、微信、QQ 等以 IM 为外围性能的产品。当然目前微信曾经成长为一个生态型产品,但其外围性能还是 IM。还有一些非以 IM 零碎为外围的利用,最典型的如一些在线游戏、社交利用,IM 也是其重要的功能模块。能够说,带有社交属性的利用,IM 性能肯定是必不可少的。

IM 零碎在互联网初期即存在,其根底技术架构在这十几年的倒退中更新迭代屡次,从晚期的 CS、P2P 架构,到当初后盾曾经演变为一个简单的分布式系统,波及挪动端、网络、平安和存储等技术的方方面面。其撑持的规模也从晚期的大量日活,到当初微信这个巨头最新颁布的达到 9 亿的日活的体量。

IM 零碎中最外围的局部是音讯零碎,音讯零碎中最外围的性能是音讯的同步和存储:

1)音讯的同步:将音讯残缺的、疾速的从发送方传递到接管方,就是音讯的同步。音讯同步零碎最重要的掂量指标就是消息传递的实时性、完整性以及能撑持的音讯规模。从性能上来说,个别至多要反对在线和离线推送,高级的 IM 零碎还反对『多端同步』;

2)音讯的存储:音讯存储即音讯的长久化保留,这里不是指音讯在客户端本地的保留,而是指云端的保留,性能上对应的就是『音讯漫游』。『音讯漫游』的益处是能够实现账号在任意端登陆查看所有历史音讯,这也是高级 IM 零碎特有的性能之一。

本文内容次要波及 IM 零碎中的音讯零碎架构,探讨一种实用于大用户量的音讯同步以及存储系统的架构实现,可能反对音讯零碎中的高级个性『多端同步』以及『音讯漫游』。在性能和规模上,可能做到全量音讯云端存储,百万 TPS 以及毫秒级提早的音讯同步能力。

次要会介绍基于 TableStore 的古代 IM 音讯零碎的架构设计,在具体介绍架构设计之前,会先介绍一种 Timeline 逻辑模型,来形象和简化对 IM 音讯同步和存储模型的了解。了解了 Timeline 模型后,会介绍如何基于此模型对音讯的同步以及存储进行建模。基于 Timeline 模型,在实现音讯同步和存储时还会有各方面的技术衡量,例如如何对音讯同步常见的读扩散和写扩散两种模型进行比照和抉择,以及针对 Timeline 模型的特色如何来抉择底层数据库。

传统架构下,音讯是先同步后存储:

对于在线的用户,音讯会间接实时同步到在线的接管方,音讯同步胜利后,并不会进行长久化。而对于离线的用户或者音讯无奈实时同步胜利时,音讯会长久化到离线库,当接管方从新连贯后,会从离线库拉取所有未读音讯。当离线库中的音讯胜利同步到接管方后,音讯会从离线库中删除。传统的音讯零碎,服务端的次要工作是保护发送方和接管方的连贯状态,并提供在线音讯同步和离线音讯缓存的能力,保障音讯肯定可能从发送方传递到接管方。服务端不会对音讯进行长久化,所以也无奈反对音讯漫游。

古代架构下,音讯是先存储后同步:

先存储后同步的益处是,如果接管方确认接管到了音讯,那这条音讯肯定是曾经在云端保留了。并且音讯会有两个库来保留,一个是音讯存储库,用于全量保留所有会话的音讯,次要用于反对音讯漫游。另一个是音讯同步库,次要用于接管方的多端同步。

音讯从发送方收回后,通过服务端转发,服务端会先将音讯保留到音讯存储库,后保留到音讯同步库。实现音讯的长久化保留后,对于在线的接管方,会间接抉择在线推送。但在线推送并不是一个必须门路,只是一个更优的消息传递门路。

对于在线推送失败或者离线的接管方,会有另外一个对立的音讯同步形式。接管方会被动的向服务端拉取所有未同步音讯,但接管方何时来同步以及会在哪些端来同步音讯对服务端来说是未知的,所以要求服务端必须保留所有须要同步到接管方的音讯,这是音讯同步库的次要作用。对于新的同步设施,会有音讯漫游的需要,这是音讯存储库的次要作用,在音讯存储库中,能够拉取任意会话的全量历史音讯。

以上是传统架构和古代架构的一个简略的比照,古代架构上整个音讯的同步和存储流程,并没有变简单太多,然而其能实现多端同步以及音讯漫游。古代架构中最外围的就是两个音讯库『音讯同步库』和『音讯存储库』,是音讯同步和存储最外围的根底。而本篇文章接下来的局部,都是围绕这两个库的设计和实现来开展。

Timeline 模型

在剖析『音讯同步库』和『音讯存储库』的设计和实现之前,在本章会先介绍一个逻辑模型 -Timeline。Timeline 模型会帮忙咱们简化对音讯同步和存储模型的了解,而音讯库的设计和实现也是围绕 Timeline 的个性和需要来开展。

Timeline 能够简略了解为是一个音讯队列,但这个音讯队列有如下个性:

每个音讯领有一个程序 ID(SeqId),在队列前面的音讯的 SeqId 肯定比后面的音讯的 SeqId 大,也就是保障 SeqId 肯定是增长的,然而不要求严格递增;

新的音讯永远在尾部增加,保障新的音讯的 SeqId 永远比曾经存在队列中的音讯都大;

可依据 SeqId 随机定位到具体的某条音讯进行读取,也能够任意读取某个给定范畴内的所有音讯。

有了这些个性后,音讯的同步能够拿 Timeline 来很简略的实现。图中的例子中,音讯发送方是 A,音讯接管方是 B,同时 B 存在多个接收端,别离是 B1、B2 和 B3。A 向 B 发送音讯,音讯须要同步到 B 的多个端,待同步的音讯通过一个 Timeline 来进行替换。A 向 B 发送的所有音讯,都会保留在这个 Timeline 中,B 的每个接收端都是独立的从这个 Timeline 中拉取音讯。每个接收端同步结束后,都会在本地记录下最新同步到的音讯的 SeqId,即最新的一个位点,作为下次音讯同步的起始位点。服务端不会保留各个端的同步状态,各个端均能够在任意工夫从任意点开始拉取音讯。即时通讯聊天软件开发能够征询蔚可云。

音讯漫游也是基于 Timeline,和音讯同步惟一的区别是,音讯漫游要求服务端可能对 Timeline 内的所有数据进行长久化。

基于 Timeline,从逻辑模型上可能很简略的了解在服务端如何去实现音讯同步和存储,并反对多端同步和音讯漫游这些高级性能。落地到实现的难点次要在如何将逻辑模型映射到物理模型,Timeline 的实现对数据库会有哪些要求?咱们应该抉择何种数据库去实现?这些是接下来会探讨到的问题。

基于 Timeline 的音讯存储模型,音讯存储要求每个会话都对应一个独立的 Timeline。如图例子所示,A 与 B /C/D/E/ F 均产生了会话,每个会话对应一个独立的 Timeline,每个 Timeline 内存有这个会话中的所有音讯,服务端会对每个 Timeline 进行长久化。服务端可能对所有会话 Timeline 中的全量音讯进行长久化,也就领有了音讯漫游的能力。

音讯同步模型

音讯同步模型会比音讯存储模型稍简单一些,音讯的同步个别有读扩散和写扩散两种不同的形式,别离对应不同的 Timeline 物理模型。

读扩散和写扩散两种不同同步模式下对应的不同的 Timeline 模型,按图中的示例,A 作为音讯接收者,其与 B /C/D/E/ F 产生了会话,每个会话中的新的音讯都须要同步到 A 的某个端,看下读扩散和写扩散两种模式下音讯如何做同步。

读扩散:

音讯存储模型中,每个会话的 Timeline 中保留了这个会话的全量音讯。读扩散的音讯同步模式下,每个会话中产生的新的音讯,只须要写一次到其用于存储的 Timeline 中,接收端从这个 Timeline 中拉取新的音讯。

长处是音讯只须要写一次,相比写扩散的模式,可能大大降低音讯写入次数,特地是在群音讯这种场景下。但其毛病也比拟显著,接收端去同步音讯的逻辑会绝对简单和低效。接收端须要对每个会话都拉取一次能力获取全副音讯,读被大大的放大,并且会产生很多有效的读,因为并不是每个会话都会有新音讯产生。

写扩散:

写扩散的音讯同步模式,须要有一个额定的 Timeline 来专门用于音讯同步,通常是每个接收端都会领有一个独立的同步 Timeline,用于寄存须要向这个接收端同步的所有音讯。

每个会话中的音讯,会产生屡次写,除了写入用于音讯存储的会话 Timeline,还须要写入须要同步到的接收端的同步 Timeline。在集体与集体的会话中,音讯会被额定写两次,除了写入这个会话的存储 Timeline,还须要写入参加这个会话的两个接收者的同步 Timeline。而在群这个场景下,写入会被更加的放大,如果这个群领有 N 个参与者,那每条音讯都须要额定的写 N 次。

写扩散同步模式的长处是,在接收端音讯同步逻辑会非常简单,只须要从其同步 Timeline 中读取一次即可,大大降低了音讯同步所需的读的压力。其毛病就是音讯写入会被放大,特地是针对群这种场景。

在 IM 这种利用场景下,通常会抉择写扩散这种音讯同步模式。

IM 场景下,一条音讯只会产生一次,然而会被读取屡次,是典型的读多写少的场景,音讯的读写比例大略是 10:1。若应用读扩散同步模式,整个零碎的读写比例会被放大到 100:1。

一个优化的好的零碎,必须从设计下来均衡这种读写压力,防止读或写任意一维触碰到天花板。所以 IM 零碎这类场景下,通常会利用写扩散这种同步模式,来均衡读和写,将 100:1 的读写比例均衡到 30:30。

当然写扩散这种同步模式,还须要解决一些极其场景,例如万人大群。针对这种极其写扩散的场景,会进化到应用读扩散。一个简略的 IM 零碎,通常会在产品层面限度这种大群的存在,而对于一个高级的 IM 零碎,会采纳读写扩散混合的同步模式,来满足这类产品的需要。采纳混合模式,会依据数据的不同类型和不同的读写负载,来决定用写扩散还是读扩散。

退出移动版