暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

实践分享 | 跨境电商 OA 系统替换 MySQL 两次迁移经验浅谈

OceanBase 2024-12-09
104

🧡 *本篇内容为 「OceanBase 布道师计划」优质投稿内容,活动仍在进行中,欢迎感兴趣点击《重磅激励!OceanBase布道师计划即日开启》了解详情或投稿。🥳


本公司为跨境电商企业,从国内开发商品,刊登到国际电商平台上售卖。目前在售 SKU 有 100w+。由于管理的店铺较多,SKU 放大到各个电商平台,存在几个亿的 Listing数据。基于该跨境电商企业的 OA 系统数据库替换 MySQL,作者对二次迁移 OceanBase 经验进行了分享。





在业务发展早期,未做数据库拆分工作,所有平台店铺数据表都在同一个数据库(MySQL)中,且各个业务之间,关联查询未作任何限制。随着业务发展,数据库难以实现分库分表。目前,业务总数据量达到 6TB,共 1400+ 张表,单表最大记录数 5 亿,单表最大数据量 300GB。数据库系统逐渐出现各种瓶颈或问题,具体表现为以下几点:


第一,业务发展早期使用的是 MySQL 单机,业务壮大后升级为集群,系统中存在不少历史遗留的全表更新业务代码。一旦执行,MySQL 主从延迟就会超过设定的阈值,导致从库无法使用。同时,所有 SQL 全部被路由到主库,导致主库 CPU 使用率飙升,进而使业务明显感知到卡顿。


第二,部分表的单表数据量大,如果做一次整体业务调整,需要频繁更新整张表,容易出现 TPS 瓶颈。这时通常会进行分区,将 TPS 流量分片到不同机器,提高业务执行效率。结合业务来说,假设我们对商品做一次全量调价的操作,为了确保调价成功,会将调价信息发送到 RabbitMQ,然后通过多台消费端进行接口调用并更新数据。但当出现大批量的调价需求时,如果增加过多消费端,会造成数据库压力过大。在维持日常业务使用的情况下,消费完整个队列的消息可能需要 1-2 个星期,这显然不符合业务预期。


第三,历史代码量太多,业务中使用的关联多表的查询较多,使用传统的分库分表方案,改造工作量巨大,而且不好处理跨机关联查询引起的性能问题。


第四,MySQL 数据膨胀厉害,云盘存储费用高涨,亟需优化存储成本。





基于上述痛点,我们亟需一款新的数据库,且需要具备以下特点:


💡 有优秀的分库分表架构能力。


💡 集群整体高可用,主要是从库延迟低,能稳定提供读服务。


💡 可以灵活扩展。


💡 运维简单,便于查找实时问题 SQL。


💡 能降低存储成本。


经过初步调研墨天轮排行上排名前十的数据库,发现 OceanBase 技术架构强大,产品文档完善,当我们在社区求助时很快就能得到反馈和解答。最重要的是 OceanBase的性能符合我们的要求,主要表现为以下几点:


✅ 表组和复制表特性,能极大地减少分区带来的跨机关联查询消耗,非常有利于我们简化后续的表分区工作。


✅ 数据压缩率高,最开始了解到 OceanBase 数据压缩率为1:3,而在实际应用后发现 MySQL 6TB 的数据,同步到 OceanBase 只需要 920GB 的空间,压缩率达到惊人的1:6。我猜测是由于 MySQL 中存在大量由于数据删除而未释放的空间造成的。而在 OceanBase 的实际使用中,我们完全无需担心这一问题,因为每天 OceanBase 都有一次数据合并,整理存储空间。


✅ 集群架构的高可用性和开源免费的 OCP 运维工具,比较适合自建集群运维,白屏页面化操作对于集群监控、集群扩展、SQL 诊断能提供极大的方便。同时也省略了使用 RDS 时,需要花费的监控和 SQL 诊断服务费用。


✅ OceanBase 使用 Paxos 协议,虽然把写放大了,但从另一个维度降低了主从副本数据同步的延迟。低延迟对于我们原有的一主二从的 RDS MySQL 架构来说,更能发挥从副本机器的查询性能。


下面来具体讲一下我们的迁移过程。下表是我司最开始使用 RDS 的机器配置和成本,以及最终迁移完成后使用 OceanBase 的机器配置和成本。



生产库从 MySQL 迁移到 OceanBase ,我们做了两次尝试,在这里 OceanBase 提供了专业的数据迁移工具 OMS,支持数据的反向同步。正是这一功能顺利支撑了我们多次调整后的数据迁移。


第一次,为了尽可能提高整体写性能,根据 RDS 原配置的核数和内存。我们使用 9 台 16 核 64GB 的小型机部署 OceanBase 3-3-3 的集群,将数据较多的表做分区。同时,将相同业务的表加入同一个表组,把多个业务需要关联查询的部分表,改成复制表,解决跨机查询带来的性能问题。


这种方案完美的解决了业务高频次的 TPS 请求延迟问题。但由于我们过于急切地使用这种完美的切换方案,导致迁移的集群性能无法支撑原业务的日常请求。主要存在如下问题。


① 历史代码存量过多:虽然做了很长时间的准备(分区、分表组、改复制表、关联查询和 DDL 语句加分区键),但还是有“漏网之鱼”,导致存在较多跨机关联查询,占用了大量 CPU。


② 部分业务表无法分区:有些业务没办法分区而且请求量大,单台小型机完全无法支撑这部分业务请求,一个节点受阻就会使整体写同步延迟。


③ 我们将 OBProxy 和 OBServer 部署在同一台机器上,当这台 OBServer 由于提供查询导致 CPU 使用率过高时,通过 OBProxy 请求会造成阻塞。


第二次迁移基于失败经验,我们意识到需要解决三个问题:


第一,单机性能需要提高,最少要能保障无法分区的业务量最大的模块的请求;


第二,历史代码庞大,所有业务模块整体分区工作量太大,而我司亟需尽快升级数据库架构;


第三,OBProxy 不能和 OBServer 部署在同一台机器。


经过优化,我们决定使用 64 核 512GB 内存部署 OceanBase 1-1-1 集群再次尝试,而且将迁移和改造分三个阶段进行。


第一阶段,将所有表加入一个大组,表结构暂时和 MySQL 一致,不做分区。这样就避免了跨机查询的问题。部署 2 台 OBProxy,一台查询只使用主副本,另一台查询优先使用从副本,通过延迟阈值的多次调整,确定了 400ms 的延迟阈值。因为这个代理的查询请求几乎都会发送到从副本请求,而 400ms 的延迟对业务来说是可接受的(相较之下,MySQL延迟阈值 3s,才能使用上一半从副本的性能)。同时为了避免由于主从数据不一致问题,我们对应用进行了改造,所有开启了事务的读请求,都会使用主副本查询。


第二阶段,分业务模块逐步改造业务分区和表组,检查所有关联查询代码以确保不会存在跨机关联。然后将整个模块的表进行分区,并从原来的大表组中迁移到新的业务模块表组中,逐步将主副本打散到所有机器上。


第三阶段,所有业务模块都完成分区和表组的改造后,取消读写分离代理。全部使用主副本查询数据,完全消弭掉同步延迟带来的数据不一致问题,为后续集群扩容做好准备。





目前为止,OceanBase 已经在内部 OA 系统试运行一个月,总体来说,以 OA 系统目前的数据量来看,使用OceanBase 和此前用 MySQL 执行 SQL 的效率相近,后续随着数据量的增加,预计 OceanBase 的性能优势会逐渐显露。


另外,在上线一个月以来,我们已经明显感知到 OceanBase 带来的优势,简要总结为以下 4 点。


第一,存储成本下降 40%,原 MySQL 单台机器需要 6TB 存储空间,在 OceanBase 单台机器只需要 1.5TB,存储空间节约了 3/4。


第二,由于 OceanBase 使用 LSM-Tree 架构,优先写内存和日志,对于云盘的性能要求也下降了,云盘的性能级别从 P2 降为了 P1。相较之下,原本在 RDS 需要使用 L2 级别 10w IOPS性能的数据盘才能扛住的业务访问压力,OceanBase 使用 L1 级别 5w IOPS 的数据盘就足够支撑。


第三,主从延迟稳定性提高。由于 OceanBase 主从延迟低,能保证从库性能使用率,进而提高了整个集群的系统稳定性及性能稳定性。目前为止,还没出现因为从副本延迟过高导致所有查询都打到主副本的情况,更没有整个服务卡顿或主从延迟导致主副本请求飙升的情况。


第四,运维效率提升,运维成本降低。OCP 提供了全量 SQL 诊断,帮助我们更便捷地进行全局慢 SQL 监控。这在此前的 RDS MySQL 需要开启全量 SQL 才能实现,每天消耗几百块钱,可以说 OCP 帮我们省了一笔运维费用。


不过从 MySQL 迁移到 OceanBase 也有一些不兼容的地方的,如下:


👉 OceanBase 4.2.1 版本暂不支持全文索引,OceanBase 4.2.3 版本开始支持,但该版本暂未推出 GA 版本,所以我们本次迁移还是选择了 4.2.1 版本。


👉 OceanBase 的 SQL 解释执行器效率没有 MySQL 高,对于传入参数较多的 SQL,比如 IN 查询范围较多的情况,获取执行计划就比较慢。


👉 OceanBase 在部分 SQL 上,类型转换的优化不如 MySQL 完善,例如 OR 查询中,条件中的字符串不会自动转换为 Int,导致无法使用索引。


👉 OceanBase 4.2.1 不支持临时表。


👉 同样的 SQL,执行器每次给出的查询方案可能不同。通常是数据分布和索引创建异常。该问题也存在于 MySQL 中,例如查询时间范围内的数据,如果指定的时间所占整体数据的 15% 左右,就可能不使用这个时间字段的索引,引发全表扫描。如果要强制使用索引,需要指定 Force Index,会有代码侵入。相比之下,OceanBase 给出了优化方案,我们可以通过告警知道哪些 SQL 波动导致恶化,然后绑定一个执行计划,相当于在数据库运维层面解决问题。





在使用 OceanBase 的过程中,我们也积累了一些经验,下面就以问题及相应解决方法的形式,和大家分享。





🧐 问题:使用读写分离代理访问时,即使开启了事务,查询也不会使用主副本,会造成数据一致性问题。


🙋‍♂️ 解决方案:对应用进行改造,对开启了事务的方法,指定使用主副本代理连接。这对于所有刚刚从MySQL迁移到OceanBase,又需要从副本提供查询能力的用户来说,应该是一个通用的解决方案。





🧐 问题:生产集群内存配置问题,一开始为了尽最大可能使用所有内存,我们直接指定了 memory_limit=512G。在夜间存在数据统计的大查询,导致内存溢出, 阿里云服务器直接消除了 OBServer。


🙋‍♂️ 解决方案:一种方式是按照官方推荐, memory_limit 改回默认值 0M. 默认常驻使用 80% 的机器内存。另一种方式是优化大查询,同时规范所有 SQL书写,在以后需要更多内存的时候,将 memory_limit 改为 90%。





🧐 问题:夜间合并时,磁盘使用量突增 20%,触发 90% 预警。LSM-Tree 结构决定了每天需要合并数据以减少垃圾数据的存在。使用 OceanBase 需要额外考虑多加 20% 的磁盘空间用于合并时的空间伸缩。


🙋‍♂️ 解决方案:额外扩容 20% 的磁盘。





🧐 问题:数据备份设置了7天恢复期,但实际存储的备份量为 14 天。


🙋‍♂️ 解决方案:通过日志备份量和数据备份量分析,因为每天生成的日志备份量和整库备份使用的空间是差不多的,我们可以直接改为每天都全量备份,这样就能保持仅留存 7 天的备份数据了。


总体而言,OceanBase 的应用符合预期,社区官方人员的及时响应和活跃的社区用户互帮互助,给了我们更大的信心。由于对新数据库不够熟悉,我们在使用过程中走了一点弯路,也希望官方可以来个傻瓜式的生产配置推荐,降低小白入门采坑的概率。



往期推荐

点击「阅读原文」,进入【布道师计】投稿

文章转载自OceanBase,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论