ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Doris Streamloader 安装配置与批量数据导入实战指南

Doris Streamloader 安装配置与批量数据导入实战指南 1. 写在前面Streamloader 到底是干嘛的先说个场景。之前我在生产环境里给 Doris 导数据用的还是最原始的curl方式一条curl --location-trusted -u root: -H label:xxx -T data.csv http://127.0.0.1:8030/api/db/table/_stream_load敲下去数据是进去了但只要文件一多、表一多这套手工操作立刻变得非常痛苦。文件要一个个对应表label 要自己保证不重复导到一半网络断了还得重新查进度、清 label、重新导。更别说几十个文件要并发导的时候脚本写起来又臭又长。Streamloader 这个工具就是来解决这个痛点的。它是 Doris 官方推出的一款专用数据导入工具专门面向批量、多文件、多表场景把本地文件、HDFS 文件批量导入到 Doris 的各个表里。它内部封装了 Stream Load 的完整逻辑你只需要给它一份描述文件清单和映射关系的配置文件剩下的拆分、并发、进度记录、失败重试它自己搞定。装好配置好之后一条命令就能把一个目录下几十个文件分别导进对应的表导入过程还支持断点续传中途挂了恢复一下就行。这篇教程适合谁一类是刚接触 Doris、正在搭建数据导入链路的新手另一类是在生产环境里被繁重的导入脚本折磨、想换成官方标准方案的运维或数据工程师。我会从零开始把 Streamloader 的下载、配置、验证、首次实战、调优、踩坑全部说清楚所有步骤都是我实际验证过的路径你照着做基本不会再卡壳。2. 安装前的准备工作2.1 环境要求先把这几项核对清楚Streamloader 本身是一个 Java 程序对底层操作系统没有强绑定Linux、Windows、macOS 都能跑只要 Java 环境达标就可以。我平时主要在 Linux 服务器上用它Windows 上也有过部署经历坑点后面会单独讲。先列一个环境清单对照自己的机器确认JDK 版本必须 8 及以上我用的是 OpenJDK 1.8 和 11 都验证过。如果机器上同时有多个 JDK务必确认JAVA_HOME指向的是正确的那个否则启动时会报UnsupportedClassVersionError或者Unable to locate a Java Runtime。Doris 集群版本建议 2.0.x 或更高版本Streamloader 依赖 Doris 的 Stream Load 接口和部分能力老版本 1.x 也能用但某些高级特性比如部分列更新、自动 schema 推导可能受限。网络连通性执行 Streamloader 的机器必须能访问到 Doris 的 FE 节点通常需要放通 FE 的 HTTP 端口 8030默认以及 FE 的查询端口 9030。如果你要通过 HDFS 导入那台机器还得能访问到 HDFS 的 NameNode 和 DataNode。磁盘空间工具本身只有几十 MB但它会在本地目录记录导入进度和临时文件建议至少留出 1GB 可用空间避免导入大文件时临时文件写满磁盘。注意曾经有人把 Streamloader 想成 Doris 集群内部的一个组件以为要部署在 BE 节点上。它其实是一个独立的客户端工具放在任何能连通 FE 的机器上都行不需要装进 Doris 的安装目录。2.2 版本选择与下载源Streamloader 的正式发布包在 Doris 官方的下载页面里可以找到和 doris、doris-src 等包放在一起包名一般是streamloader_x.x.x_x86_64.zip这种格式注意选对 CPU 架构x86 和 ARM 的包不要搞混。另外它也会同步到 GitHub 的 apache/doris-stream-loader 仓库的 Releases 页面如果你是内网环境、无法直接访问官方下载站从 GitHub Releases 拉包再传进内网也完全可行。关于版本选择我的建议是不要盲目追求最新选一个和你的 Doris 版本匹配度高的稳定版本即可。官方 Release 说明里一般会标注“兼容的 Doris 版本范围”比如某些版本专门修复了和 2.1.x 的兼容性问题。我生产环境里 Doris 是 2.1.xStreamloader 用的就是同期的稳定版用了大半年没出过兼容性事故。下载完之后可以用unzip streamloader_x.x.x_x86_64.zip解压包里的内容非常精简主要是几个 shell 脚本、jar 包和一个 lib 目录。2.3 Windows 部署差异说明如果你是在 Windows 上跑 Streamloader有几个细节要提前知道。Streamloader 的发布包里既有.sh启动脚本也有.bat脚本Windows 下用.bat即可。但 Windows 和 Linux 有两个明显的不同点一是路径分隔符。配置文件里写文件路径时Windows 推荐用正斜杠D:/data/import/或者用双反斜杠D:\\data\\import\\避免因为 YAML 解析把\当成转义符导致路径找不到。二是本地文件系统的性能差异。同一个导入任务在 Windows 和 Linux 上跑吞吐量可能会有不小差距这跟操作系统的文件缓存机制有关不要惊讶。如果数据量大我建议 Windows 只用来做功能验证生产导入还是放在 Linux 上执行。说完这些前置项下面进入正式的安装步骤。3. 安装与部署全流程3.1 下载安装包并校验完整性先从官方源下载对应架构的 zip 包。以 Linux x86_64 环境为例下载完成后建议先做两步检查第一步校验 hash。官方下载页一般会提供 md5 或 sha256 值用md5sum streamloader_xxx.zip或sha256sum streamloader_xxx.zip比对一下防止下载过程中文件损坏。这一步很多人会跳过但如果你遇到“解压报 CRC 错误”或者“jar 包启动异常”的问题回过来查这一下很管用。第二步确认解压后的文件没有缺失。正常的包解压后应该包含bin/、lib/、conf/这几个目录。如果少了lib/目录下的一堆依赖 jar那基本说明包不完整或者被安全软件清理了需要重新下载。3.2 解压、目录规划与 JAVA_HOME 配置解压本身没什么好说的unzip streamloader_xxx.zip -d /opt放在/opt/streamloader这类统一目录下即可。但我建议你做一件事创建软链方便以后升级版本。ln -s /opt/streamloader-1.0.0 /opt/streamloader这样以后更新版本只要把新包解压改一下软链指向脚本和定时任务都无需改动非常省心。我被人问过很多次“为什么目录名字带版本号”就是因为这个维护上的便利性。然后是 JAVA_HOME 的检查。启动脚本默认会读取系统的JAVA_HOME环境变量如果没有设置有的脚本会自动去/usr/bin/java找。为避免歧义建议在/etc/profile或启动脚本里显式指定export JAVA_HOME/usr/local/jdk1.8.0_202 export PATH$JAVA_HOME/bin:$PATH配置完执行java -version确认一下。3.3 启动脚本的可执行权限与初始验证解压后如果直接运行bin/streamloader.sh很多第一次接触的人会碰到Permission denied这是因为压缩包里的脚本默认没有执行权限。执行一下chmod x /opt/streamloader/bin/*.sh然后跑版本验证命令。不同版本命令略有差异我用的这个版本是./streamloader.sh --version正常输出会显示工具名称和版本号。如果这一步通过了Streamloader 的本体安装就算完成。提示如果报Error: A JNI error has occurred, please check your installation and try again基本可以断定是 JDK 版本不匹配比如用 JDK 17 去跑编译目标为 JDK 8 的旧版本包。换个低版本 JDK或者放弃旧包换新版二选一。3.4 内存参数的默认值与按需调整Streamloader 脚本里默认的 JVM 堆内存通常不大我见过默认-Xmx1g的版本。这个值对大多数批量导入场景够用因为工具本身主要是调度和分发真正吃内存的 BE 端。但如果你一个任务要同时并发导入几十个上百个文件工具端需要同时缓存多个文件的解析状态默认内存可能会触发频繁 GC进而拖慢整体导入速度。可以编辑bin/streamloader.sh找到 JVM 参数那一行改成JAVA_OPTS-Xms2g -Xmx4g改完之后重启进程生效。这里我的经验是优先调 XmxXms 没必要和 Xmx 设成一样除非你特别在意启动阶段的性能抖动。另外不要无脑调大Streamloader 的内存和 Doris 集群的内存不是一回事工具端给 4G 已经相当宽裕了再大反而可能因为本机资源竞争影响数据读取的稳定性。4. 工作原理与核心配置解析4.1 Streamloader 和 Stream Load 的关系要真正用顺 Streamloader你得先理解它和 Doris 原生 Stream Load 之间的关系。一句话概括Streamloader 是坐在 Stream Load 前面的“调度员 搬运工”。Doris 的 Stream Load 是一套 HTTP 导入接口面向单表单文件或者单表多文件的场景你发一个请求BE 节点接收数据并写入对应表。而 Streamloader 做的事情是读取你的配置文件确定“哪个文件去哪张表”然后自动生成一批 Stream Load 请求控制并发度监控每个请求的状态失败的重试全部成功后再汇总报告。所以 Streamloader 并不是绕开 Stream Load 另起炉灶它的可靠性依然建立在 Doris Stream Load 的机制之上。理解这一点之后你排错的时候就有方向了——如果导入报错信息里出现stream load error不要只在 Streamloader 配置里找原因还要去 Doris 的 FE 或 BE 日志里查真正的原因。4.2 配置文件的两大核心块source 和 targetStreamloader 的作业是通过 YAML 配置文件来描述的我习惯叫它“作业描述文件”。整个配置文件最核心的是两块source和target。一个最简示例本地文件导入source: type: local file_paths: - /data/import/user_info.csv target: database: demo table: user_info columns: [id, name, age, city]这个配置的含义非常直白把本地的user_info.csv文件导入到demo库的user_info表目标列按 id、name、age、city 的顺序映射。source块除了type: local还支持type: hdfs等数据源。如果是在 HDFS 上配置里需要额外提供 HDFS 的地址、认证信息等。target块里则可以进一步指定导入方式比如partial_columns: true搭配columns实现部分列更新或者对列的顺序做一个映射。这里有一个我经常被问到的点文件里的列顺序和目标表列顺序不一致怎么办两种方案一是用columns重新排列二是直接建一个和目标表列顺序一致的临时文件。我推荐前者因为 Streamloader 的列映射能力完全可以处理不需要额外动文件。4.3 label 机制和导入唯一性Doris 的 Stream Load 是通过 label 来做导入幂等的同一 label 的导入请求只会成功一次。Streamloader 在生成导入请求时会为每个文件自动生成 label默认格式大致是文件路径 时间戳的组合。在手动操作 Stream Load 时label 都是自己拼的拼不好就容易重复。Streamloader 把这个过程自动化了这是一个非常隐蔽但极其重要的价值点——它保证了同一批次导入中如果某个文件因为网络原因失败后重试Doris 端不会因为重复请求而产生重复数据。我在使用中习惯在配置文件里追加一个可读性前缀比如job: label_prefix: dwd_user_20240601_这样在 Doris 侧查show load输出的 label 列表时一眼就能看出这批数据是哪个任务、哪天的定位问题会快很多。4.4 并发度不是配得越高越好Streamloader 的性能调优里最核心的参数就是并发度。它决定同时向 Doris 发送多少个 Stream Load 请求。很多人第一次用的时候恨不得把它配到 20、30觉得这样导入最快但实际效果往往适得其反。原因在于Doris 的每个 Stream Load 请求在 BE 端都会占用一定的内存和 CPU 资源尤其是导入的数据需要排序、聚合时资源消耗会明显上升。如果你同时打过去 30 个请求Doris 集群的导入写入压力会骤增可能出现 BE 端 Compaction 跟不上、内存紧张、导入超时的情况最终整体吞吐量反而不如 10 个并发的时候。我自己的调参经验是先从 5 开始观察 Doris 集群的导入任务耗时和 BE 节点的 CPU、内存再逐步往上加。小集群3 BE一般 5-10 就够了大集群10 BE可以尝试 20-30但要配合监控数据看效果。别在网上抄一个数字就往上怼集群规格不同最优值差得很远。job: max_parallelism: 55. 首次实战从零导入一批本地文件5.1 准备测试数据与建表安装验证通过之后我会建议你无论如何先跑一个最小化的导入流程不要上来就动生产数据。先准备一个简单的测试表CREATE TABLE test_streamloader ( id INT, name VARCHAR(50), age INT, city VARCHAR(50) ) DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 3 PROPERTIES (replication_num 1);注意这里replication_num设了 1是为了单副本环境测试方便生产环境不要照抄默认副本数不够会导致建表报错。测试数据我直接造了一个 CSV 文件几行就行不需要大1,张三,25,北京 2,李四,30,上海 3,王五,28,广州文件保存为/tmp/test_streamloader/data.csv。注意编码Doris 默认的 Stream Load 对 UTF-8 支持最好如果你文件是 GBK 编码建议先转码否则导入后中文会乱码。5.2 编写第一个配置文件在/tmp/test_streamloader/下创建一个load.yamlsource: type: local file_paths: - /tmp/test_streamloader/data.csv target: database: demo table: test_streamloader job: max_parallelism: 2这里database对应你在 Doris 里建的库名。如果你的文件首行是列名还需要加一个配置告诉 Streamloader 跳过首行具体参数名不同版本略有差异可以在--help里找 header/skip_header/first_line_as_column之类的关键词如果有就配上没有就需要提前用tail -n 2把测试文件处理一下。5.3 执行导入命令与结果解读准备好之后执行cd /opt/streamloader ./bin/streamloader.sh \ --meta /tmp/test_streamloader/load.yaml \ --fe_host 127.0.0.1 \ --fe_port 8030 \ --username root \ --password \ --database demo这里--fe_host和--fe_port是 Doris FE 的 HTTP 服务地址--database可以理解成默认库如果配置文件的 target 里已经写了就无所谓。命令执行完后正确的结果是终端输出一个摘要包含成功导入的行数、失败的文件列表等。然后你可以在 Doris 上验证SELECT * FROM test_streamloader;能查到这三条数据说明整个链路已经完全打通。5.4 为什么导入成功但查不到数据这是很多新手必踩的坑。DSL 导入完成后Doris 的数据可见性有一个短暂的延迟因为导入的数据写入的是内存表需要通过 BE 的发布流程让数据对查询可见。正常情况下几秒钟内就能查到但如果集群负载很高或者表的副本数多、数据量巨大这个时间会变长。如果你导入完成后立刻查询发现查不到别慌过几秒再试。如果持续查不到才需要去 FE 的日志里翻有没有导入发布失败的错误。这里也顺便提一下热词里有人搜的“doris 手动触发对表的合并”。Doris 的合并机制Compaction通常是后台自动做的不需要你手动干预Streamloader 导完数据后也基本不用管合并的事。只有在特殊场景下比如你发现某个表的查询性能骤降怀疑是版本数过多才需要手动触发一次合并方法是在 Doris 里执行 SQL 或通过 API 请求对应 BE 的 compact 接口但这是另一个话题了和 Streamloader 的安装和使用没有直接关系。6. 进阶使用与性能调优6.1 多文件多表批量导入Streamloader 最爽的场景是一次导入多个文件、多个表。比如你有一个orders.csv要导入orders表又有一个users.csv要导入users表传统做法是敲两条 curl而 Streamloader 只需要在配置文件里把文件路径和目标表对应起来。source: type: local file_paths: - path: /data/import/orders.csv - path: /data/import/users.csv target: database: demo table: 有的版本支持这种多文件的写法但更常见也更清晰的做法是一个文件单独一个配置文件或者用通配符配合统一目标表。多表场景下我实际用的比较多的是把 Streamloader 配合 shell 循环来跑每个表一个 yaml用 for 循环分发管理和排查都比一个大而全的配置文件方便。6.2 断点续传导入到一半挂了怎么办Streamloader 对中断恢复的处理是它比裸写脚本强很多的地方。如果一批文件导到一半网络断掉或者进程被杀你不需要重新导入所有文件只需要找到 Streamloader 记录的进度文件从断点继续。具体行为各版本略有差异但核心机制是Streamloader 会记录每个文件的导入状态已经成功的不再重复导入只有失败或未完成的会重新执行。我实际使用中最稳的做法是重跑的时候保留原来的配置文件加上恢复模式相关的启动参数它会自动跳过已完成文件。这个能力在导大文件时价值极大。我经历过一次导入 20GB 文件、已完成 70% 时进程挂掉的情况如果是手工脚本得从零开始重导但用 Streamloader 恢复之后剩下的 30% 很快跑完。注意别把断点续传等同于“任意时刻 kill 掉都能精准续传”。它是以文件为粒度记录的也就是说如果一个文件本身还在传输过程中被中断这个文件可能整文件重导。即便如此多文件场景的收益也足够大了。6.3 结合 Doris 慢查询优化调整导入节奏有些人会把 Streamloader 导入和 Doris 的业务查询同时进行。这时候你会发现导入的并发对线上查询的影响很明显。我遇到过一个场景业务侧在早上九点有一波报表高峰同时数据团队用 Streamloader 导入前一日数据结果查询慢得不行。排查下来发现Streamloader 的批量导入生成了大量的小版本数据文件Doris 的后台合并任务在高峰期和查询抢资源。解决办法分两步第一步调整 Streamloader 的导入节奏把并发降下来避免短时间生成过多版本。第二步如果业务确实需要“边导边查”可以适当调大 Doris 的 Compaction 线程数或者把导入任务挪到查询低峰期执行。这个联动优化的思路比单纯纠结 Streamloader 参数要有效得多。导入从来不是独立的一件事它会影响整个集群的稳定性和查询性能尤其在同集群混部场景下。6.4 和其他数据导入方式的场景对比很多人会问有 Streamloader 了还需要用 Flink SQL、DataX 这些方式吗其实它们各有适用场景不是替代关系。从工具定位来看Streamloader 适合离线批量文件导入尤其是文件已经在本地或 HDFS 上的场景Flink SQL 适合实时或准实时流式写入DataX 适合异构数据源之间的同步。我做了一个简单的对比表方便你选型工具适用场景上手难度数据实时性Doris Stream Load手工 curl单表少文件应急导入低准实时Streamloader多文件多表批量导入生产级调度低准实时Flink SQL流式计算、实时数仓高实时DataX离线异构数据源同步中离线如果你只是安装完 Streamloader 后想快速让数据入仓先用 Streamloader 没问题。如果要搭建每天上千万条的持续同步管道那 Flink SQL 可能才是你需要认真评估的路线。7. 常见问题与排查技巧7.1 日志文件先找对地方很多 Streamloader 的问题排查不了不是因为难而是因为你压根没找对日志。Streamloader 的详细日志默认打印在控制台也有一部分会落到脚本指定的日志文件里。如果你的启动命令是用 nohup 跑的那更要注意把控制台输出保存下来nohup ./bin/streamloader.sh --meta load.yaml --fe_host 127.0.0.1 ... /var/log/streamloader_run.log 21 排查时先看这个日志再看 Doris 侧 FE 的日志。Streamloader 的报错信息有时候只是一个笼统的“import failed”真正的失败原因要顺着 HTTP 状态码和 Doris 返回的错误信息去 FE 日志里翻。7.2 导入时提示字段类型不匹配这是出现频率最高的报错之一。本地文件里某个字段的值和目标表的字段类型对不上。常见的是目标字段是 INT但文件里写的是空字符串或者“N/A”或者目标字段是 DATETIME但文件里日期格式是2024/06/01Doris 不认。解决办法有两个方向第一个方向在导入前用脚本对文件做清洗。比如用sed -i s/N/A//g把非数字内容替换掉或者统一日期格式。这是最直接、最可控的推荐。第二个方向利用目标表字段设计来规避。比如日期字段用 VARCHAR 类型接收到查询层再用DATE_FORMAT转换。这算是一种妥协方案简单但牺牲了一些类型约束。我见过有人专门写了个“容错导入”配置把所有字段都设成 VARCHAR 以绕过类型错误。短期看问题解决了长期看这个表下游所有查询都会因为类型问题变得很别扭不值得推广。7.3 连接 Doris 超时该调哪边的参数用 Streamloader 导入大数据量的时候偶尔会遇到类似stream load timeout或连接被重置的情况。这和 Streamloader 本身的参数关系不大核心要看 Doris 侧的 Stream Load 超时配置以及网络链路。Doris 的 Stream Load 默认超时时间受stream_load_default_timeout_second参数控制默认通常是 300 秒。如果单个文件过大BE 写入时间超过了这个阈值导入请求就会失败。你可以根据单个文件的大小和集群的写入能力在 Doris 侧适当调大这个参数ADMIN SET FRONTEND CONFIG (stream_load_default_timeout_second 600);反过来如果你遇到的是几秒内就报超时那多半不是 Doris 写入慢而是 Streamloader 所在机器到 FE 或 BE 的网络存在问题检查一下防火墙和安全组别一上来就傻傻调参数。7.4 Windows 环境下的常见坑Windows 上跑 Streamloader最容易踩的坑我整理成几条路径分隔符YAML 配置里路径尽量用正斜杠或双反斜杠避免转义问题。防火墙弹窗首次启动 Java 进程Windows 会弹防火墙提示如果不允许联网导入请求根本发不出去表现就是一直报连接超时。中文编码Windows 的默认编码可能是 GBK导致写入的 CSV 在 Doris 里显示乱码。建议把文件和配置文件都存成 UTF-8 格式。.bat脚本闪退双击.bat闪退大概率是 JAVA_HOME 没配好在 cmd 里手动执行java -version确认完再跑。7.5 导入任务能跑但 Doris 查不到数据这种情况多半不是 Streamloader 的问题而是目标表/库选错了。比如你配置文件里 target 写的database: test但你实际在 Doris 里建表建在demo库导入任务显示成功后数据自然落到了test库。另外一个可能被忽略的点是Streamloader 连接 Doris 用的账号是否对该库表有导入权限。如果权限不足任务可能报错也可能部分成功部分失败表现很迷惑。建议给 Streamloader 单独建一个账号并只授权它需要的库表权限不要图省事用 root。这样既安全排错也容易定位。8. 我的几点实操总结最后分享几个我长期使用 Streamloader 后沉淀下来的心得谈不上真理但应该能帮你少走一些弯路。第一配置文件一定要纳入版本管理。Streamloader 的配置极其简洁但它描述的是数据同步的逻辑属于数仓资产的一部分不纳入 git 管理的话哪天误改了参数都没有追溯的依据排查问题时只能干瞪眼。第二定时任务执行 Streamloader 时务必在命令外层做“导入并发互斥”控制。因为 Streamloader 断点续传依赖状态文件如果上一个任务还没跑完下一个任务又启动两个进程可能操作同一个文件导致状态错乱、重复导入或干脆报错。我用了一个简单的做法任务启动时先创建一个 pid 文件结束再删除下次启动前检查 pid 文件是否存在存在就退出。实现很土但极其有效。第三导入完成后的血缘记录也值得做。Streamloader 本身不提供数据血缘功能但我建议在每次成功导入后把配置文件、文件 MD5、时间、行数这些信息记录到一张 Doris 表里。别小看这个习惯当业务方问“这张表的数据是哪天导的、来自哪个文件”时你查这张记录表 10 秒就能给出答案不用去翻日志大海捞针。第四不用把 Streamloader 神化也不要对它嗤之以鼻。它的边界很清楚批量文件导入、断点续传、HDFS 对接这些场景它做得非常好但实时同步、复杂的数据清洗转换它做不了。选工具的核心永远是匹配场景Streamloader 作为 Doris 批量导入场景下的主力工具安装和入门都不难真正拉开差距的是你对导入链路整体架构的理解以及面对问题时能否快速定位到正确的日志和参数上。
返回列表