开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
IM消息的存储的经典方案有两种:读扩散与写扩散。
1. 读扩散
消息只存储一份,所有成员都去读取同一条消息。
- 缺点:
- 需要额外存储信息,比如群ID,会话ID等标识是某个群或好友的消息。
- 接收端获取消息业务复杂,比如新用户进群、群成员删除消息、获取所有群消息等。
- 优点
- 存储空间小。
- 写操作压力小,每条消息只需要写入一次。
2. 写扩散
每个用户都有一个接收消息的信箱,即发送一条群聊每个群成员都会保存一份。
- 缺点:
- 存储空间变大。
- 并发写操作。比如万人群,每条消息并发写入1w次。
- 优点
- 查询消息压力分散,读取速度快
- 接收端消息处理简单,只需要从个人信箱中读取消息。
- 对于已读、未读、总未读数等这些复杂逻辑可以很好的处理。
3. 单聊消息的存储方案
单聊消息的存储推荐写扩散,这样双方处理删除消息、撤回、新消息拉取都很方便。不过这里写扩散可以做个优化,消息只需要保存一份,双方用户只需要存储该条消息的索引来节省存储空间。
4. 群聊消息的存储方案
群聊消息的存储就比较复杂,加上烦人的企业IM的已读、未读、n人读等等。下面我们来分析下选用哪种方案合适。
我们知道一个聊天的IM肯定是读多写少的,如果选用了读扩散,那整个系统的读操作是很巨大的。下面看下读扩散处理群聊的场景:
- 比如你加了100个群,每次都需要都依次检索这100个群的消息。而写扩散用空间换时间,接收端只需要从一个信箱中获取即可。对比可知两种方式拉取一次群消息的读取量是100:1。
- 某用户删除群消息需要额外记录删除的消息,那么该用户拉取群消息的时候需要关联删除消息表做合并数据。
- 新用户进群旧消息不可见,那么需要记录该用户进群时的时间戳或进群时最新一条的msgId等额外信息实现。
- 对于已读、未读等复杂逻辑处理起来很复杂。
因此写扩散更合适作为群聊消息的存储方案。对于以上的场景,写扩散也很好的支持。
对于大群(万人群或更大)用写扩散来说,每条新消息的写入并发又会非常巨大,这时候读扩散更适合。其实这就需要在产品设计上解决了,比如微信设置了群上限。读写扩散存储是可以穿插使用的,不限定死只能用一种。