存储成本降低85%,携程历史库场景的降本实践

news2025/4/11 1:40:46

携程,一家中国领先的在线票务服务公司,从 1999 年创立至今,数据库系统历经三次替换。在移动互联网时代,面对云计算卷积而来的海量数据,携程通过新的数据库方案实现存储成本降低 85% 左右,性能提升数倍。本文讲述携程在历史库场景下,如何解决水平扩容、存储成本、导入性能等痛点,以及对于解决方案的制定和思考过程。

自创立之初,携程前期业务以使用 SQL Server 数据库为主。在 MySQL 传入国内并大行其道时,携程也在 2016-2018 年将数据库逐步从 SQL Server 转到 MySQL 数据库。但是,随着技术多元化及业务的不断发展,MySQL 逐渐显露瓶颈,如扩容工艺复杂、数据存储成本高、表相关维护操作耗时等,如今已无法满足携程需求。

因此,携程在生产环境数据量过大时,尝试将生产环境中业务访问极少的冷数据归档到历史库,以减少生产环境中的数据量,降低生产环境中的查询时延、表结构变更时延等关键性能指标。

最初,携程使用 MyRocks( RocksDB for MySQL )作为历史库,只因其兼容 MySQL 主从架构,且自带压缩,对成本节约友好。如下图所示,今年上半年国内、国外机票预定量倍增,订单量相应增加,但随着业务数据量的激增, MyRocks 扩容难的问题暴露了出来。由于 MyRocks 无法适应如此快速的数据增长,携程需要再次考虑历史库选型,引入新的架构进行优化。

图片

图片

在历史库选型过程中,携程重点关注以下四个方面:

  • 水平扩缩容。所选数据库是否能够水平扩缩容、扩缩容后是否方便进行负载均衡;

  • 迁移便捷度。是否方便数据迁移;

  • 降本。是否有足够低的存储成本;

  • 增效。数据写入历史库的性能是否能达到要求。

基于上一次的历史库选型经验和产品调研,此次携程决定对完全自研且开源的分布式数据库 OceanBase 进行初步考察。除了高度兼容 MySQL 外,OceanBase 还具备透明水平扩展、高可靠、数据压缩能力强等特点。于是,携程根据业务场景对 OceanBase 数据库做了进一步的调研和测试。

如下图所示,携程对 MySQL 业务迁移至 OceanBase 的容量进行了测试对比,依据压缩算法的原理,表对比压缩率与数据类型、重复度等密切相关,所以携程采用了整库迁移对比,希望更接近实际场景。结果显示,MySQL 容量 2.1TB,迁移到 OceanBase 后为 264GB,数据压缩比 8:1。

图片

空间对比:MySQL(蓝) vs OceanBase(橙)

此外,在测试过程中,携程也考察了 OceanBase 在水平扩缩容、迁移便捷度,以及性能方面的表现,最终决定应用 OceanBase,上线后,效果符合预期。

图片

一、水平扩缩容

携程最初使用 MySQL 作为归档历史库,当集群空间也达到上限时,采用了分库分表的解决方案。分库分表的方案在一定程度上带来了水平扩展的能力,降低了业务的系统性风险。

图片

与此同时,分库分表方案使携程历史库面临诸多问题。

  • 问题 1:在通过增加节点进行水平扩容时,需要  DBA 介入数据的迁移过程,利用人工完成数据的 rebalance。

  • 问题 2 :额外的数据管理负担和数据运算压力,在某些场景下,需要遍历每个 ShardDB,并执行相同语句获取结果。此时请求量会翻倍,一旦出现慢 SQL,容易导致进程堆积。

  • 问题 3:分库分表方案多种多样,如果开发人员设计不合理或使用不当,会出现数据分布不均的问题。

综合以上问题,我们在对历史库进行选型时,希望能够找到一款可以同时支持对业务无感的在线扩缩容、自动负载均衡及分布式事务的原生分布式数据库。

OceanBase 是原生分布式数据库,基于 Multi-Paxos 实现了分布式一致性协议,支持分布式事务;同时支持透明水平扩展,满足业务快速扩容缩容的需求,扩容后分区表的数据会自动均衡到新节点上,对上层业务透明,节省迁移成本。

在携程业务高速发展时,历史库的扩容操作对业务透明,这些特性完美地解决了携程历史库业务场景在最初使用分库分表策略时的各种痛点。

图片

携程历史库在使用 MySQL 分库分表方案时,将数据按照月、日进行分表,需要开发人员在发布系统上主动配置,应用代码需要进行改造。一旦容量告警,需要 DBA 人工介入,进行数据拆分。而在 OceanBase 中只需要创建以时间作为分区键的 range 分区表,OceanBase 会自动将分区表的多个分区均匀地分散在每个 Zone 的各台节点上。每台节点均可以独立执行 SQL,如果应用需要访问的数据在不同机器上,节点自动将请求路由至数据所在的机器,对业务完全透明。

图片

扩容时只需要在集群维度为其增加资源节点,通过修改租户资源规格的方式,可以将资源分配给指定租户,然后集群的 RootService 会调度分区副本在各 Zone 内部进行迁移,直到各节点的负载差值小于用户配置的阈值。各个分区主副本也会在每个节点上进行自动均衡,避免主副本的分配倾斜导致部分节点的请求负载过大。

二、数据迁移

在传统异构数据迁移方案中,通常有两种方式:一种是静态数据迁移,确保数据静态后,使用导出工具的方式进行迁移;另一种是需要开发人员在业务代码中进行双写。针对 MySQL 历史库的迁移,携程最终选择 OMS,进行数据迁移。

OMS(OceanBase Migration Service ,OceanBase 迁移服务)是一种支持同构或异构数据源与 OceanBase 之间进行数据交互的服务,具备在线迁移存量数据和实时同步增量数据的能力。OMS 支持了携程历史库的在线不停服迁移,整个迁移过程中,业务应用无感知。

图片

OMS 提供了可视化的集中管控平台,支持为数据迁移过程进行全生命周期的管理服务,在管控界面上即可完成对数据迁移和数据同步任务的创建、配置、监控和管理,交互简单方便。同时还提供了多种数据一致性校验方式,更加全面、省时、高效地保证数据质量。

图片

携程通过 OMS(OceanBase Migration Service)提供的不停服数据迁移功能,将现有的 MySQL 历史库通过 OMS 平滑迁移至 OceanBase,在迁移过程中没有进行业务上的改造。迁移过程中原 MySQL 历史库持续对外提供服务,将数据迁移对业务的影响最小化。

图片

三、存储成本

数据压缩是降低海量数据存储空间占用的关键手段。OceanBase 高压缩比的分布式存储引擎, 摒弃了传统数据库的定长数据块存储, 采用基于 LSM-Tree 的存储架构和自适应压缩技术,创造性地解决了传统数据库无法平衡“性能”和“压缩比”的难题。

OceanBase 支持 zlib、snappy、lz4 和 zstd 四种压缩算法。在通用压缩的基础上,OceanBase 自研了一套对数据库进行行列混存编码的压缩方法(encoding),使用行列的字典、差值、前缀等编码算法,在通用压缩算法之前对数据做了编码压缩,带来更大的压缩率,进一步降低存储成本。

存储层会根据数据特征自适应地选择最优的编码规则,合并时会计算数据的压缩比,如果发现压缩比不高,会尽快回退,选择其他的编码方式,从而确保数据编码的过程不会影响正常的数据写入性能。

OceanBase 在数据压缩方面的表现十分优秀,携程 MySQL 历史库中大小为 475G 的表,迁移到 OceanBase 后仅占 55G,平均存储资源仅为原来的 1/8,存储成本降低 85% 左右。

四、导入性能

携程历史库除了看重水平扩展性、存储成本等因素外,还对历史库的大量归档数据导入性能提出了较高要求。OceanBase 的并行执行框架能够将 DML 语句通过并发的方式进行执行( Parallel DML ),对于多节点的数据库,实现了多机并发写入,并且保证大事务的一致性。结合异步转储机制,还能在很大程度上优化 LSM-Tree 存储引擎在内存紧张的情况下对大事务的支持。

我们可以通过这样一个例子来体验 PDML:以 TPC-H 的 lineitem 表为基础,创建一张相同表结构的空表  lineitem2。然后以 INSERT INTO...SELECT 的方式,将 lineitem 的全部 600 万行数据插入新表 lineitem2 中。然后我们分别用关闭和开启 PDML 的方式执行,观察其效果和区别。

首先,复制 lineitem 的表结构,创建 lineitem2。需要注意的是,在 OceanBase 数据库中我们使用分区表进行数据扩展,此处的例子中我们使用 16 个分区,那么对应的 lineitem2 也应完全相同:

obclient [test]> SHOW CREATE TABLE lineitem;
CREATE TABLE `lineitem` (  `l_orderkey` bigint(20) NOT NULL,  `l_partkey` bigint(20) NOT NULL,  `l_suppkey` bigint(20) NOT NULL,  `l_linenumber` bigint(20) NOT NULL,  `l_quantity` bigint(20) NOT NULL,  `l_extendedprice` bigint(20) NOT NULL,  `l_discount` bigint(20) NOT NULL,  `l_tax` bigint(20) NOT NULL,  `l_returnflag` char(1) DEFAULT NULL,  `l_linestatus` char(1) DEFAULT NULL,  `l_shipdate` date NOT NULL,  `l_commitdate` date DEFAULT NULL,  `l_receiptdate` date DEFAULT NULL,  `l_shipinstruct` char(25) DEFAULT NULL,  `l_shipmode` char(10) DEFAULT NULL,  `l_comment` varchar(44) DEFAULT NULL,  PRIMARY KEY (`l_orderkey`, `l_linenumber`),  KEY `I_L_ORDERKEY` (`l_orderkey`) BLOCK_SIZE 16384 LOCAL,  KEY `I_L_SHIPDATE` (`l_shipdate`) BLOCK_SIZE 16384 LOCAL) partition by key(l_orderkey)  (partition p0,   partition p1,   partition p2,   partition p3,   partition p4,   partition p5,   partition p6,   partition p7,   partition p8,   partition p9,   partition p10,   partition p11,   partition p12,   partition p13,   partition p14,   partition p15);

在不开启 PDML 的情况下,创建好 lineitem2 后,我们先以默认配置不开启并行的方式插入, 因为这是一个 600 万行的大事务,我们需要将 OceanBase 数据库默认的事务超时时间调整到更大的值(单位为 μs):

​​​​​​​

obclient [test]> INSERT INTO lineitem2 SELECT * FROM lineitem;Query OK, 6001215 rows affected (1 min 47.312 sec)Records: 6001215  Duplicates: 0  Warnings: 0

可以看到,不开启并行的情况下,单个事务插入 600 万行数据,OceanBase 的耗时为 107 秒。

下面我们通过添加一个 Hint,开启 PDML 的执行选项。再次插入前,我们先将上次插入的数据清空。来看这次的执行耗时:

​​​​​​​​​​​​​​

obclient [test]> TRUNCATE TABLE lineitem2;Query OK, 0 rows affected (0.108 sec)
obclient [test]> INSERT /*+ parallel(16) enable_parallel_dml */ INTO lineitem2 SELECT * FROM lineitem;Query OK, 6001215 rows affected (22.117 sec)Records: 6001215  Duplicates: 0  Warnings: 0

可以看到开启 PDML 后,相同的表插入 600 万行数据,OceanBase 数据库的耗时缩短为 22 秒左右。PDML 特性带来的性能提升大约为 5 倍,数据写入性能远超 MySQL,并发 DML 这一特性支撑了携程批量归档数据快速导入历史库的需求。

图片

总的来说,到目前为止,携程已经把众多核心业务迁移到 OceanBase 数据库。携程历史库场景经过 OceanBase 替换 MySQL 的实践后,取得了以下四点主要收益。

第一,无缝 scale-in or out:使用普通的 PC 服务器即可构建超高吞吐的 OceanBase 集群,无需分库分表,快速按需扩展,并为携程历史库在水平扩展过程中提供了平滑的成本增长曲线。

第二,数据迁移对业务透明:OMS 支持全量数据迁移、增量数据同步,支持主流数据库的一站式数据迁移,高效地完成了携程历史库数据到 OceanBase 的迁移。

第三,降低存储成本 85% 左右:基于 OceanBase 的高级压缩技术,在保证性能的同时,数据存储空间节约近 85%。同等硬件投入的前提下,OceanBase 支持携程历史库存储更多数据。

第四,数据写入性能优秀:OceanBase 的无共享架构、分区级主副本打散,以及并行执行框架提供的 Parallel DML 能力,真正实现了高效的多节点写入。利用该特性,数据写入性能提升了数倍,能够从容应对携程历史库的超高并发数据写入需求。

目前,携程使用的是 OceanBase 3.x 版本,未来将逐步升级至 4.x 版本,以获得更好的性能和写入效率。此外,OceanBase 4.x 高度兼容 MySQL 8.0,并支持租户级别的物理备份,这将有利于携程做数据的离线备份,以及能够更快地恢复备份。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/966751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TensorRT来加速YOLO v5推理与检测

TensorRT来加速YOLO v5推理与检测 文章目录 TensorRT来加速YOLO v5推理与检测TensorRT简介一、TensorRT安装1. 电脑基础环境2. 查看 cuda 版本3. 安装TensorRT4. 验证TensorRT 二、YOLO v5模型导出函数1.onnx 模型导出(def export_onnx()函数…

nmon性能监控工具介绍【杭州多测师_王sir】

nmon监控工具 (nmon监控centos6X)1) 工具准备nmon16X(性能监控)和nmon_analyser(性能报告分析器);2) 下载nmon页面地址:http://nmon.sourceforge.net/pmwiki.php?nSite.Download3) 下载指定版本nmon到centos6X:wget https://nchc.dl.sourceforge.net/project/nmon…

HTTP协议初识·中篇

加上目录,会出现导向不正确的情况,可能是bug,目录一长就容易出错? 本篇主要讲解了: 网页分离(网页代码和.c文件分离) html链接跳转 网页添加图片 确认并返回资源类型 填写正文长度属性 添加表单 临时重定向 补充知识&a…

04. 函数和函数调用机制

1. 先学习/复习C语言的入门知识 1.1 C语言简介 C语言是一种通用的编程语言,于1972年由丹尼斯里奇(Dennis Ritchie)创建。C语言最初目的是为了开发UNIX操作系统,但由于其简洁的语法、快速的执行速度和可移植性,自此成…

Linux系统中驱动入门设备树DTS(经典)

设备树(DTS:device tree source),字面意思就是一块电路板上设备如上图中CPU、DDR、I2C、GPIO、SPI等,按照树形结构描绘成的一棵树。按照策略和功能分离的思路,就是驱动代码(功能)和设备树DTS配置…

算法通关村16关 | 滑动窗口如此简单

1. 滑动窗口基本思想 滑动窗口就是快慢指针问题,快指针走一步,慢指针走一步,维护窗口的大小。 下图有大小为3的滑动窗口移动示例。 窗口:窗口是left和right之间的元素,也可以理解为一个区间。窗口的大小可能固定&#…

Win7设备和打印机里空白,0个对象,但是可以打印的处理办法

呉師傅 你是不是遇到过Win7系统打开设备和打印机的时候显示是空白的,0个设备的情况?要怎么操作才能解决这一问题呢,下面就分享一下如何处理这个问题的小方法大家可以尝试一下。 问题如下: 解决方法: 1、点击桌面左下…

Unity中Shader的消融视觉效果优化smoothstep(min,max,x)

文章目录 前言Unity中Shader的消融视觉效果优化 一、在clip(value) 的 基础上 用 smoothstep(min,max,x),并且增加一个渐变纹理对消融边缘进行视觉上的优化二、进行优化 前言 Unity中Shader的消融视觉效果优化 一、在clip(value) 的 基础上 用 smoothstep(min,max…

3.0 Dubbo的可扩展机制SPI源码解析

1. Dubbo SPI 架构图 2. Demo ExtensionLoader<Protocol> extensionLoader ExtensionLoader.getExt ensionLoader(Protocol.class); Protocol http extensionLoader.getExtension("dubbo"); System.out.println(http); 上⾯这个Demo就是Dubbo常⻅的写法&am…

java八股文面试[多线程]——newWorkStealingPool

newWorkStealingPool是什么&#xff1f; newWorkStealingPool简单翻译是任务窃取线程池。 newWorkStealingPool 是Java8添加的线程池。和别的4种不同&#xff0c;它用的是ForkJoinPool。 使用ForkJoinPool的好处是&#xff0c;把1个任务拆分成多个“小任务”&#xff0c;把这…

【MySQL学习笔记】(七)内置函数

内置函数 日期函数示例案例-1案例-2 字符串函数示例 数学函数其他函数 日期函数 示例 获得当前年月日 mysql> select current_date(); ---------------- | current_date() | ---------------- | 2023-09-03 | ---------------- 1 row in set (0.00 sec)获得当前时分秒…

剑指 Offer 57 - II. 和为s的连续正数序列(简单)

题目&#xff1a; class Solution { public:vector<vector<int>> findContinuousSequence(int target) { //本题使用滑动窗口&#xff08;双指针&#xff09;int i1, j1; //定义左右边界&#xff0c;一般是左闭右开int sum0; //窗口内的和vector&…

区块链技术与应用 - 学习笔记1【引言】

大家好&#xff0c;我是比特桃。本系列主要将我之前学习区块链技术时所做的笔记&#xff0c;进行统一的优化及整合。其中大量笔记源于视频课程&#xff1a;北京大学肖臻老师《区块链技术与应用》公开课。肖老师的课让我找回了求知若渴般的感觉&#xff0c;非常享受学习这门课的…

2023/9/3周报

目录 摘要 文献阅读1 1、标题和提出问题 2、物理模型对于水质预测的缺陷 3、模型框架 4、相关公式 5、结果分析 文献阅读2 1、标题和提出问题 2、问题叙述 3、模型框架 4、误差修补 5、实验结果和分析 总结 摘要 本周阅读了2篇论文&#xff0c;分别为一种基于深…

ReactNative 井字游戏 实战

效果展示 需要的插件准备 此实战项目需要用到两个插件。 react-native-snackbar 底部信息提示组件。 react-native-vector-icons 图标组件。 安装组件&#xff1a; npm i react-native-snackbar npm i react-native-vector-icons npm i types/react-native-vector-icons /…

uni-app之android离线自定义基座

一 为什么要自定义基座 1&#xff0c;基座其实就是一个app&#xff0c;然后新开发的页面可以直接在手机上面显示&#xff0c;查看效果。 2&#xff0c;默认的基座就是uniapp帮我们打包好的基座app&#xff0c;然后我们可以进行页面的调试。 3&#xff0c;自定义基座主要用来…

Python:列表推导式

相关阅读 Python专栏https://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 列表推导式使得创建特定列表的方式更简洁。常见的用法为&#xff0c;对序列或可迭代对象中的每个元素应用某种操作&#xff0c;用生成的结果创建新的列表&#xff…

VSC++: 奇怪的风吹

void 奇怪的风吹() {//缘由https://ask.csdn.net/questions/1062454int aa[]{15, 30, 12, 36, 11, 20, 19, 17, 16, 18, 38, 15, 30, 12, 36, 11, 20, 19, 17, 16, 18, 38, -1},j 0, a 0, y 0, z 0;while (aa[j] > 0){if (j && aa[j] > 35 || aa[j] < 15)…

CXL.cache D2H Message 释义

&#x1f525;点击查看精选 CXL 系列文章&#x1f525; &#x1f525;点击进入【芯片设计验证】社区&#xff0c;查看更多精彩内容&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c…

记录一下自己对linux分区挂载的理解

一直狠模糊&#xff0c;分两个区&#xff0c;一个挂载/, 一个挂载/home 两者是什么关系 实测 先看挂载的内容 然后umount /home后创建一个新文件 再挂载回去 发现旧分区又回来了&#xff0c;说明路径只是个抽象的概念&#xff0c;分区挂载&#xff0c;互相之间数据是不影响…