分库分表真实案例,扩容10倍容量
数据存储我们一般采用MySQL,但是面对海量数据,单表在容量及性能上都无法支撑。这时我们要如何解决。
今天就给大家讲讲携程的分表业务是如何落地的。
一、背景
随着机票订单业务的不断增长,当前订单处理系统的架构已经不能满足日益增长的业务需求,系统性能捉襟见肘,主要体现在以下方面:
- 数据库CPU资源在业务高峰期经常达到50%以上,运行状况亮起了黄灯
- 磁盘存储空间严重不足,需要经常清理磁盘数据腾挪可用空间
- 系统扩容能力不足,如果需要提升处理能力只能更换配置更好的硬件资源
因此我们迫切需要调整和优化机票订单数据库的架构,从而提升订单系统的处理性能。通过建立良好的水平扩展能力,来满足日益增长的业务需求,为后续系统优化和支撑10x订单量的增长打下良好基础。
1.1 存储架构的演进
我们选择一个新的系统架构,应该基于当下面临的问题,综合成本、风险、收益等多方面因素,选择出的最合适的方案。机票订单库的架构演进也不例外。
我们最开始接触机票订单数据库时,它是一个非常庞大的数据集合,所有的订单业务全部都集中一个数据库上,因此整体BR非常高。同时,我们的SQL语句也非常复杂,混杂着很多历史遗留下来的存储过程。可想而之,整个数据库当时的压力巨大,维护成本居高不下。DBA每天的工作也非常忙碌,想方设法降高频,解决慢SQL等线上问题。生产偶尔也会因为某些没有review的SQL导致数据库短暂的停止服务。
初期,我们采用了最常见的几种手段进行优化,包括:
- 索引优化
- 读写分离
- 降高频
虽然手段比较常规,通过一段时间的治理,订单库的稳定性也得到了一定的增强。总体实施成本较低,效果也是立竿见影的。
随着时间的推移和数据的积累,新的性能瓶颈逐渐显露。我们再次对系统进行了升级,对数据库架构做了改进。主要包括以下几个方面:
- 垂直拆分
基于业务对数据库进行垂直拆分在很大程度上提高了系统的可靠性和可维护性。一个上百人的团队,同时对一套数据库进行维护,对于发布变更来说是一种煎熬,同时也存在很大的风险。当一个非核心链路上的发布出现了问题,例如某些操作导致了锁表或者占用过多的系统资源,其他关键链路的数据库访问都会因此受到影响。
我们根据不同的业务场景,例如:订单管理系统、出票、退票、改签等业务,将数据库进行垂直拆分。使各自业务系统数据隔离,减少相互的影响。这些拆分的数据库,可以根据不同性能要求,灵活调整数据库的部署方式,来降低总体成本。
- 水平拆分(冷热数据分离)
通常来说,当航班过了起飞时间并且用户已经使用了当前机票,那么我们认为该订单服务已经完成,后续订单数据发生改变的可能性很小,于是会将该数据迁移到一个具有相同结构的冷数据库中。该数据库仅提供查询功能,不提供修改功能。但是我们发现少数场景仍然需要对这些数据进行修改。于是我们开发了一套数据还原功能,将处于冷数据库中的数据,还原到热数据库中,然后再进行操作。
注:我们当时采用的数据库和数据结构是完全一致的,这样做备份和还原、查询会比较方便。其实也可以采用其他类型的数据库,例如Mongo等。在读取性能和使用成本等方面可能会更具优势。
这次升级同样解决了不少问题,使数据库的稳定性得到了很大的增强。
1.2 基于冷热数据分离的适用性
虽然基于冷热数据的分库方案,在目前来看遇到了瓶颈。但是我认为它是一个非常值得借鉴的方案。我们现在仍然有大量的业务系统数据库采用这种方案对数据进行拆分。它不仅实施简单,同时运维成本也相对较低。
优势:
- 功能简单
- 实施成本低
局限性:
- 数据冷处理的规则应该相对简单,不应该经常发生变化
- 热数据的膨胀需要受到限制,否则热数据的量一旦累积过多,性能瓶颈仍然会出现
- 需要额外的查询来找到订单所处的位置(冷/热数据库)
- 因为冷数据量庞大,冷数据的查询能力、表结构调整能力都收到了限制,不能进行复杂的业务查询操作
根据我们的系统规划,在当下或者可预见的未来满足以上提到原因中的多个,那么就得谨慎选择采用此方案。或者在改方案的基础上进行优化。
正是由于我们目前的业务场景恰好命中了上面列举的所有问题,我们才需要对这个架构进行进一步调整,选择一个更好的水平扩展的方式,解决当前系统面临的问题。
1.3 当时面临的主要问题
从2019年开始,我们就开始着手研究和规划订单数据库sharding项目。当时主要面临如下问题:
1.3.1 订单的存储要求
受制于当前订单数据库架构的限制以及机票业务的特殊性(通常不超过2年的处理生命周期),改造前的订单数据库仅能够支持2年的订单存储。超过2年,我们会将数据进行归档。用户和员工都无法通过在线查询的方式获取订单信息。
但是基于以下几个方面原因,原本2年的存储和处理周期已经不能满足客户和业务的需要:
1) 从客户的角度出发,仍然有查询历史订单的需求;
2) 业务场景的拓展导致机票订单整个服务周期变长;
原先机票使用完成(出行)一段时间后就可以视为服务结束,大部分订单3个月后就不会发生变化,但是由于新业务的推出,热点数据查询和处理周期明显变长。
1.3.2 系统架构瓶颈
1)热数据膨胀
热数据原本仅千万级别,由于业务的变化热数据数量不断膨胀。
2)冷数据量庞大
由于订单存储周期拉长和订单量的增长,冷数据的数量也不断攀升。冷数据库查询性能不断下降;索引调整也变得非常困难,经常出现修改失败的场景。
3)数据库高峰期BR达到了10w+;
4)系统存储了20TB的数据,磁盘使用率达到80%以上,经常触发使用容量告警;
5)主库的CPU使用率高峰期接近50%;
6)由于采用了读写分离的架构,当主库的服务器的性能受到影响的时候,AG延迟变得非常高,偶尔达到分钟级,有的时候甚至更长。
主从同步的延迟,导致了数据新鲜度的降低。我们之前的ORM层封装了一个新鲜容忍度的参数。当不能满足新鲜度要求的时候,读取会切换到主库,从而进一步加重了主库的负担。
因此,订单库的整体性能压力非常大,如果想快速解决性能问题,只能对机器进行扩容。但是由于数据库本身就是消耗资源大户,CPU和内存消耗非常高,只能通过进一步提高数据库的硬件配置来解决问题,因此整体升级的成本居高不下。另外硬件升级完成后,SQLServer 的授权成本可能也会进一步提升。
为了彻底解决以上问题,我们计划通过优化架构来提升系统的水平扩展能力,从而进一步提升我们系统的性能和服务水平。
二、项目目标和实施方**案**
2.1 目标
基于上文提到的这些问题,为了确保系统能够长久持续的稳定运行并且提升订单系统的处理能力,我们计划对数据库的架构进行升级,总体实现以下目标:
- 订单的存储和处理周期至少达到5年
- 提升订单系统的处理能力,支撑订单 QPS10 倍的规模增长
- 在提升系统性能的前提下,降低总体成本
- 提高系统的水平扩展能力,通过简便的操作可以快速扩容以应对长期的业务增长
我们希望通过1-2年的时间,实现对数据库架构升级改造以及完成SQLServer迁移到MySQL的目标。
2.2 架构改造
2.2.1 新旧架构的对比
旧系统架构:
架构说明:
1)订单数据库
为热数据的主库,提供读写功能
2)订单数据库 Slave
为热数据的从库,在保障新鲜度的前提下提
还没有评论,来说两句吧...