数据冷热分离+归档-亿级表优化
背景
好久没有写文章了,因为特别忙也没有好的技术点给大家分享,索性暂时不写了。最近,在梳理系统的性能问题,尤其是营销自动化系统,数据体量越来越大了(8亿+,中途也在人工不断清理数据)。前期做的一系列优化,从监控来看慢sql也在增加,如果持续增加到某一个点肯定会影响客户使用,所以打算对大表进行一次优化(主要是做冷热分离+归档)。
方案演进回顾
我个人对营销自动化系统方向评估,这次改造后系统架构已经演化七七八八了未来很难再有大的动作(指架构上的调整),除非业务有大的的调整(基本不可能)。所以,利用这次机会回顾整个"营销自动化系统"迭代过程中我们是怎么演进系统的。
架构设计有几个原则:
-
简单原则,不要用复杂的方案解决简单问题。比如:大部分场景缓存先更新数据库同步删缓存,你非要采集数据库日志投递kafka再启消费者消费事件再删缓存,这个方案太过于复杂了没有必要;
-
适合原则,适合自身团队的是最好的,如果因为觉得有些技术牛逼就引入进来,反而造成系统复杂度高;
-
持续演进,架构都是持续演进的,并不是一切开始就能设计出来,如果你不知道业务未来什么样,多少客户用,不可能设计出来完美的架构,另外再设计方案的时候参考下竞品,满足未来1-2年内的扩展就可以了。
下面聊聊初期到业务趋于稳定期的架构演进我们做了啥吧。
初期
初期业务优先,保证业务上线验证业务的价值,我们也做了系分设计但是考虑并不完善,回顾第一版和最后这版的架构差异挺大的。前期架构的设计原则是简单优于复杂,适合优于先进先让业务跑起来,考虑不完善也没有关系未来迭代再演进。所以公司有什么用什么,存储都考虑单表也没有考虑缓存,SQL 调优也没有时间做。当时产研团队50人左右说搞就搞,中途为了赶进度我还把大家拉到会议室面对面闭关开发(2周),最终项目上线。上线后业务需求暴多,数据体量还没有那么大,短期没有暴露问题,是有时间给大家缓冲的,这里也说明一个问题,系统刚上线很难爆炸式增长的。
业务增长期
上线一段时间业务推广,产品直播等功能渗透率直线增长很快扛不住了。主要是体现在数据量大、数据库读写qps高、有些统计能力sql复杂、索引问题等。这批问题急需解决,但是业务需求多不可能等优化完了再开发业务需求。这时候两条腿走路,边优化边开发需求按周优化性能,需求迭代正常排期,一次大迭代也会夹带一些性能优化技改。
业务增长期需求特别多,尽量避免大的架构调整,我们只做了下面的调整
1、 SQL调优,参考下面两篇文章主要讲SQL的优化;
亿级表优化思路之 SQL 篇,值得收藏为啥会写亿级表优化?网上谈的不少但是不知道大伙儿是否在自己 Owner 的业务中验 - 掘金
SQL 调优最佳实践 「值得收藏」什么是 SQL 调优?是不是觉得自己知道但又很模糊说不清楚,面试被问没有真实的案例,并 - 掘金
上亿表查询、大批量数据更新优化「值得收藏」反范式设计,适当冗余字段,简化 SQL 复杂度,提升查询效率; 大批量数据更新 - 掘金
2、 加缓存,读多的场景统一加缓存,到后期缓存每天给我们扛了2-4kw的流量;
3、 提高单pod并发,主要是利用线程池提高业务处理能力;
SQL 优化我写了3篇文章,所以并不是一遇到问题就上复杂的架构业务增长期你也忙不过来。采用28原则找到优化后最有效果的问题处理就可以了。
业务缓和期
熬过业务增长期,业务增长没有那么快了这时候你是有时间处理更复杂的问题的。业务增长缓慢但是数据体量可没减少,每日新增几百万行数据,单表性能也在逐步下降(当时2亿+)从SQL监控来看慢查询是持续增加的,经过对问题分析决定做一次数据库上的调整。
1、 分库分表,单表的读写性能明显降低了有了分区方案亿级表优化「TIDB 分区篇」,值得收藏这是亿级别表优化的第二篇,对第一篇感兴趣的可以看看。距上次写亿级别优化已经有一个 - 掘金;
2、 集群迁移,"营销自动化"数据库是TIDB,但TIDB是所有业务团队混用的有非常多业务在上面,"营销自动化"业务在高峰期时数据写入和读取流量非常大,再加上全平台业务都在跑,出现过几次稳定性问题。可以说上面的业务在相互影响,就看谁是压垮骆驼的最后一根稻草,因为"营销自动化"的特点就是数据体量大,QPS高每次受伤的都是它,有了集群迁移方案4亿表数据库集群迁移方案实践大体量数据(4亿级数据表)、高QPS业务数据库集群迁移最佳实践,不停机、支持回滚、保障数据一 - 掘金;
业务稳定期
近期,业务非常稳定了需求少了、架构上也没有需要大调的点。但某张表数据已经达到8亿+,然后前期做了分库分表、做了SQL优化、加了缓存,但这些并不是银弹能解决所有问题,比如:查询复杂场景缓存无法解决;数据体量巨大,SQL尽管优化的很好也没办法减少扫描行数;引出了下一阶段的优化思路"冷热表"+"数据归档"。
"冷热表"+"数据归档"
名词解释
1、 热表:存储当前活跃、频繁访问的数据的表。它通常包含最近的、需要快速查询和实时更新的数据,适用于需要高性能、高吞吐量的场景。热表的数据通常是正在执行的操作、活跃的事务、用户请求等。
2、 冷表:冷表的主要目的是将不常被访问的数据从热表中分离出来,以提高数据库的性能和响应速度。冷表数据仍然属于业务的一部分,可能是较长时间内没有频繁更新的数据,但偶尔仍会被查询;
3、 归档表:归档表则是针对已经不再活跃、完全过时的数据,通常是历史数据,目的是将这些数据迁移到独立的存储区域,以减轻主数据库的负担。归档表的数据可能长期不再被访问,但由于合规、备份或历史查询等原因,依然需要保留。
热表、冷表、归档表数据划分规则
名词解释清楚后,接下来看看三个表的划分规则,切记、切记、切记,这个跟业务息息相关,跟客户、产品提前沟通清楚是否是业务容忍范围。大部分是按照下面几个规则切割吧。
-
时间纬度,比如180天前的数据作为切割边界,180前的数据切割到冷表;
-
状态机,有些业务是有状态的,按照业务状态切割将完成、废弃状态切割到冷表;
-
访问频率,将高频访问的数据视为热数据,低频访问的数据视为冷数据切割到冷表。例如,内容系统可以将浏览量非常低的文章作为冷数据,浏览量较高的文章作为热数据;
-
按接口划分,特定接口走冷表,可扩展性低。
那归档表呢?已经删除数据、流失租户/客户数据、产品定义n年前的数据,这批数据放到归档表后不提供业务测查询了。
数据迁移方案
冷热表、归档表规则划分好了之后,按照规则进行数据迁移即可。但是数据迁移又是一大问题,热表-->冷表-->归档表,数据从热表到冷表再到归档表的迁移,最简单的来看,需要实现 2 个步骤:
-
数据查询并写入下一个存储;
-
上一个存储的数据删除。
我提供几个方案
方案一:
执行一个job,定时每天凌晨「业务低峰期」开始自动迁移,每次迁移若干条,这样就会在不知不觉中将数据迁移完。
方案二:
业务上双写,冷表和热表都写,启动定时任务清理数据即可,冷库就是全量数据,数据准确性高。
方案三:
可以通过ETL工具实时采集openlog同步到冷库,启动定时任务清理热数据即可,冷库就是全量数据
我分析下方案优缺点:
方案一:某一时间点对数据库的压力会比较大,而且搬移周期长,按照我以往的经验这个方案不靠谱至少我不会用;方案二:业务双写代码复杂,耦合严重,并且性能不高;方案三:对业务无感通过oplog同步即可,也有缺点掉数据恢复困难。
数据查询路由规则
同一个业务数据被拆分到多个表,多数据源的查询是难题,冷库和热库对应着不同的业务表,流量穿透到后端服务需要知道查询具体的业务表,应该有一个映射规则吧,比如:某一些时间段的查询走冷表,有一状态机的查询走热表等。这些都没有办法写到中间件的只能写到业务代码,另外每个业务的冷热表规则不一样,都要写一个规则。大家可以思考下有木有其他方案?
提前告知:我们系统的"冷表"是全量数据哈,所以我们没有在代码中做复杂的路由规则。
"营销自动化系统"冷热数据+归档方案
方案1:根据任务时间
描述 | 超过180天数据定义为冷数据,从热表删除写入冷表 |
---|---|
改动 | 新增清理机制「预计复杂度🌟」 |
影响范围 | -- |
风险 | -- |
预计优化 | 预计清理数据约52.5% |
方案2:按照状态机
描述 | 已结束"营销自动化"任务定义为冷数据,从热表删除写入冷表 |
---|---|
改动 | 新增清理机制,新增路由规则「预计复杂度🌟🌟🌟🌟」 |
影响范围 | 较广,查询/更新接口改造 |
风险 | 存在部分边界场景 |
预计优化 | 预计清理数据约60.8% |
方案3:按照任务状态
描述 | 达到终态"营销自动化"任务,定义为冷数据,从热表删除写入冷表 |
---|---|
改动 | 新增清理机制「预计复杂度🌟🌟🌟」 |
影响范围 | 较广,更新接口埋点,或者监听更新事件 |
风险 | 存在部分边界场景 |
预计优化 | 预计清理数据约84.4% |
我们给产品提供了3种解决方案,时间纬度和状态机。最终选择了方案一和方案二集合使用,主要原因是客户好理解、开发简单、清理效果也非常明显。
友情提示,规则可以根据业务场景调整的,我们将某一个场景的时间调整成清理90天前的数据。
再看"营销自动化系统"冷表、热表、归档表的范围
热表:180天内数据,某些场景只保留90天数据;
冷表:全量数据(归档数据会删除),这里会跟大家理解的可能有差异,后文会讲为啥是全量数据;
归档表:已删除、流失租户/客户等数据。
好了,写完清理规则后,聊聊业务场景方便对冷表、热表、归档表的理解
"营销自动化系统"业务上分为管理端能力和员工端能力,请记住"员工端"读写频率高,SQL复杂;"管理端"读写频率低,SQL相对简单。根据此特点我们把"员工端"能力划分到热表,"管理端"能力查询划分到冷表,如下图。
冷表是"全量数据"哈,各位认知里的冷表应该是从热表删除的那部分数据。为什么这样设计?
- 避免在某一时刻集中查询热表写入冷表,再删除热表操作,定时器只需要删除热表数据即可,逻辑简单;
- 给业务测便利,"管理端"能力是查询全量数据,如果冷表有全量数据查询简单方便,不用开发复杂的数据表路由规则。
如果冷表的数据体量大到无法容忍的地步,可以逐步清理冷表的数据,如果产品能接受直接清理数据不给用户查询和访问直接删除是可以的。如果不能接受只有启动定时任务讲数据查出来后写入成本更低的存储即可。
这时候可以用方案一啦:执行一个job,定时每天凌晨「业务低峰期」开始自动迁移。
结尾
请记住架构设计3原则。。。。。