企业背景
iCC Grow是一家致力于为品牌方实现全方位业务增长的SaaS服务提供商。公司业务遍布全球,截至目前,iCC Grow业务覆盖餐饮80%头部品牌、美妆、鞋服、汽车、电商、奢侈品等行业。服务门店超60万家,辐射用户总数突破3个亿。通过构建包括组织变革管理、客户获取、客户运营、群聊运营SCRM和智能标签在内的整合系统,致力于推动品牌客户沟通的全面数字化。目标是帮助品牌方解决客户获取效率低、客户运营效率低、客户资产流失等问题,同时提高品牌、客户、合作伙伴之间的高效沟通。
业务痛点
随着业务的扩展和业务数据量的不断增长,我们部分业务表的大小已经超过了 700GB,行数也达到了上亿行的规模。使用 MySQL 分库分表的方案,不仅需要依赖第三方工具,而且数据读写都比较复杂。传统单机数据库 MySQL 的痛点对业务造成了极大影响。
- 磁盘碎片率高,资源使用率低,MySQL基于BTree的存储架构,在频繁增删改业务表的情况下,容易有存储碎片,需要定时做表、索引的重建来优化业务。这个问题一方面会导致MySQL存储空间使用的更多,另一方面在查询时可能需要读取更多的数据块,影响查询性能。
- 业务需要修改大表字段时,我们虽然能够使用第三方开源工具,比如pt-osc、gh-ost之类的尽量降低变更的影响,但是在变更的时效性上,无法保证。通常我们做表结构变更时,可能要以天来计,特别对于紧急变更情况不友好。
- MySQL数据库采用了主从架构,一旦业务突增,比如最常见的客户会批量下发群发任务,这时数据库会涌入大量的写入、读取操作,整个执行变得十分缓慢,在效率上不满足我们的业务要求,进而影响整个业务。
数据库选型
为了更好地支撑业务,以及应对业务全面升级的需求,我们考虑对整体的架构和数据存储组件重新设计和选型,比如升级为分布式数据库。我们在数据库选型中考虑的因素主要包括以下几点。
- 高扩展性:数据库系统应具备快速在线扩缩容的能力,以防业务突增时,数据库性能无法满足。
- 多租户能力:以满足客户资源隔离的需求和平台 SaaS 化的改造。首先,每一个客户都需要独立的数据库实例,无法共用资源;其次,业务侧采用了微服务架构,业务拆分模块分别对应多个MySQL实例;综上两点会造成MySQL数据库实例数增多,运维难度上升。而OceanBase的多租户能力可以将MySQL实例改造成租户的方式,即使是多个客户、模块的业务,在同一个集群里做到资源隔离,互不干扰,同时减少集群数量,降低运维复杂度。
- 兼容 MySQL 8.0:选择的数据库系统应能够与 MySQL 语法兼容,可以减少业务改造的工作量和成本。
- 高可用性:分布式数据库具有更强的数据一致性能力,同时数据库集群的容灾恢复能力也是重要的考量因素,基于MySQL的主从架构无法满足RTO=0的要求,在极端故障场景下,可能造成数据丢失。作为SaaS的业务,一旦有城市级别的故障,会涉及多个客户的实例,影响较大。
- 高性能:作为品牌的服务商,客户品牌种类多,客户门店数量庞大,toC的业务场景下,经常会需要做活动促销,因此我们对于数据库的单表存储量、性能并发都有一定的要求。基于目前的业务场景,要求单表行数据存储要求能超十亿行,事务并发处理能每秒超过百万次,以满足客户不定期做活动,业务突增的场景。
- 其他功能:客户需要实时同步在SaaS系统中的C端客户数据,对接系统种类繁多,数据库周边配套工具能够提供异构数据库数据的在线迁移、同步功能等,或者兼容目前使用的DTS迁移工具。
经过对现有分布式数据库产品的调研和考察,我们认为OceanBase比较符合我们对数据库的要求,因此,对 OceanBase和 MySQL 进行了性能、扩展性、可用性这三方面的对比,
特性 | MySQL | OceanBase 4.1.0 |
性能 | 面临着海量数据的挑战,查询速度变得极度缓慢,MySQL的每秒事务处理能力(TPS)受限于硬件资源,一般情况下,TPS值在100到1000之间。 | 据官方数据,大规格单集群下可支撑峰值6100万次/秒 (TPS+QPS) ;单表最大3200亿行;准内存处理性能。 |
扩展性 | 扩展计算节点时面临限制,无法实现快速在线扩缩容,而且数据迁移能力较弱。分库分表更是有诸多问题。 | 水平扩展;在线扩缩容不停服;单集群OBServer节点数无限制。 |
可用性 | 支持主从切换、读写分离等高可用性方案需要依赖额外的组件和中间件;RT以小时为单位。 | 基于 Paxos 协议,数据强一致性;少数副本故障,数据不丢,服务不停;RPO=0,RTO<8s。 |
相较而言,原生分布式数据库 OceanBase 在各方面都优于 MySQL,尤其是在处理海量数据量时表现出的扩展能力。
功能验证
初步考察OceanBase以后,我们做了兼容性、基础功能、扩展性的测试。
- MySQL兼容性测试:虽然OceanBase官方推荐使用5.x的驱动版本,但因为存量迁移过程中需要考虑回退,以及业务代码统一,因此最终采用了8.0.23 mysql-connector-java来测试,OceanBase完全满足兼容性要求。
- 基础功能测试:测试SaaS平台上的业务功能,任务群发管理。该功能主要帮助客户公司运营和销售人员实现任务管理,是触发实施模版化的操作,比如用户需要做活动推送消息时,会向多个渠道同时发起推送任务,OceanBase在这种高并发的场景下,性能完全满足需求。
- 扩展性测试:先搭建了单节点的OBServer实例,再扩展为1-1-1集群,进一步再扩展为2-2-2集群,上述操作都在数据库管理平台执行,扩展过程中,基础功能测试无影响,业务无感知。
性能验证
用于测试的表结构:
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY, -- 产品 ID
corpid INT, -- 企业 ID
name VARCHAR(255), -- 产品名称
description TEXT, -- 产品描述
price DECIMAL(10, 2), -- 价格
category_id INT, -- 类别 ID
subcategory_id INT, -- 子类别 ID
brand_id INT, -- 品牌 ID
weight DECIMAL(10, 2), -- 重量
dimensions JSON, -- 尺寸 (JSON 字段,包含 50 个属性)
color VARCHAR(255), -- 颜色
material VARCHAR(255), -- 材质
size VARCHAR(255), -- 尺寸
stock INT, -- 库存
rating DECIMAL(3, 2), -- 评分
review_count INT, -- 评论数量
release_date DATE, -- 发布日期
sales_count INT, -- 销售数量
discount DECIMAL(3, 2), -- 折扣
sku VARCHAR(255), -- SKU
upc VARCHAR(255), -- UPC
ean VARCHAR(255), -- EAN
mpn VARCHAR(255), -- MPN
model_number VARCHAR(255), -- 型号
warranty VARCHAR(255), -- 保修信息
tags JSON, -- 标签 (JSON 字段,包含 50 个属性)
images JSON, -- 图片 (JSON 字段,包含 50 个属性)
shipping_info TEXT, -- 运输信息
return_policy TEXT, -- 退货政策
additional_info TEXT -- 其他信息
);
CREATE INDEX idx_products_corpid ON products(corpid);
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY, -- 订单 ID
corpid INT, -- 企业 ID
order_number VARCHAR(255), -- 订单号
customer_id INT, -- 客户 ID
product_id INT, -- 产品 ID
order_date DATE, -- 订单日期
shipping_date DATE, -- 发货日期
delivery_date DATE, -- 送达日期
shipping_address JSON, -- 收货地址 (JSON 字段,包含 50 个属性)
billing_address JSON, -- 账单地址 (JSON 字段,包含 50 个属性)
payment_method VARCHAR(255), -- 支付方式
payment_info JSON, -- 支付信息 (JSON 字段,包含 50 个属性)
order_status VARCHAR(255), -- 订单状态
tracking_number VARCHAR(255), -- 跟踪号
shipping_provider VARCHAR(255), -- 运输提供商
shipping_fee DECIMAL(10, 2), -- 运费
tax DECIMAL(10, 2), -- 税费
discount DECIMAL(10, 2), -- 折扣
subtotal DECIMAL(10, 2), -- 小计
total DECIMAL(10, 2), -- 总计
currency VARCHAR(255), -- 货币
quantity INT, -- 数量
size VARCHAR(255), -- 尺寸
color VARCHAR(255), -- 颜色
weight DECIMAL(10, 2), -- 重量
dimensions VARCHAR(255), -- 尺寸
gift_message TEXT, -- 礼物留言
special_instructions TEXT, -- 特殊说明
promo_code VARCHAR(255), -- 优惠码
referral_code VARCHAR(255), -- 推荐码
additional_info TEXT -- 其他信息
);
CREATE INDEX idx_orders_corpid ON orders(corpid);
用于测试查询性能的 SQL:
-- 1.简单 SELECT 查询:
SELECT * FROM products WHERE corpid = 1 LIMIT 10
-- 2.复杂 SELECT 查询:
SELECT * FROM products WHERE corpid = 2 and category_id = 98 and stock = 10 LIMIT 10
-- 3.JOIN 关联查询:
SELECT * FROM products JOIN orders ON products.corpid = orders.corpid AND products.id = orders.product_id WHERE products.corpid = 1 LIMIT 10
-- 4.带聚合函数的查询:
SELECT COUNT(*) FROM products WHERE corpid = 1
-- 5.带 JSON 字段的 JOIN 查询:
SELECT * FROM products JOIN orders ON products.corpid = orders.corpid AND products.id = orders.product_id WHERE products.corpid = 1 AND JSON_EXTRACT(products.dimensions, '$.attribute_1') = "value1" limit 10
-- 6.JOIN关联多表,同时多条件和多 json 字段查询:
SELECT *
FROM products
JOIN orders ON products.corpid = orders.corpid AND products.id = orders.product_id
WHERE products.corpid = 1 AND price > 10 AND stock > 10 AND rating > 4
AND JSON_EXTRACT(products.dimensions, '$.attribute_1') = "value1"
AND JSON_EXTRACT(products.dimensions, '$.attribute_2') = "value1"
AND JSON_EXTRACT(products.dimensions, '$.attribute_3') = "value1" limit 10
-- 7.分页多条件查询:
SELECT * FROM products WHERE corpid = 1 AND price > 10 AND stock > 10 AND rating > 4 LIMIT 10 OFFSET 0
查询性能测试
在相同的规格(4核8G)的测试环境和数据量(产品表 3200 万,订单表 66.7 万)下,OceanBase 的查询性能明显优于 MySQL。
SQL id | 查询场景 | 数据量 | MySQL 执行时间(秒) | OceanBase 执行时间(秒) |
1 | 简单 SELECT 查询 | 3200万 | 0.01 | 0.01 |
2 | 复杂 SELECT | 3200万 | 87.88 | 0.64 |
3 | JOIN 关联查询 | 3200万 | 0.03 | 0.01 |
4 | 带聚合函数的查询 | 3200万 | 2.18 | 0.44 |
5 | 带 JSON 字段的 JOIN 查询 | 3200万 | 0.02 | 0.01 |
6 | JOIN 关联表同时多条件和多 json 字段查询 | 3200万 | 1.93 | 0.06 |
7 | 分页多条件查询 | 3200万 | 0.01 | 0.01 |
总执行时间 | 3200万 | 92.04 | 1.19 |
写入性能测试
数据量 300 万,用 3 个 corpid, 每个bu (业务租户) 插入 100万, 每个表有 30 列,其中 3 个 json 列,每个 json 列插入 50 个属性。OceanBase和 MySQL 的写入性能大致相当。
服务器环境 | 数据库类型 | 规格 | 插入数据量 | 总耗时(秒) | 每500行耗时(秒) |
阿里云 | MySQL | 4核8G | 300万 | 1895.33 | 0.73(平均) |
阿里云 | OceanBase | 4核8G | 300万 | 1877.15 | 0.73(平均) |
应用收益
从传统集中式数据库MySQL升级为原生分布式数据库OceanBase后,我们在性能、扩展性、高可用、隔离性、降本等方面都获得了不错的收益。
· 高性能:任务日历、群发等功能的 SQL 查询性能提升了30倍。
· 低成本:磁盘数据单副本OceanBase 不到100GB,MySQL 500GB,从MySQL的主从两副本迁移到OceanBase三副本,存储成本下降 70% ,同时内存占用由原来的16GB降低到10GB,内存使用率降低了30%。
· 原生分布式及高可用:通过原生分区表方案,我们成功解决了大表存储查询缓慢和数据复制等问题,并提供了高可用性方案。
· 多云多活:方便多云部署管理 OceanBase,目前已接入电信云、阿里云。
· 多租户:实现了多 MySQL 实例的整合管理,SaaS 化后能大大减轻部分私有化部署和后期运维的成本。
而且,相比于 MySQL 管理多实例时非常高的硬件成本, OceanBase 多租户的能力还可以根据各个数据库实例的规模,选择不同规格的租户,能够更加清晰地计算每个实例使用的资源和费用预估。
OceanBase 在实例多的场景下,可以允许将多个实例合到一个集群中,每个实例对应一个租户。然后将有不同波峰、波谷的业务放入一个集群,比如白天跑业务、晚上跑批和分析,混合部署能够充分利用整个集群的资源和存储空间。也就是说,多租户之间可以业务混部、削峰填谷。当一个 OBServer 上只有一个租户负载很高,但是其余租户空闲时,负载高的租户的 CPU 可以超出限制。
我们利用 OceanBase 的多租户特性,根据实际情况配置了租户间的数据隔离属性,成功推动了平台的 SaaS 化演进。此外,OceanBase 的分布式架构也为未来的系统扩展和业务发展提供了有力支持。
未来规划
目前,我们正在调研通过 OMS 替换 DataWorks 和 MaxCompute 等数据同步工具和计算服务。后续将深化OceanBase的应用,比如:
- 在多个云平台上架设 OceanBase 数据库。
- 使用 OceanBase提供的 Binlog Service,实现 SaaS 部署 OceanBase,并将数据同步至 Hologres。
- 使用 OceanBase 替换现有的 Hologres 数据库。
同时,我们对OceanBase也有一些期待,如下。
- OBServer:每日合并只能是基于集群做数据合并,无法基于租户单独配置数据合并的时间点。希望可以支持单独配置各租户的合并时间。
- ODC:希望能支持异构数据源,例如 Redis、Mongo 等,并进一步完善数据库权限账号管理的功能,如需要区分读写账号等。
- OMS:希望支持选择表中的特定字段进行迁移和同步,并且自动修改目标库对应表的字段类型。