im 系统知识整理
| 实现方式、对比维度 | IM即时通讯开源代码 | IM即时通讯自研 | 集成商业IM即时通讯sdk |
|---|---|---|---|
| 实现难度 | 低 | 高 | 中 |
| 功能扩展性 | 依赖开源项目计划,相对困难 | 不依赖外部条件,相对简单 | 依赖其它厂商,难度中等 |
| 运维成本 | 自己运维,成本高 | 自己运维,成本高 | 不需要自己运维 |
| 上线周期 | 中 | 慢 | 快 |
| 适用人群 | 个人体验 | 研发能力较强的大公司 | 中小型公司,个人工作室 |
1. im 功能要求
1.1 架构分层
服务端
账号系统、消息系统、资料系统、关系链系统、群组系统
客户端
android、ios、web、小程序、flutter
管理后台
用管理员、安全打击
1.2 产品内容
- 1、消息传输:支持文字、图片、短语音、短视频等富媒体消息及自定义消息与自定义表情,支持保存历史漫游消息,集成消息撤回、消息转发、安全打击等扩展能力,构建稳定、便捷的消息传输通道。
- 2、会话管理:集成 TUIKit 组件,轻松实现添加会话、会话置顶、会话列表展示,未读消息计数,历史漫游消息展示等功能。
- 3、群组管理:支持群成员管理、群组自定义字段、群资料与群公告变更与展示、群组置顶等能力,提供私有群、公开群、聊天室、音视频聊天室等多种群组类型,满足个性化群组需要。
- 4、资料管理:支持设置用户资料、更改头像,可配置好友关系,提供好友验证选项,适配您的业务场景
2. im 技术难点
- 消息的可靠性、有序性。
- 高并发场景下的消息实时推送,以及消息拉取。
- 消息存储方案选型:使用读扩散还是写扩散。
- 消息未读数的准确计算。
- 群回执消息。
- 异地多活
- 涉及产品可使用第三方:文件存储,安全审核,消息离线推送
3. im 问题
3.1 设计阶段基本问题
- 用户从没有网络切换到有网络的情况下,如何第一时间把消息推送过去?
如果同时考虑避免用户抱怨消耗太多流量和电量呢?
—————— 不停的尝试连接网络,手机操作系统会返回网络状态的,不用你消耗流量来检测 - 如何处理消息后发先至的问题(A.send>B.send && A.receive<B.receive)?如何处理丢消息的情形?
—————— 消息订阅和发布,kafka,redis,mqtt - 用户在多台设备上登陆,消息同步机制如何设计?
- 用户数量
3.2 消息不丢、不重复、不乱序
不丢:主要靠服务端的消息暂存和SDK的ACK机制;
不重复:主要靠消息的全局唯一ID生成算法和SDK去重机制;
不乱序:主要靠服务端统一的并发排序机制。
3.3 解决数据库高并发查询慢的瓶颈
- 弃用查询速度一般的MYSQL,选用查询速度超快的NOSQL数据库MongoDB。
- 读写分离,写时写到主数据库,实时同步至多台从数据库,查询时选择最闲的从数据库,从而使查询压力分散到多台。
- 分库分表,比如每一个群组是一个表,避免产生超大数据量的表,使单次查询速度保持在可控范围。
- 冷热分离,比如单聊的数据表,可以设置热表保存数据的日期范围,半年内的数据保存到热表,半年以前的数据保存到冷表,避免数据量过于巨大。
- 最热缓存,对于最常用的热点数据复制到Redis内存中进行查询,速度极快,避免数据库高频次的重复查询
3.4 解决聊天通讯的高并发瓶颈
- 采用基于Protobuf的二进制字节格式,包极小,还支持压缩,使单次通讯的流量压缩至最低。
- 采用为高并发而生的AIO框架JAVA,使单台的并发能力大幅提高,单台并发最高可达到50W左右。
- 采用自研的聊天集群软件使聊天的压力由单台分散到多台,
比如A登陆在服务器A,B登陆在服务器B,A给B发消息,服务器A收到,查询内存,得知B登录在服务器B上,于是转发给B服务器,服务器B就会通过与B的长连接把消息发给B;
群聊也类似,A和B在同一群组,A在群里发了一条消息,查询内存,得知在线的群成员列表,然后给所有在线成员一一发送这条消息,注意以单聊的形式发,这样其他成员便不会重复转发这条消息