
作者:姚力,翼鸥教育高级 DBA
自2021年起,翼鸥教育便携手OceanBase社区版踏上了数字化转型的征程。在随后的两年间,我们成功部署了多达12套生产集群,其中核心集群占比超过四分之三,累积数据量更是突破30TB大关。这一里程碑式的成就,彰显了我们对高效、稳定数据库解决方案的不懈追求。
提及翼鸥教育的明星产品——“ClassIn 在线教室”,它不仅是连接全球150多个国家师生的桥梁,更是集智慧教学服务、软件应用与硬件配套于一体的综合性教育平台。同时,我们的产品矩阵还涵盖了TeacherIn、NOBOOK等众多教育科技精品,共同推动教育行业的创新发展。
面对MySQL数据库在应对高并发写操作及大规模数据处理时的局限性,翼鸥教育毅然选择了OceanBase作为解决方案。MySQL虽能通过扩展从库缓解读压力,但面对写瓶颈时却显得力不从心,特别是当单机数据量膨胀至2TB以上时,性能下降成为难以忽视的问题。分库分表虽可尝试,却难以从根本上解决根本问题,且业务连续性保障亦成挑战。MySQL的高可用能力还需依赖复杂的外部组件维护,增加了运维的复杂性和成本。正是基于这样的考量,OceanBase以其独特的多分区灵活扩展能力、卓越的数据压缩效率以及金融级的高可用性,成为了我们理想的替代选择。4.2.x版本的发布,特别是4.2.1 LTS的稳定推出,其单机性能、压缩效率及AP分析能力的显著提升,更坚定了我们全面升级的决心,并顺利完成了从3.1.4版本到4.2.1版本的跨越。接下来,我们将分享此次升级过程中的宝贵经验,希望能为业界同仁提供参考与启示。
一、为什么选择从3.1.4版本升级到4.2.1版本?
在上线 OceanBase 3.1.4 版本后,我们陆续部署了 12 套生产集群,其中超过 3/4 的集群是核心集群,数据量超 30TB。上线之后,OceanBase 3.1.4 的确为我们解决了不少难题,在灵活扩展、数据库压缩和高可用等方面的表现优异。
OceanBase 在翼鸥教育的应用场景如下图所示,翼鸥教育的应用通过访问 SLB(服务器负载均衡)再连接到 OceanBase 生产集群。在大数据场景下,由于 OceanBase 3.1.4 版本 AP 性能较弱,我们将上游数据通过 OMS 工具同步至 OceanBase 集群,在实时场景使用 OMS 将数据同步至 Kafka,在离线场景使用 Data X 将数据抽取到大数据的数仓系统中进行分析。

俗话说没有一款产品是万金油,OceanBase 3.1.4 在我们的业务场景中逐渐显现出一些不足。
DDL 支持不完善。OceanBase 的 DDL 速度非常快,但在 3.x 版本支持不够完善,比如向上兼容不支持 text-> medium text,再比如不支持 int -> varchar 的列类型修改。 字符集支持不完善。由于历史原因,我们使用的字符集没有用 OceanBase 支持的 utf8mb4_general_ci,而是 utf8mb4_bin 字符集,导致我们使用 OMS 在上游加字段时,下游的大数据集群就会发生数据迁移任务的中断。 大 IN 支持不友好。例如在 MySQL 中 IN 包含 80 万个值,查询只需 10ms,而在 OceanBase 3.1.4 版本中需要 5s,是因为时间主要消耗在查询解析方面。OceanBase 4.2 版本后对这方面做了优化,性能提升明显。 分区数太多影响性能。当分区数超过 30000 后,响应时间下降明显。 数据膨胀问题。OceanBase 降本增效的效果非常显著,原来 MySQL 集群中 6TB 数据迁移到 OceanBase 后缩减到了 1TB。但我们发现集群使用一段时间后,数据存在空间放大的问题。比如本来一年增长 1.5TB,但集群膨胀了 4T。 物理备份不支持 S3。S3 是可以充分利用网络带宽且价格优惠的存储方式,但 OceanBase 3.1.4 版本仅支持 nfs,未支持 S3。
基于上述使用方面的不足,我们决定升级到 OceanBase 4.x 版本。
二、升级至新版本的流程和效果
从版本选型到版本升级,我们历经四个阶段:版本选型、功能和性能测试、组件升级、集群升级。
第一阶段:版本选型
选择版本时我们主要考虑五个因素。
功能:新版本能否满足当前业务需求? 性能:新版本性能相较于旧版本性能提升多少? 稳定性:新版本是否足够稳定,有没有 bug? 兼容性:迁移后与旧的集群是否兼容? 产品生命周期:新版本是否为官方长期支持版本?
针对上述问题,我们结合应用场景需求,对 OceanBase 4.x 版本特性与升级点进行了分析:
性能显著提升:新版本相较于旧版本的性能能够更好地满足当前场景的需求; 长期支持版本更稳定:OceanBase 4.2 版本是长期支持版本,长期支持版本经过多次迭代,遇到的问题较少,与此同时,创新版本经过几个版本的迭代和修复,更加稳定; 兼容性更好:因为是从 OceanBase 低版本升级到高版本,所以兼容性更好。
第二阶段:功能和性能测试。
在 MySQL 环境中,我们可以使用 tcpcopy 进行流量回放来进行业务验证。然而,在 OceanBase 中,业务是以租户为单位的,如果直接采集流量,会涉及多个租户。为了方便实现,我们自己开发了一个代理(Agent),实时将 SQL_audit 中的 SQL 同步到 Kafka。在目标端,可以启动多个 Agent 读取 select 语句来并行进行回放,并观察目标端是否受到影响。

我们基于 gopacket 抓包。再进行 mysql ps 数据解析,经过解析的 PS 协议及其参数的结果存在 Redis,最后通过 Agent 读取 Redis 回放。这样可以让我们提前发现业务迁移中可能存在的问题,比如执行计划是否变慢、是否有不兼容问题等。
在迁移前,我们通过 sysbench 压测观察 OceanBase 新版本相较于旧版本的性能提升度。我们的服务器规格都是 64C/512G,但此处仅基于 16C/96G 的业务租户配置进行压测。从下图可见,OceanBase 4.2.1 版本较 OceanBase 3.1.4 版本性能提升 3 倍左右,即使在读写比 7:3 的场景下,新版本的性能更优,也更为稳定。

此外,保险起见,我们基于 JMeter,使用 CSV 动态生成参数的方式对生产线接口进行压测(线上租户配置为 3 节点 16C/96G )。结果如下图所示,OceanBase 4.2.1 版本较 OceanBase 3.1.4 性能提升 2 倍左右。

第三阶段:组件升级。
在确定版本升级后,我们先对组件进行升级,以下是我们在升级过程中的一些经验总结,供大家借鉴:
1. 如何解决长期未使用的 Agent 导致升级 OCP 时报错的问题?
具体而言,显示 ocp-server-ce:check_operation_task 未通过,The Server have running task。这是因为我们升级 OCP 时使用的 Agent 经久未用导致无法回滚,所以我们在它的原数据库中更新状态就可以了:update task_instance set state='SUCCESSFUL' where id in (父任务 id);
2. 如何针对 OMS Store 进行性能调优?
作为 OMS 的重度用户,OMS store 可以理解为一个 binlogservice 的 webservice,并且 store 内部有 OB CDC 模块。该模块包括数据消费模块和拉取日志模块。消费日志线程(cdc)会从多个 OBServer 中拉取 clog 并排序,存储到内存中。此时,CDC 拉取日志模块会消费内存中数据,并将其落盘。然而,由于最初使用的是机械硬盘,默认的 storage 即机械盘,导致落盘速度较慢。为了进行性能调优,我们将参数 storage 调整为内存,并且将 OB CDC 使用的内存限额从 20G 调整为 40G。此外,为了及时更新心跳时间,我们还将 DDL 当前拉取日志的上限(progress_limit_sec_for_ddl)从 3600 秒调整为 60 秒。
3. 如何解决 OMS 迁移和同步任务延迟问题?
在 OMS 的迁移流程中,首先会启动 OMS store,以保证后续 DBA 能成功取到增量数据。然后,全量迁移流程随之启动,待全量迁移和全量校验完成后,再启动增量数据迁移和校验流程。在这个流程中,我们经常遇到数据迁移慢、校验时间长的问题,以及数据同步到 Kafka 延迟的问题。究其原因,不同场景采用默认参数,速度不及预期,我们可以通过调整参数来解决上述问题。
在数据迁移和校验场景,速度慢的时候我们通常会想到调整线程数或切片大小,以读取更多数据。但是读取更多数据就意味着内存需要更大的承载量,所以我们要把 JVM 参数调高。
常用调参:
workerNum | limitator.platform.threads.number sliceBatchSize | limitator.select.batch.max connectorJvmParam | task.checker_jvm_param
应用场景调参:
sliceByMinMax: false(id 不连续) sliceByMinMax: true(id 连续)
在数据同步 sink 到 Kafka 场景下,如果速度较慢,可能是由于分片算法的影响,导致 OBServer 的 I/O 较高。这是 slicebyminmax 的原因,通常情况下,我们的跑批操作类似数据库工具 pt 和 ghost,它们基于范围 100~~10000 不断向前滚动。然而,有时我们的自身 ID 包括业务使用的 UUID,它可能是不连续的,这会导致读取 I/O 较高。在这种情况下,需要关闭切片的 slicebyminmax 设置,这样可以提高数据同步速度。如果仍然无法满足预期,在机器的支持能力足够的情况下,还可以调整批处理的大小,每次读取更多的数据。
另外还需要调整 JVM 的内存。在这个场景下,开发人员都知道,对于插入操作,可以很容易地进行批量处理。但对于更新和删除操作,就不那么容易进行批量处理。因此,需要根据上游的情况如是否有大事务等,动态调整参数,尤其是针对 insert 和 update 的比例。首先消除最重要的瓶颈,然后再调整其它常用的参数,特别是在 OMS 中将增量同步到大数据库的情况下。我们采取了大数据库的 lock_time 默认值,并将 OceanBase 的 ob_query_time 参数设置得比较大,因为锁的释放时间根据 ob_query_time 来确定,可能会导致长时间被锁住的情况,进而使 jdbc 的 writer 的点位不更新。实际上,数据仍然会持续写入目标端。
常用调参:
workerNum
maxRecordCapacity
connectorJvmParam
应用场景调参
splitThreshold(insert 攥批效率高;update 和 delete 不能批量,拆开效果好)
4.如何解决 4018 错误码报错?
在使用 OceanBase 的过程中,让我们最困扰的问题是 4018 错误码,这也是版本升级的直接原因。当出现 4018 错误码的时候,一个 zone 中两个机器只有一个机器节点报错,无法请求,导致业务报错。短期解决方法是重启报错的机器节点,而从长远来看,升级版本才能彻底解决问题。我们升级到 OceanBase 4.2.1.3 版本后,再没有遇到过 4018 问题。

第四阶段:集群升级。
在集群升级的过程中,我们仍然保持谨慎的态度,分为准备、生产上线、整体回归、收尾操作四个步骤,升级成功后整体效果满足预期:
新版本的 DDL 支持完善,解决了旧版本的 DDL 问题,且性能得到较大提升; 数据被进一步压缩,比如 300GB 数据迁移到新版本后压缩至 200GB,存储空间得到释放; 新版本的备份支持 S3,使我们可以充分利用网络带宽; 数据从 OMS 同步到 Kafka,性能提升 7 倍。
至于上文提到的字符集支持问题,可能是 OB server 带来的,在 OMS 迁移的部分场景中仍会出现任务中断的现象。
三、总结和规划
目前,我们把 8 套核心集群都升级到了 OceanBase 4.2.1 版本,升级经验总结如上。而在我们从上线到使用 OceanBase 期间,有五点应用经验可供大家参考。
第一, 在我们使用 OceanBase 的过程中,跑批是业务经常做的工作。经验指出,跑批或数据更新时,尽量指定分区,避免跨节点分布式事务。
第二, 尽可能使用本地索引以节省开销,因为全局索引更新需要分布式事务,所以在唯一性或者多维场景下使用全局索引。
第三, 针对副本切主,OBServer 事务查杀有重试逻辑,业务同学要能够及时捕获异常,利用分布式特性和发挥分区并行的优势,避免业务报错。
第四, 在 OLAP 环境下可以充分利用并行提升查询速度,建议单个分区小于 50GB。
第五, 此前人工排查问题时速度比较慢,obdiag 推出后,问题定位和日志分析都变得方便、简单,在此推荐大家充分利用这个工具。
后续,我们会把剩余 OceanBase 集群都升级到 4.2.1 版本。同时,随着 OceanBase 4.3 版本 AP 能力的提升,我们也考虑将大数据集群升级到该版本。




