文档参考:书名:《从程序员到架构师:大数据量、缓存、高并发、微服务、多团队协同等核心场景实战》-王伟杰
1.冷热分离概述
1.1 业务场景
首先介绍一下业务场景。
1.1 业务场景:
几千万数据量的工单表如何快速优化 这次项目优化的是一个邮件客服系统。它是一个SaaS(通过网络提供软件服务)系统,但是大客户只有两三家,最主要的客户是一家大型媒体集团。
这个系统的主要功能是这样的:它会对接客户的邮件服务器,自动收取发到几个特定客服邮箱的邮件,每收到一封客服邮件,就自动生成一个工单。之后系统就会根据一些规则将工单分派给不同的客服专员处理。
这个系统是支持多租户的,每个租户使用自己的数据库(MySQL)。
这家媒体集团客户两年多产生了近2000万的工单,工单的操作记录近1亿。
平时客服在工单页面操作时,打开或者刷新工单列表需要10秒钟左右。
该客户当时做了一个业务上的变更,增加了几个客服邮箱,然后把原来不进入邮件客服系统的一些客户邮件的接收人改为这几个新增加的客服邮箱,并接入这个系统。
发生这个业务变更以后,工单数量急剧增长,工单列表打开的速度越来越慢,后来客服的负责人发了封邮件,言辞急切,要求尽快改善性能。
项目组收到邮件后,详细分析了一下当时的数据状况,情况如下。
- 工单表已经达到3000万条数据。
- 工单表的处理记录表达到1.5亿条数据。
- 工单表每日以10万的数据量在增长。
当时系统性能已经严重影响了客服的处理效率,需要放在第一优先级解决。本次选用的冷热分离方案做的优化。
1.2 冷热分离简介
1.2.1 什么是冷热分离
冷热分离就是在处理数据时将数据库分成冷库和热库,冷库存放那些走到终态、不常使用的数据,热库存放还需要修改、经常使用的数据。冷热分离,简单来说,就是将常用的“热”数据和不常使用的“冷”数据分开存储。
1.2.2 什么情况下使用冷热分离
假设业务需求出现了以下情况,就可以考虑使用冷热分离的解决方案。
- 数据走到终态后只有读没有写的需求,比如订单完结状态。
- 用户能接受新旧数据分开查询,比如有些电商网站默认只让查询3个月内的订单,如果要查询3个月前的订单,还需要访问其他的页面。
1.3 MySQL用冷热数据
1.3.1 问题
在冷热分离实际操作过程中,需要考虑以下问题。
- 如何判断一个数据是冷数据还是热数据?
- 如何触发冷热数据分离?
- 如何实现冷热数据分离?
- 如何使用冷热数据?
- 历史数据如何迁移? 接下来针对以上5个问题进行详细讲解。
1.3.2 如何判断一个数据到底是冷数据还是热数据
一般而言,在判断一个数据到底是冷数据还是热数据时,主要采用主表里一个字段或多个字段的组合作为区分标识。
这个字段可以是时间维度,比如“下单时间”,可以把3个月前的订单数据当作冷数据,3个月内的订单数据当作热数据。
当然,这个字段也可以是状态维度,比如根据“订单状态”字段来区分,将已完结的订单当作冷数据,未完结的订单当作热数据。
而在实际工作中,最终使用哪种字段来判断,还是需要根据实际业务来决定的。
关于判断冷热数据的逻辑,这里还有两个要点必须说明。
- 如果一个数据被标识为冷数据,业务代码不会再对它进行写操作。
- 不会同时存在读取冷、热数据的需求。
回到项目场景,这里就把lastProcessTime大于1个月,并且status为“关闭”的工单数据标识为冷数据。
1.3.3 如何触发冷热数据分离
了解冷热数据的判断逻辑后,就要开始考虑如何触发冷热数据分离了。一般来说,冷热数据分离的触发逻辑分为3种。
1)直接修改业务代码,使得每次修改数据时触发冷热分离(比如每次更新订单的状态时,就去触发这个逻辑),如图所示。
2)如果不想修改原来的业务代码,可以通过监听数据库变更日志binlog的方式来触发(比如:canal)。具体方法就是另外创建一个服务,这个服务专门用来监控数据库的binlog,一旦发现ticket表有变动,就将变动的工单数据发送到一个队列,这个队列的订阅者将会取出变动的工单,触发冷热分离逻辑,如图所示。
3)通过定时扫描数据库的方式来触发。 这个方式就是通过quartz配置一个本地定时任务,或者通过类似于xxl-job的分布式调度平台配置一个定时任务。这个定时任务每隔一段时间就扫描一次热数据库里面的工单表,找出符合冷数据标准的工单数据,进行冷热分离,如图所示。
以上3种触发逻辑到底选哪种比较好?下面给出它们各自的优缺点,如图所示。
根据以上对比,可以得出每种触发逻辑的建议场景。
1.修改写操作的业务代码建议在业务代码比较简单,并且不按照时间区分冷热数据时使用。
场景示例:假设是根据订单的状态来区分冷热数据,订单的状态不会随着时间自动变化,必须有人去修改才会触发变化,并且很容易找出所有修改订单状态的业务代码,这种情况下可以用这种触发逻辑。
2.监听数据库变更日志建议在业务代码比较复杂,不能随意变更,并且不按时间区分冷热数据时使用。
示例场景:跟上一场景类似:假设是根据订单的状态来区分冷热数据,订单的状态不会随着时间自动变化,必须有人去修改才会变化。其不一样的地方在于,业务代码很复杂,特别是有些用了很多年的系统中,修改订单状态的代码分布在多个位置,甚至多个服务中,不可能都找到,并且因为难以评估影响面,所以修改起来风险很大。这种情况下就适合使用监听数据库变更日志的方式。
3.定时扫描数据库建议在按照时间区分冷热数据时使用。
示例场景:就是这个项目中的业务场景。这里的业务需求是已经关闭超过1个月的工单视为冷数据,这种场景下,工单变更的那一瞬间,即使工单已经关闭了,也不能将其视为冷数据,而必须再等待1个月。这样的情况非常适合使用定时扫描。所以这一次,项目组就选用了定时扫描数据库的触发方式。但是对于不同项目自身的场景,到底选择哪种触发方式,还是需要根据具体业务需求来决定。
当决定了冷热分离的触发方式后,就进入下一个决策点:如何分离冷热数据。因为篇幅和时间问题,明天继续。