Apache SeaTunnel过年临门一脚调优,有哪些技巧?
摘要:这篇就当是一次复盘:从“我以为是流式,不会堆内存”到慢慢意识到——你以为的“流”,其实是很多层 buffer 和 batch 堆起来的。
作者 | 肌肉娃子
起因:我以为只是“复制一份配置”这么简单
最开始的想法很朴素:
amzn_order 的 Seatunnel CDC → Doris 同步已经跑得挺稳了,那我把这套配置直接“平移”到 amzn_api_logs 上,表名改一改,跑起来就完事。
结果就是:
线上机器内存一路飙到十几 G,Java 进程频繁 OOM,Doris / Trino 全在同一台机器上跟着抖。
更扎心一点:这事本质不是 SeaTunnel 的 bug,而是我自己对数据分片、流式写入和内存模型的理解太粗糙。
这篇就当是一次复盘:从“我以为是流式,不会堆内存”到慢慢意识到——你以为的“流”,其实是很多层 buffer 和 batch 堆起来的。
事故现场:一台 60G 机器,快被我榨干了
当时的 top 大概是这样:
MiBMem:63005.9total,2010.6free,53676.2used,8097.3buff/cache
MiBSwap:0.0total,0.0free,0.0used
...
PIDVIRTRES%MEMCOMMAND
236602122.5g16.9g27%java...seatunnel-2.3.11...
187309914.3g7.1g11%trino
189579449.5g1.7g2%doris_be
SeaTunnel 这个 Java 进程实打实吃了 16~17G 堆,全机 free 内存不到 2G,Swap 又是关的,随时有被 OOM Killer 一刀秒掉的风险。
当时我脑子里还有个迷思:“不是流式写吗?为啥会把内存吃满?”
表结构和配置:看起来正常,其实每一项都在助推 OOM
表结构:amzn_api_logs
CREATETABLE`amzn_api_logs`(
`id`bigintNOTNULL,
`business_type`varchar(100)NOTNULL,
`req_params`jsonDEFAULTNULL,
`resp`jsonDEFAULTNULL,
`seller_id`varchar(32)NOTNULL,
`market_place_id`varchar(32)NOTNULL,
`create_time`datetimeNOTNULL,
`update_time`datetimeDEFAULTNULL,
`remark`varchar(255)DEFAULTNULL,
`is_delete`bigintNOTNULLDEFAULT'0',
`version`bigintNOTNULLDEFAULT'0',
PRIMARYKEY(`id`)USINGBTREE,
KEY`idx_create_time`(`create_time`)USINGBTREE
)ENGINE=InnoDB;
两列 JSON:req_params / resp。
日志类 JSON,体积能有多大大家心里都有数。
初版 SeaTunnel 配置(核心部分)
job.name="amzn_api_logs"
execution.parallelism=10
job.mode="STREAMING"
checkpoint.interval=60000
}
source{
MySQL-CDC{
parallelism=6
incremental.parallelism=4
snapshot.parallelism=4
table-names=["amzn_data_prd.amzn_api_logs"]
snapshot.split.size=50000
snapshot.fetch.size=10000
chunk-key-column="id"
exactly_once=true
startup.mode="initial"
}
}
sink{
doris{
sink.model="UNIQUE_KEYS"
sink.primary_key="id"
sink.label-prefix="amzn_api_logs_cdc_doris"
sink.enable-2pc="true"
doris.batch.size=50000
...
doris.config{
format="json"
read_json_by_line="true"
}
}
}
当时我的心理预期大概是:
“CDC + STREAMING + Doris,一条条流过去,内存顶多放点 buffer,不至于炸。
