前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >IM系统海量消息数据是怎么存储的?

IM系统海量消息数据是怎么存储的?

作者头像
普通程序员
发布2019-10-23 11:49:15
7.1K0
发布2019-10-23 11:49:15
举报
文章被收录于专栏:普通程序员

一、与消息相关的主要场景

1、存储和离线消息。

现在的IM系统,消息都要落地存储。这样如果接收消息的用户不在线,等他下次上线时,能获取到消息数据。

2、消息漫游

消息漫游包括主要两种场景,

(1)用户新安装IM软件,要能看到以前的聊天记录

(2)聊天软件有PC版和App版,在App上聊的天,打开PC版要能够看到

二、不同场景读取 消息关键点

1、拉取离线消息

每个用户打开App就需要拉取离线,网络中断重连后要拉取离线,收到消息序列号不连续也要拉取离线,拉取离线消息是一个高频操作 。离线消息包括单聊、群聊、控制类等消息,消息类型类型众多。因此离线消息需要以用户ID(多端情况下需要以端)为检索维度。说的直白一点,就是每个人(端)都需要一个收件箱,拉离线消息就是把个人(端)收件箱里的消息取到客户端。

2、消息漫游

消息漫游的典型使用场景是,打开某个会话(单聊、群聊、公众号),下拉界面,客户端向服务端请求这个会话的聊天数据。消息漫游需要以会话为检索维度。消息漫游拉取数据的频率相对较低。我们把这类获取消息的方式成为拉取历史消息。

三、存储消息关键点

1、离线消息

离线消息读取频繁(写也有一定压力),但是检索逻辑简单(参看《一个海量在线用户即时通讯系统(IM)的完整设计》拉取离线消息章节)。我们采用内存数据库(Redis)存储,主要结构使用SortedSet(可以有更高效的存储结构,但Redis不支持)。对于群消息,采用扩散写方式(一条群消息给每个群成员都写一份)。按照消息接受者ID水平分库。

2、历史消息

历史消息的访问频率低,但是每条消息都需要存储,我们采用关系型数据库(MySQL)存储,重点考虑写入效率。对于群消息,采用扩散读方式(每条群消息只写一条记录)。按照消息发送者ID(单聊),或群ID(群聊)进行水平分库。

四、消息存取方案

1、离线消息

存储离线消息。按照消息接收者ID(toID),取模Hash分库(也可以用一致性Hash)。每个用户创建一个SortedSet结构的Key,用于存储离线消息。离线消息按照时间先后顺序排列即可。SortedSet添加一个元素时间复杂度是O(log(N)),N 是有序集的基数,由于离线消息的msgid是有序的,所以实际插入时间复杂度很可能退化为O(1)。

读取离线消息。离线消息读取策略参看《一个海量在线用户即时通讯系统(IM)的完整设计》拉取离线消息章节。理论上读取离线消息的时间复杂度为O(log(N)+M), N 为离线消息的条数, M 为一次读取消息的条数。实际上,由于离线消息从有序集的头部开始读取,实际时间复杂度比这个值低。

2、历史消息

历史消息分为两大类,单聊消息、群聊消息。

单聊消息按照发送者ID(fromId)水平(取模Hash)分库,存到一张数据表(例如叫msg_user_send)中。核心字段包括msgid(消息ID),fromId(发送者Id),toId(接收者Id),content(消息内容)。

拉取单聊历史消息时(假设拉取userId1跟userId2的聊天),分别读取两人给对方发送的消息(因为分库原因,两人发送的消息可能分布在不同数据库中),然后进行Merge。

群聊消息按照群ID(groupId)水平(取模Hash)分库,存到一张表中(例如叫:msg_group)。核心字段包括msgid(消息ID),fromId(发送者Id),groupId(群Id),content(消息内容)。

另外一张msg_group_user表记录用户加入群的时间,如下图。某个人(如张三)加入群的时间,相当于一个游标,群消息表中,这个游标之后的聊天消息,是这个人(张三)能够查看的数据(当然,也可以做查看加入群之前若干条消息)。

拉取群历史消息,直接倒序读取这个群消息表数据即可。

由于MySQL和Redis都采用了水平分库,存储能力几乎可以线性扩展!是不是这样就足够了呢?答案是否定的,优化永远没有尽头。如果我在非洲某个国家登录系统,从北京的机房读取消息数据显然不太合适!如何让数据靠近用户,是一个更加有挑战的问题。

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

本文分享自 普通程序员 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档