本文由融云技术团队原创分享,原题“IM 音讯数据存储结构设计”,内容有订正。
1、引言
在现在的挪动互联网时代,IM 类产品已是咱们生存中不可或缺的组成部分。像微信、钉钉、QQ 等是典型的以 IM 为外围性能的社交产品。另外也有一些利用尽管 IM 性能不是外围,但 IM 能力也是其整个利用极其重要的组成部分,比方在线游戏、电商直播等利用。
在 IM 技术利用场景越来越宽泛的前提下,对即时通讯 IM 技术的学习和把握就显的越来越有必要。
在 IM 宏大的技术体系中,音讯零碎无疑是最外围的,而音讯零碎中,最要害的局部是音讯的散发和存储,而离线音讯和历史音讯又是这个关键环节中不可回避的技术要点。
本文将基于 IM 音讯零碎的技术实际,分享对于离线音讯和历史音讯的正确理解,以及具体的技术配合和实际,心愿能为你的离线音讯和历史音讯技术设计带来最佳实际灵感。
学习交换:
- 挪动端 IM 开发入门文章:《新手入门一篇就够:从零开发挪动端 IM》
- 开源 IM 框架源码:https://github.com/JackJiang2…
(本文同步公布于:http://www.52im.net/thread-38…)
2、相干文章
技术相干文章:
《什么是 IM 零碎的可靠性?》
《闲鱼 IM 的在线、离线聊天数据同步机制优化实际》
《闲鱼亿级 IM 音讯零碎的牢靠投递优化实际》
《一套亿级用户的 IM 架构技术干货(下篇):可靠性、有序性、弱网优化等》
《IM 音讯送达保障机制实现(二):保障离线音讯的牢靠投递》
《我是如何解决大量离线音讯导致客户端卡顿的》
融云技术团队分享的其它文章:
《融云安卓端 IM 产品的网络链路保活技术实际》
《全面揭秘亿级 IM 音讯的牢靠投递机制》
《解密融云 IM 产品的聊天音讯 ID 生成策略》
《万人群聊音讯投递计划的思考和实际》
《基于 WebRTC 的实时音视频首帧显示工夫优化实际》
《融云 IM 技术分享:万人群聊音讯投递计划的思考和实际》
3、IM 音讯投递的个别做法
在通常的 IM 音讯零碎中,对于实时音讯、离线音讯、历史音讯大略都是上面这样的技术思路。
对于在线用户:音讯会间接实时发送到在线的接管方,音讯发送实现后,服务器端并不会对音讯进行落地存储。
而对于离线的用户:服务器端会将音讯存入到离线库,当用户登录后,从离线库中将离线音讯拉走,而后服务器端将离线音讯删除。
这样实现的毛病就是音讯不长久化,导致音讯无奈反对音讯漫游,升高了音讯的可靠性。
(PS:实际上,这其实也不能算是毛病,因为一些场景下存储历史音讯并不是必须的,所谓的音讯漫游能力也不是必备的,比方微信。)
而在咱们设计的音讯零碎中,服务器只有接管到了发送方发上来的音讯,在转发给接管方的同时也会在离线数据库及历史音讯库中进行音讯的落地存储,而历史音讯的落地也就能反对音讯漫游等相干性能了。
4、什么是离线音讯和历史音讯?
对于离线音讯和历史音讯,在技术上,咱们是这样定义。
1)离线音讯:
离线音讯就是用户(即接管方)在离线过程中收到的音讯,这些音讯大多是用户比较关心的音讯,具备肯定的时效性。
以咱们的零碎教训来说,咱们的离线音讯默认只保留最近七天的音讯。
用户(即接管方)在下次登录后会全量获取这些离线音讯,而后在客户端依据聊天会话进行离线音讯的 UI 展现(比方显示一个未读音讯气泡等)。
(PS:用户离线的可能性在技术上其实是由很多种状况组成的,比方对方不在线、对方网络断掉了、对方手机解体了、服务器发送时出错了等等,严格来讲——只有无奈实时发送成的音讯,都算“离线音讯”。)
2)历史音讯:
历史音讯存储了用户所有的聊天音讯,这些音讯包含收回的音讯以及接管到的音讯。
在客户端获取历史音讯时,通常是依照会话进行分页获取的。
以咱们的零碎教训来说,历史音讯的存储工夫咱们设计默认为半年,当然这个工夫能够按理论的产品经营规定来定,没有硬性规定。
5、IM 音讯的发送及存储流程
以下是咱们零碎整体的音讯发送及存储流程:
如上图所示:当用户发送聊天音讯到服务器端后,首先会进入到音讯零碎中,音讯零碎会对音讯进行散发以及存储。
这个过程中:对于在线的接管方,会抉择间接推送音讯。然而遇到接管方不在线或者是音讯推送失败的状况下,也会有另外的音讯获取形式,比方接管方会被动向服务器拉取未收到的音讯。然而接管方何时来服务器拉取音讯以及从哪里拉取是未知的,所以音讯存入到离线库的意义也就在这里。
音讯零碎存储离线的过程中,为了不影响整个零碎的更为安稳,咱们应用了 MQ 音讯队列进行 IO 解偶,所以聊天音讯实际上是异步存入到离线库中的(通过 MQ 进行慢 IO 解偶,这其实也是惯常做法)。
在散发完音讯后:音讯服务会同步一份音讯数据到历史音讯服务中,历史音讯服务同样会对音讯进行落地存储。
对于新的客户端设施:会有同步音讯的需要(所谓的音讯漫游能力),而这也正是历史音讯的次要作用。在历史音讯库中,客户端是能够拉取任意会话的全量历史音讯的。
6、IM 离线音讯、历史音讯在存储逻辑上的区别
6.1 概述
通过下面的图中能清晰的看到:
1)离线音讯咱们存储介质选用的是 Redis;
2)历史音讯咱们选用的是 HBase。
对于为什么选用不同的存储介质,其实咱们思考的是离线音讯和历史音讯不同的业务场景和读写模式。
上面咱们重点介绍一下离线音讯和历史音讯存储的区别。
6.2 离线音讯存储模式——“扩散写”
离线音讯的存储模式咱们用的是扩散写。
如上图所示:每个用户都有本人独自的收件箱和发件箱:
1)收件箱寄存的是须要向这个接收端同步的所有音讯;
2)发件箱里寄存的是发送端收回的所有音讯。
以单聊为例:聊天中的两人会话中,音讯会产生两次写,即发送者的发件箱和接收端的收件箱。
而在群的场景下:写入会被更加的放大(扩散),如果群里有 N 集体,那一条群音讯就会被扩散写 N 次。
小结一下:
1)扩散写的长处是:接收端的逻辑会十分清晰简略,只须要从收件箱里读取一次即可,大大降低了同步音讯所需的读的压力;
2)扩散写的毛病是:写入会被成指数地放大,特地是针对群这种场景。
6.3 历史音讯存储模式——“扩散读”
历史音讯的存储模式咱们用的是扩散读。
因为历史音讯中,每个会话都保留了整个会话的全量音讯。在扩散读这种模式下,每个会话的音讯只保留一次。
比照扩散写模式,扩散读的长处和毛病如下:
1)长处是:写入次数大大降低,特地是针对群音讯,只须要存一次即可;
2)毛病是:接收端接管音讯十分的简单和低效,因为这种模式客户端想拉取到所有音讯就只能每个会话同步一次,读就会被放大,而且可能会产生很屡次有效的读,因为有些会话可能基本没有新音讯。
6.4 小结
在 IM 这种利用场景下,通常会用到扩散写这种音讯同步模型,一条音讯产生一条,然而可能会被读屡次,是典型的读多写少的场景。
一个优化好的 IM 零碎,必须从设计上均衡读写压力,防止读或者写任意一个维度达到天花板。
当然扩散写这种模式也有其弊病,比方万人群,会导致一条音讯,写入了一万次。
综合来讲:咱们须要依据本人的业务场景做相应设计抉择,以咱们的 IM 零碎为例,就是是依据了离线和历史音讯的不同场景抉择了写扩散和读扩散的组合模式。适宜的才是最好的,没有必要死搬硬套实践。
7、IM 客户端的拉取音讯逻辑
7.1 离线音讯拉取逻辑
对于 IM 客户端而言,离线音讯的获取针对的是本人的整个离线音讯,包含所有的会话(直白了说,就是上线时拉取此次离线过程中的所有未收取的离线音讯)。
离线音讯的获取是自上而下的形式(按工夫序),咱们的教训是一次获取 200 条(PS:如果离线音讯过多,会分页屡次拉取,拉取 1“次”能够了解为拉取 1“页”)。
在客户端拉取离线音讯的信令中,须要带上以后客户端缓存的音讯的最大工夫戳。
通过上节的图咱们应该晓得,离线音讯咱们存储的是一个线性构造(指的是按工夫程序),Server 会依据这个工夫戳向下查找离线音讯。当重装或者新装置 App 时,客户端的“以后客户端缓存的音讯的最大工夫戳”能够传 0 上来。
Server 也会缓存客户端拉取到的最初一条音讯的工夫戳,而后依据业务场景,客户端类型等因素来决定从哪里开始拉取,如果没有拉取完 Server 会在拉取音讯的应答中带相应的标记位,通知客户端持续拉取,客户端循环拉取,直到所有离线音讯拉完。
7.2 历史音讯拉取逻辑
历史音讯的获取通常针对的是繁多会话。
在拉取过程中,须要向服务端提交两个参数:
1)对方的 ID(如果是单聊的话就是对方的 UserID,如果是群则是群组 ID);
2)以后会话的最后面音讯的工夫戳(即以后会话最老一条音讯的工夫戳)。
Server 据这两个参数,能够定位到这个客户端的此会话,而后一次获取 20 条历史音讯。
音讯的拉取时序上采纳的是自下而上的形式(也就是工夫序逆序),即从最初面往前翻。只有有音讯,客户端能够始终向前翻,手动触发获取会话的历史音讯。
下面的拉取逻辑,在 IM 界面性能上通常对应的是下拉或点击“加载更多”,比方这样:
8、本文小结
本文次要分享了 IM 中无关离线音讯和历史音讯的正确,次要包含离线音讯和历史音讯的区别,以及二者在存储、散发、拉取逻辑方面的最佳践等。如对文中内容有异议,欢送留言探讨。
9、参考资料
[1] 一套海量在线用户的挪动端 IM 架构设计实际分享 (含具体图文)
[2] 一套原创分布式即时通讯(IM) 零碎实践架构计划
[3] 从零到卓越:京东客服即时通讯零碎的技术架构演进历程
[4] 一套亿级用户的 IM 架构技术干货(上篇):整体架构、服务拆分等
[5] 闲鱼亿级 IM 音讯零碎的架构演进之路
[6] 闲鱼亿级 IM 音讯零碎的牢靠投递优化实际
[7] 闲鱼亿级 IM 音讯零碎的及时性优化实际
[8] 基于实际:一套百万音讯量小规模 IM 零碎技术要点总结
[9] IM 音讯送达保障机制实现(一):保障在线实时音讯的牢靠投递
[10] 了解 IM 音讯“可靠性”和“一致性”问题,以及解决方案探讨
[11] 零根底 IM 开发入门(一):什么是 IM 零碎?
(本文同步公布于:http://www.52im.net/thread-38…)