导航
- 基本目标
- 痛点
- 性能痛点
- 业务痛点
- 场景梳理
- 什么是冷热分离
- 冷热分离思路
- 热数据的存储
- 结语
- 参考
一 基本目标
提升系统稳定性,最大限度减少数据库压力。
二 痛点
性能痛点
- 群列表查询高频&耗时
- 单库单表,抗风险能力低
- 死锁
- 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左右,针对单库单表的优化,再加上一些高频数据做一下冷热分离还是可以坚持很长一段时间。
当然,随着业务的不断增加,后续还是会走上本地数据库之路。这里笔者只根据个人的工作经验,抛砖引玉,欢迎大家怕批评和斧正。
