Apache SeaTunnel MongoDB到Doris同步时,有哪些常见问题及解决方案?

摘要:最近在几个数据中台项目里,频繁用SeaTunnel做MongoDB到Doris的数据同步。说实话,这活儿看着简单,真上手了才发现坑不少。尤其是生产环境,数据量大、结构复杂,稍不注意就掉坑里。
最近在几个数据中台项目里,频繁用SeaTunnel做MongoDB到Doris的数据同步。说实话,这活儿看着简单,真上手了才发现坑不少。尤其是生产环境,数据量大、结构复杂,稍不注意就掉坑里。 这篇文章不打算重复那些基础配置步骤——网上已经有很多了。我想聚焦在实际生产环境中,那些最容易让人栽跟头的地方。特别是当你面对的是TB级别的MongoDB集合,需要稳定同步到Doris做实时分析时,下面这五个坑点,几乎每个都会遇到。我会结合具体的报错日志、排查思路,以及我们团队摸索出来的解决方案,帮你把这些坑一个个填平。 1. 数据类型映射:BSON到SQL的转换问题 MongoDB的BSON类型系统和Doris的SQL类型系统,表面上看起来能自动映射,实际上藏着不少“惊喜”。最典型的就是Decimal128和ObjectId的处理。 1.1 Decimal128的精度丢失问题 MongoDB里用Decimal128存储高精度数值,比如金融交易的金额。SeaTunnel默认会把它映射成Doris的DECIMAL类型,但这里有个关键限制:Doris的DECIMAL最大支持38位精度,而Decimal128是34位小数位。如果你在SeaTunnel的schema里没明确指定精度,很可能遇到这样的错误: java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result 解决方案是在schema里显式声明精度。别用自动推断,手动控制: source { MongoDB { uri = "mongodb://user:password@host:27017" database = "finance" collection = "transactions" schema = { fields { _id = string amount = "decimal(38, 18)" # 明确指定38位总精度,18位小数位 currency = string timestamp = timestamp } } } } 注意:如果你的数据里Decimal128的小数位超过18位,需要根据实际情况调整。我们有个电商项目,优惠券计算精度要求高,就用了decimal(38, 24)。 1.2 ObjectId和嵌套文档的序列化坑 MongoDB的_id字段默认是ObjectId类型,SeaTunnel会把它转成字符串。这看起来没问题,直到你发现Doris表里的主键冲突——因为ObjectId转字符串后,Doris的UNIQUE KEY检查可能会出问题。 更麻烦的是嵌套文档。MongoDB里很常见的结构: { "_id": ObjectId("507f1f77bcf86cd799439011"), "user": { "name": "张三", "address": { "city": "北京", "district": "朝阳区" } } } SeaTunnel默认会把整个user对象转成一个JSON字符串存到Doris的一个VARCHAR字段里。如果你想在Doris里直接查询user.address.city,就得用JSON函数解析,性能很差。 我们的做法是在SeaTunnel里用transform插件提前展开: transform { # 展开嵌套字段 sql { query = """ SELECT _id, user.name as user_name, user.address.city as city, user.address.district as district FROM mongodb_source """ } } sink { Doris { fenodes = "fe1:8030,fe2:8030" username = "admin" password = "***" database = "analytics" table = "user_flat" # 现在表结构是平的,查询效率高 } } 如果嵌套层级太深或者不确定,也可以考虑在Doris里用MAP类型,但要注意2.0以上版本才支持。
阅读全文