IM群聊数据冷热分离的方案实践
  楠木大叔   12/24/22 10:53:26 AM
在IM的大型实践中,有很多处理方案,比如,数据冷热分离、分库分表、本地数据库等方案。

导航

  • 基本目标
  • 痛点
    • 性能痛点
    • 业务痛点
  • 场景梳理
  • 什么是冷热分离
  • 冷热分离思路
  • 热数据的存储
  • 结语
  • 参考

一 基本目标

提升系统稳定性,最大限度减少数据库压力。

二 痛点

性能痛点

  • 群列表查询高频&耗时
  • 单库单表,抗风险能力低
  • 死锁
  • CPU100%,宕机

以上问题,集中体现在群成员单表较大,读写业务操作频繁。

业务痛点

  • 无限增长的群和群成员
  • 群没有生命周期
  • 业务咨询师需要入驻大量客户对接群

以上问题,导致分库分表困难——很难找到一个合适的维度拆分群成员表

三 场景梳理

平台/商家咨询师获取"我的群会话"

  • 人工切换机构对接群tab,切换到群列表
  • 有新消息时,通过点击消息盒子进入群列表
  • 通过客户查询,进入群列表
  • 全局刷新
  • 自动刷新

以上任何动作,都将触发群列表接口的查询。(根据阿里云日志接口统计:平均调用频次>1000次/min)

产生的问题:

  • 全量数据中查询"我的群聊会话"
  • 大量重复查询
  • 实时查询

基于实际业务场景分析

  • 转诊派单业务本身具有时效性和阶段性
  • 咨询师每天对接的群数量有限
  • 每天新增的商家对接群数量有限

可以推断,咨询师只关心需要对接的那部分群会会话,这部分会话我们称为活跃会话

活跃会话: 三个月内产生的群会话+当天新增的会话+当天产生消息的会话

四 什么是冷热分离

为了更好的理解冷热分离的概念,我们先了解下什么是热数据,什么是冷数据。

  • Hot(热数据)
    • 被频繁查询或更新
    • 对访问的响应时间要求很高,通常在10毫秒以内
  • Cold(冷数据)
    • 不允许更新,偶尔被查询
    • 对访问的响应时间要求不高,通常在1~10秒内都可以接受
热数据

热数据指的是需要即时对用户进行分发的数据,即从数据源抓取之后经过数据处理,需要即时存储到可快速分发的存储介质供API或直接面向用户的系统使用。

热数据需要重点保障服务质量和稳定性,为了保证数据的时效性,在数据处理上也是优先级高的数据。

冷数据

冷数据指的是不需要即时发给用户的数据。

这些数不会原样分发给用户,它们需要经过长期的积累,使我们可以从中得到基于此更高层次的分析。

冷热分离

冷热分离指的是在处理数据时将数据库分为冷库和热库,冷库指用于存放走到了终态的数据(冷数据)的数据库,热库用于存放还需要修改的数据(热数据)的数据库。

冷热分离好处

通过合理的冷热分离设计,可以达到的好处:

  • 降低单表数据量,提升单表性能
  • 大量业务冷数据转冷存

五 冷热分离思路

1、冷热数据的判断

绝大部分场景,数据都可以分为“冷数据”和“热数据”。数据划分的原则,可以根据时间远近、热点/非热点用户等等。例如在以往项目中的实例,用户通常只访问一段时间之内的数据,例如近一周或一个月。如果数据不做划分,必然会导致一定程度上的性能、成本损耗。

3个月内的群数据作为热数据,3个月前的群数据作为冷数据。

Notes:
a. 当天新增的会话
b. 当天产生消息的会话
c. 不会同时存在读冷/热数据的需求

2、触发冷热数据分离
结合业务场景,我们冷热数据分离的触发实现有2种方式:业务层代码实现、定时扫描数据库实现

(一)业务层代码实现
在代码中实现,当有对数据进行写操作时,触发冷热分离。

(二)定时扫描数据库实现
通过定时扫描数据库的方式来触发。
建议使用场景:在按照时间区分冷热数据时使用。

六 热数据的存储

1.存储(持久化)
增加chatmember-hot表,定时从chatmember 同步活跃数据到该表。

字段 类型 说明
Id bigint(20) 主键
ChatId bigint(20) 会话Id
ChatType Int(2) 会话类型
UserId bigint(20) 群成员ID
UserType Int(2) 用户类型
IsRemoved 是否退群
IsDeleted 是否移除
UnReadCount 消息未读数
IsMaster 是否群主
LastMsgId 群聊中我的最后一条消息
IsTop 置顶
IsAtMe @我
IsAtAll @所有人
LastMsgSendTimestamp 最新消息发送时间戳
Createtime 创建时间
Updatetime 更新时间
Synctime 同步时间

3、热数据更新机制

这里都是以咨询师视角去监控会话的变化,涉及触发场景:

  • 主动加入群
  • 被邀请入群
  • 自动加群
  • 被移除群
  • 退群
  • 来新消息
  • 咨询师搜索群
  • 从客户查询进群
  • ...

以上场景都会在业务代码中触发热数据的更新(增加和减少)。
鉴于业务场景多点分布,为了尽可能少的影响现有架构,将复杂时间简单化

(一)初始化热数据表(chatmember-hot)
上线时,将冷数据表(chatmember)中近三个月的数据同步到热数据表(chatmember-hot)

(二)增量同步

  • 增加一个Job——syncColdToHotJob,定时同步过去1h内的增量数据增量同步到热数据表,执行频率1h
  • 增量同步,以热数据表最新的createtime

(三)超过三个月冷数据激活后的会话,快速同步到热数据表

  • 在chat表中增加,isActive(是否活跃),activeTime(激活时间)
  • 新消息入库接口,判断该消息的会话创建时间大于90天&&isActive=false,修改该会话的isActive=true
  • 增加一个Job——syncActiveChatJob,扫描近15min内激活的会话,然后同步其chatmember到热数据表
  • 数据同步到热库之后,isActive设置为false,避免重复同步


结语

在IM的大型实践中,有很多处理方案,比如,数据冷热分离、分库分表、本地数据库等方案。

在笔者目前群聊业务中,群数量100w左右,针对单库单表的优化,再加上一些高频数据做一下冷热分离还是可以坚持很长一段时间。

当然,随着业务的不断增加,后续还是会走上本地数据库之路。这里笔者只根据个人的工作经验,抛砖引玉,欢迎大家怕批评和斧正。

七 参考

版权声明: 本文为智客工坊「楠木大叔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。