LogMiner vs 裸日志解析(六):想提速,只能“堆实例”,结果把源库拖垮

前面聊了单线程限制------LogMiner解析速度上限就在1万到1.5万条/秒,日志量越大性能越差。

那怎么办?总不能业务等着你慢慢解析吧。

很多团队想到的解决办法是:一个实例不够,那就多开几个。

一个库开好几套采集实例,一个实例采一批表,每个实例独立解析自己负责的那部分日志。听起来很合理对吧?横向扩展嘛。

但实际效果往往跟预期完全相反。

一个真实的场景

之前跟一个做数据平台的团队聊,他们刚开始用Flink CDC采一个Oracle库,十几张表,跑得挺稳。

后来表越来越多,加到五六十张,延迟开始上来了。他们的解决办法是:再起一套Flink CDC任务,把表拆成两批,两个任务并行采。

延迟确实降了一点。但好景不长,表继续加,延迟又上来了。于是再拆------三套、四套、五套。

到最后,他们在一个Oracle库上跑了七套Flink CDC任务,每套连接器都在源库上开自己的LogMiner会话。结果呢?

延迟没降多少,源库先扛不住了。

CPU使用率从原来的30%多涨到了70%以上,PGA内存被吃掉了一大块,业务高峰期数据库响应明显变慢。DBA找过来问:你们到底在数据库上跑了什么?

为什么"堆实例"解决不了问题?

因为每套实例的成本,都记在源库头上。

第一,每个LogMiner会话都要占用源库的CPU。

LogMiner虽然被限制只用一个CPU核心,但那是每个会话一个核。你开七套实例,就是七个LogMiner会话在源库上跑。七个核同时干活,对源库的CPU压力是叠加的。

第二,每个LogMiner会话都要占用PGA内存。

前面聊过大事务OOM------LogMiner的解析结果存在PGA里,事务越大,PGA占用越高。七套实例并行跑,七份PGA同时消耗,内存压力是七倍。

第三,每个实例都要独立扫描日志。

LogMiner的工作方式是"从指定的起始SCN开始扫描redo文件"。七套实例意味着七次独立的扫描。同样的日志内容,被重复读取了七遍。磁盘I/O、内存带宽全都被浪费了。

第四,日志切换的协调问题更复杂。

Oracle的redo log是循环使用的。多套实例并行读取,每套都有自己的检查点SCN。如果某套实例落后太多,它需要的归档日志可能已经被清理了------检查点失效,任务挂掉。

第五,SCN一致性更难保证。

多套实例独立解析,各自的SCN进度不一样。如果下游需要合并这些变更流,怎么保证事务的全局顺序?一个事务的数据块修改可能被实例A采到,回滚块的修改被实例B采到------跨实例的事务归集,几乎不可能做对。

麻烦在哪?

吞吐没上去多少,源库先被拖慢。

七套实例的吞吐,不是七倍,可能只有两倍多。因为源库的资源是有限的------CPU、内存、磁盘I/O,你开再多实例,总量不变。实例之间互相争抢,每个实例的速度都往下掉。

运维复杂度翻倍。

一套实例的时候,配置、位点、监控、告警,一套就够了。七套实例意味着:

  • 七份配置文件要维护
  • 七个位点要跟踪
  • 七套监控要配
  • 七个任务可能在不同时间出问题

一个任务挂了,你得先搞清楚是哪个实例、采的哪批表、位点在哪里、为什么挂。排查时间成倍增加。

源库的DBA会来找你。

这是最现实的问题。你跑了七套LogMiner,占用了源库大量CPU和PGA。业务高峰期数据库变慢,第一个被问责的就是你的CDC链路。

有个DBA跟我说过一句话:"你们的同步任务,比我们自己的业务还费资源。"

裸日志解析怎么解决?

TLA的思路不太一样------单进程多线程,把算力加在解析机上,而不是加在生产库上。

具体来说:

第一,解析机独立部署。

TLA部署在一台独立的服务器上,不跑在源库上。它通过读取归档日志或者在线日志文件来解析,不需要在源库上开任何会话、跑任何进程。

第二,单进程多线程并行。

不需要开多个实例。一个TLA进程,内部用多个线程并行解析日志。线程之间共享内存空间,避免了跨进程通信、上下文切换、数据复制这些开销。

第三,算力加在解析机上。

想提高吞吐?加解析机的CPU核数、加内存。源库毫无感知------它只是提供了一个日志文件,谁在读、读多快,跟它没关系。

第四,只扫描一次日志。

多个线程协同工作,按数据块或按日志段拆分任务,每个线程处理自己负责的那部分。同一份日志只被扫描一次,不重复读取。

第五,顺序控制在解析阶段内建。

多线程并行解析的同时,按顺序构建事务流。不需要后置排序,不需要多实例协调。

我们团队在做TLA的时候,就是按这个思路设计的。单进程多线程解析引擎,部署在独立服务器上,通过读取归档日志和在线日志做解析。实测小字段场景能跑到10.8万条/秒,内存占用稳定,不随日志量增长而恶化。目前Oracle版本已经跑通了,后续MySQL、PG和国产数据库的支持也在推进中。

一个直观的对比

假设你需要从同一个Oracle库采集100张表,峰值日志量很大。

堆实例的方式:

实例数 源库CPU占用 源库PGA占用 实际吞吐 运维复杂度
1套 1核 中等 1万条/秒 低
3套 3核 较高 2万条/秒 中
7套 7核 很高 2.5万条/秒 高
10套 10核 极高 可能反而下降 失控

单进程多线程的方式:

解析机配置 源库CPU占用 源库PGA占用 实际吞吐 运维复杂度
4核 0 0 5万条/秒 低
8核 0 0 10万条/秒 低
16核 0 0 20万条/秒 低

这个对比的核心差异是:堆实例是把成本加在源库上,单进程多线程是把成本加在解析机上。

源库是生产系统,它的CPU和内存应该留给业务。解析机是辅助系统,它的资源可以按需扩展,不影响任何人。

再说一个容易被忽略的点

多实例方案的数据一致性,比单进程多线程更难保证。

假设一个事务修改了两张表:表A和表B。表A由实例1采集,表B由实例2采集。如果实例1先解析完,实例2还没解析到,下游就会先收到表A的变更,后收到表B的变更。如果下游需要两张表的数据保持事务一致性,这个顺序就错了。

单进程多线程方案不存在这个问题。所有线程在同一个进程内协同工作,顺序控制在解析阶段内建。事务的完整性由解析引擎统一保证,不依赖多实例之间的外部协调。

说句实在话

想提速,只能"堆实例"------这是单线程LogMiner方案的宿命。

因为单进程的解析能力上不去,只能靠加进程、加实例来横向硬堆。但每个实例的成本都记在源库头上。吞吐没上去多少,源库先被拖慢。实例一多,配置、位点、监控全都翻倍,运维迅速失控。

TLA走的是另一条路------单进程多线程,在一台独立的解析机上用多个线程并行解析日志。想扩展,加的是解析机的CPU和内存,源库毫无感知。

这是"LogMiner vs 裸日志解析"系列的第六篇。后面会继续聊其他几个坑------大事务OOM、SCN追不上、在线日志读写冲突,等等。

欢迎交流。


补充:文中提到的性能数据和资源消耗情况基于内部测试和公开社区案例,实际效果受硬件配置、数据库版本、日志大小等因素影响。

相关推荐
学好statistics和DS2 小时前
数据库数据世界的逻辑基石:Armstrong公理系统全解析
数据库·数据库开发
IT古董2 小时前
《FDE前沿部署工程师实战教程》23 - Enterprise AI Event Bus:事件驱动、消息队列与AI工作流自动触发
大数据·数据库·人工智能
程序猿乐锅2 小时前
【黑马点评 | 第七篇】Redis 分布式锁的两种实现
java·数据库·redis·分布式·spring·缓存
这个DBA有点耶2 小时前
连接池与MySQL交互实战:连接风暴、连接泄漏与连接状态异常排查
数据库·mysql·架构
TDengine (老段)2 小时前
TDengine TSDB 实战排障三(集群高可用)
数据库·物联网·时序数据库·tdengine·涛思数据·问题排查
需要8263 小时前
MySQL MVCC 与事务隔离级别:从一条 update 看版本链
java·数据库·spring boot·mysql·spring cloud
夜雪一千3 小时前
MySQL 默认值使用方法
数据库·mysql
SelectDB3 小时前
1TB/天 × 30 天日志成本怎么估:核对命令、降冷配置与踩坑记录
大数据·数据库·数据分析
SelectDB3 小时前
日志选型别只比 Loki 和 ELK:三条路径、一份可复制的落地清单
大数据·数据库·数据分析