ARTICLE DETAIL

资讯详情

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

Docker Compose 部署 Doris 存算分离集群实战指南

Docker Compose 部署 Doris 存算分离集群实战指南 1. 为什么要在 Docker 里折腾 Doris 存算分离第一次接触 Doris 存算分离架构的时候我脑子里冒出来的第一个问题就是好好的存算一体不用为什么要拆开后来在一个日志分析项目里被现实教育了——计算节点和存储节点绑死扩容只能整体扩存储不够了加机器算力跟着浪费算力不够了加机器存储又冗余一堆。成本压不下来运维还特别别扭。存算分离就是来解决这个矛盾的把数据放到共享存储上计算节点变成无状态需要多少算力就起多少计算节点存储按实际用量独立扩展。Doris 从 3.0 版本开始正式支持存算分离模式底层依赖共享存储来存放数据计算节点通过缓存机制加速热数据访问。这个架构特别适合云原生环境也特别适合用 Docker 来快速搭建验证环境。我这次就是在一台开发机上用 Docker Compose 把整套 Doris 存算分离集群跑起来包括元数据服务、共享存储、计算节点和前端节点。你可能会问为什么不用官方的一键部署脚本原因很简单存算分离涉及多个组件的协同官方脚本对共享存储的配置有特定要求而 Docker 方式能让你完全掌控每个组件的版本、网络和挂载配置。更重要的是Docker 方式搭出来的环境可以随时销毁重建对于学习和验证来说成本极低。这篇文章适合那些已经对 Doris 有基本了解、想动手试试存算分离架构的运维和开发人员也适合想在自己机器上快速搭一套分析型数据库环境的数据工程师。整个部署过程涉及几个核心组件Doris 的 FE前端节点负责元数据管理和查询规划、BE后端节点负责数据存储和计算、共享存储层这里我用 MinIO 来模拟对象存储、以及 Docker 网络配置。我会把每一步的意图、参数选择的理由、以及我踩过的坑都讲清楚让你能直接抄作业。2. 部署前的整体设计与组件选型思路2.1 存算分离架构的核心变化存算一体模式下BE 节点既管存储又管计算数据落在本地磁盘上。存算分离模式下BE 节点变成了无状态的计算节点数据统一写到共享存储上本地磁盘只用来做缓存。这个变化带来的直接影响是BE 节点可以随时增减不用担心数据丢失存储容量和计算容量可以独立扩展多集群可以共享同一份数据。Doris 存算分离的架构里FE 仍然负责元数据管理但元数据也需要持久化到共享存储或者独立的元数据服务中。BE 节点启动时会从共享存储拉取数据分片的元信息然后按需缓存热数据到本地。计算节点之间通过一致性哈希来分配数据分片查询时如果本地缓存没有命中就从共享存储读取。这个架构对共享存储的要求比较高需要支持高吞吐的顺序读写需要兼容 S3 协议延迟要尽量低。我用 MinIO 来模拟因为它是开源的、兼容 S3 协议、Docker 部署极其简单适合做验证环境。生产环境可以换成云厂商的对象存储或者其他兼容 S3 的分布式存储。2.2 为什么选 Docker Compose 而不是单容器单容器部署 Doris 存算分离几乎是不可能的因为至少需要 FE、BE、共享存储三个组件而且它们之间有网络通信和依赖关系。Docker Compose 能在一个 YAML 文件里定义所有服务、网络和卷一条命令拉起整套环境特别适合本地验证。我对比过几种方案手动 docker run 一个个起容器网络配置和依赖顺序容易出错用 Kubernetes 太重本地开发机跑不动用官方脚本又不够灵活。Docker Compose 刚好卡在中间既有编排能力又足够轻量。而且 Compose 文件本身就是最好的文档谁拿到都能复现。2.3 版本选择和资源规划Doris 的存算分离功能在 3.0 版本之后才比较稳定我选的是 3.0.x 的稳定版镜像。MinIO 用的是最新的稳定版。Docker 和 Docker Compose 的版本建议用较新的因为涉及到一些网络和卷的特性。资源方面我给了 FE 2GB 内存、BE 4GB 内存、MinIO 1GB 内存。这是最低配了再低跑起来会很卡。磁盘至少留 20GB 给 Docker 卷和镜像。CPU 核心数越多越好BE 做查询的时候会吃满多核。组件镜像版本内存建议CPU建议磁盘建议Doris FE3.0.x2GB2核5GBDoris BE3.0.x4GB4核10GBMinIO最新稳定版1GB1核5GB注意BE 节点的内存不要低于 4GB否则启动时可能因为内存不足直接退出日志里会报 OOM 相关的错误。3. 核心细节解析与实操要点3.1 Docker 网络规划与容器互通Docker Compose 默认会创建一个 bridge 网络所有服务在同一个网络里可以通过服务名互相访问。这个特性对 Doris 部署特别重要因为 FE 和 BE 之间需要频繁通信BE 和 MinIO 之间需要传输数据。我定义了一个自定义网络doris-net子网用172.20.0.0/16。为什么要自定义子网因为默认的 Docker 网络子网可能和宿主机所在网段冲突导致容器无法访问外网或者宿主机无法访问容器。自定义子网能避免这个问题。在 Compose 文件里每个服务都加入这个网络然后通过服务名来配置连接地址。比如 BE 配置里写 MinIO 的地址就是http://minio:9000FE 配置里写 BE 的地址就是be:9060。这种服务名解析是 Docker 内置的 DNS 功能不需要额外配置。3.2 共享存储的配置要点MinIO 的部署很简单但有几个参数必须注意。首先是MINIO_ROOT_USER和MINIO_ROOT_PASSWORD这两个是访问密钥Doris 配置里要用到。其次是数据卷的挂载路径我挂到/data下确保容器重启后数据不丢。创建 bucket 的时候我建议用doris-data这个名字和 Doris 配置里的 bucket 名称保持一致。bucket 的权限要设置成私有因为这是内部数据存储不需要公开访问。MinIO 的 API 端口是 9000控制台端口是 9001。Doris 只需要 API 端口控制台端口是用来在浏览器里管理 bucket 的。两个端口都映射到宿主机方便调试。3.3 Doris FE 和 BE 的关键配置项FE 的配置里meta_dir要指向一个持久化的卷否则容器重启后元数据丢失整个集群就废了。http_port默认是 8030rpc_port默认是 9020query_port默认是 9030。这些端口都要在 Compose 文件里映射出来方便宿主机访问。BE 的配置里最关键的是storage_root_path和共享存储相关的配置。存算分离模式下BE 需要知道共享存储的地址、密钥、bucket 名称。这些配置通过be.conf文件传入。另外BE 的webserver_port默认是 8040brpc_port默认是 8060heartbeat_service_port默认是 9050。还有一个容易忽略的点FE 和 BE 的priority_networks配置。在 Docker 环境里容器可能有多个网卡Doris 需要知道用哪个网段来通信。我设置成172.20.0.0/16和 Docker 子网保持一致。# be.conf 关键配置示例 storage_root_path /opt/apache-doris/be/storage priority_networks 172.20.0.0/16 webserver_port 8040 brpc_port 8060 heartbeat_service_port 9050提示priority_networks如果配错了FE 会找不到 BE日志里会一直报心跳超时。排查的时候先看这个配置。3.4 环境变量与启动顺序控制Docker Compose 的depends_on只能控制启动顺序不能控制服务就绪状态。MinIO 启动很快但 Doris FE 启动需要几十秒BE 启动更慢。如果 BE 在 FE 还没就绪的时候就启动BE 会注册失败。我的做法是在 Compose 文件里用healthcheck来检测服务状态然后让 BE 依赖 FE 的健康状态。MinIO 的 healthcheck 可以用mc ready local命令FE 的 healthcheck 可以用curl检查 HTTP 端口。healthcheck: test: [CMD, curl, -f, http://localhost:8030/api/bootstrap] interval: 10s timeout: 5s retries: 10这个配置的意思是每 10 秒检查一次 FE 的 HTTP 端口连续失败 10 次才认为不健康。BE 的depends_on里加上condition: service_healthy就能确保 FE 完全启动后再启动 BE。4. 完整实操过程与核心环节实现4.1 环境准备与 Docker 安装检查在开始之前先确认 Docker 和 Docker Compose 已经安装好。用docker version和docker compose version检查。如果还没装Ubuntu 上可以用apt安装CentOS 上用yumWindows 和 macOS 直接装 Docker Desktop。我遇到过一个问题Docker Desktop 在 Windows 上启动时报virtualization support not detected这是因为 BIOS 里的虚拟化支持没开。进 BIOS 把 Intel VT-x 或 AMD-V 打开就行。还有一个常见错误是failed to connect to the docker api at npipe这通常是 Docker Desktop 没启动或者服务异常重启一下就好。磁盘空间也要检查docker system df看看镜像和卷占了多少空间。如果空间不够先docker system prune清理一下。4.2 编写 Docker Compose 文件Compose 文件是整个部署的核心我把它拆成几个部分来写。首先是版本声明和网络定义version: 3.8 networks: doris-net: driver: bridge ipam: config: - subnet: 172.20.0.0/16然后是 MinIO 服务services: minio: image: minio/minio:latest container_name: doris-minio networks: - doris-net ports: - 9000:9000 - 9001:9001 environment: MINIO_ROOT_USER: dorisadmin MINIO_ROOT_PASSWORD: dorisadmin123 volumes: - minio-data:/data command: server /data --console-address :9001 healthcheck: test: [CMD, mc, ready, local] interval: 10s timeout: 5s retries: 5接着是 FE 服务fe: image: apache/doris:fe-3.0.3 container_name: doris-fe networks: - doris-net ports: - 8030:8030 - 9020:9020 - 9030:9030 environment: FE_SERVERS: fe:9010 FE_ID: 1 volumes: - fe-meta:/opt/apache-doris/fe/doris-meta - ./fe.conf:/opt/apache-doris/fe/conf/fe.conf healthcheck: test: [CMD, curl, -f, http://localhost:8030/api/bootstrap] interval: 10s timeout: 5s retries: 10最后是 BE 服务be: image: apache/doris:be-3.0.3 container_name: doris-be networks: - doris-net ports: - 8040:8040 - 8060:8060 - 9050:9050 environment: FE_SERVERS: fe:9010 BE_ADDR: be:9050 volumes: - be-storage:/opt/apache-doris/be/storage - ./be.conf:/opt/apache-doris/be/conf/be.conf depends_on: fe: condition: service_healthy minio: condition: service_healthyvolumes 部分定义持久化卷volumes: minio-data: fe-meta: be-storage:这个 Compose 文件里每个服务的配置都有明确的意图。MinIO 的 healthcheck 用mc ready local来检测FE 的 healthcheck 用 HTTP 接口检测BE 依赖这两个服务的健康状态。端口映射把容器内的端口暴露到宿主机方便用 MySQL 客户端连接 Doris。4.3 配置文件的详细参数说明fe.conf 的关键配置# 元数据目录 meta_dir /opt/apache-doris/fe/doris-meta # HTTP 端口 http_port 8030 # RPC 端口 rpc_port 9020 # 查询端口 query_port 9030 # 编辑日志端口 edit_log_port 9010 # 网络优先级 priority_networks 172.20.0.0/16 # 存算分离模式 cloud_unique_id 1be.conf 的关键配置# 存储路径 storage_root_path /opt/apache-doris/be/storage # 网络优先级 priority_networks 172.20.0.0/16 # Web 服务端口 webserver_port 8040 # BRPC 端口 brpc_port 8060 # 心跳端口 heartbeat_service_port 9050 # 共享存储配置 enable_file_cache true file_cache_path /opt/apache-doris/be/storage/cache # S3 兼容存储配置 aws_s3_endpoint http://minio:9000 aws_s3_access_key dorisadmin aws_s3_secret_key dorisadmin123 aws_s3_bucket doris-data aws_s3_region us-east-1这些配置里cloud_unique_id是存算分离模式的标识每个集群唯一。enable_file_cache开启本地缓存能显著提升热数据查询性能。file_cache_path指定缓存目录建议放在 SSD 上。注意aws_s3_region虽然 MinIO 不强制要求但 Doris 的 S3 客户端需要这个参数随便填一个合法的区域名就行比如us-east-1。4.4 启动集群与初始化操作配置文件准备好之后在 Compose 文件所在目录执行docker compose up -d这个命令会按依赖顺序启动所有服务。启动完成后用docker compose ps查看状态确保所有服务都是healthy。接下来要创建 MinIO 的 bucket。用mc客户端或者直接访问http://localhost:9001登录控制台创建。bucket 名称必须是doris-data和 be.conf 里的配置一致。然后进入 FE 容器添加 BE 节点docker exec -it doris-fe bash mysql -h 127.0.0.1 -P 9030 -u root在 MySQL 客户端里执行ALTER SYSTEM ADD BACKEND be:9050;这个命令把 BE 节点注册到 FE 中。执行完后用SHOW BACKENDS;查看状态如果Alive是true说明 BE 注册成功。4.5 验证存算分离是否生效验证存算分离是否生效最直接的方法是建表插入数据然后看数据是否写到了 MinIO 里。先建一个测试库和表CREATE DATABASE test_db; USE test_db; CREATE TABLE test_table ( id INT, name VARCHAR(50) ) DISTRIBUTED BY HASH(id) BUCKETS 3 PROPERTIES ( replication_num 1 );插入几条数据INSERT INTO test_table VALUES (1, alice), (2, bob), (3, charlie);然后去 MinIO 控制台看doris-databucket 里有没有文件生成。如果有说明数据确实写到了共享存储上。再查一下数据SELECT * FROM test_table;如果能查到数据说明整个链路是通的。还可以通过 BE 的 Web 界面查看缓存状态访问http://localhost:8040里面有缓存命中率和存储使用的统计信息。5. 常见问题与排查技巧实录5.1 BE 注册失败或心跳超时这是最常见的问题。现象是SHOW BACKENDS;里 BE 的Alive是false或者 FE 日志里一直报心跳超时。排查思路分三步先看网络通不通再检查priority_networks配置最后看端口有没有被占用。网络排查用docker exec -it doris-be ping fe如果能 ping 通说明网络没问题。priority_networks配置错了的话BE 会用错误的网卡 IP 去注册FE 自然找不到。端口占用用netstat -tlnp检查。我遇到过一次 BE 注册失败原因是be.conf里priority_networks写成了172.20.0.0/24但实际子网是172.20.0.0/16网段不匹配导致 BE 选错了 IP。改成/16之后就好了。5.2 共享存储连接失败现象是 BE 启动时报 S3 连接错误或者建表时提示存储不可用。排查的时候先确认 MinIO 的 bucket 是否存在再检查密钥和 endpoint 配置。用docker exec -it doris-be curl http://minio:9000测试网络连通性。如果返回 XML 格式的错误信息说明网络是通的问题在认证配置上。检查aws_s3_access_key和aws_s3_secret_key是否和 MinIO 的环境变量一致。还有一个坑是 bucket 名称大小写敏感。MinIO 的 bucket 名称必须全小写如果写成Doris-Data会创建失败。Doris 配置里的 bucket 名称也要和实际创建的一致。5.3 内存不足导致容器退出BE 节点对内存比较敏感如果宿主机内存不够BE 容器会直接被 OOM Killer 杀掉。用docker logs doris-be看日志如果最后几行是Killed或者Out of memory就是内存不足。解决办法有两个一是给 BE 分配更多内存在 Compose 文件里加mem_limit或者deploy.resources.limits.memory二是调低 BE 的内存使用上限在be.conf里设置mem_limit参数。我一般建议宿主机至少留 8GB 内存给 Docker。5.4 查询性能不达预期存算分离模式下如果本地缓存没命中查询需要从共享存储拉数据延迟会比存算一体高。如果发现查询慢先看缓存命中率。BE 的 Web 界面里有缓存统计命中率低于 80% 就说明缓存配置有问题。检查file_cache_path是否指向了 SSD缓存目录的磁盘 IO 性能直接影响查询速度。另外enable_file_cache必须设为true否则所有查询都走共享存储性能会很差。还有一个容易忽略的点是数据分桶数。分桶太少会导致单个分片数据量过大缓存效率低。建表时根据数据量合理设置分桶数一般建议每个分片 1GB 左右。问题现象可能原因排查方法解决方案BE 注册失败网络不通或 priority_networks 错误ping 测试、检查配置修正网段配置存储连接失败密钥错误或 bucket 不存在curl 测试、检查 MinIO修正密钥和 bucket 名容器退出内存不足查看容器日志增加内存或调低上限查询慢缓存未命中或磁盘 IO 差查看缓存命中率开启缓存、换 SSD5.5 实操心得与避坑清单踩了这么多坑我总结了几条经验。第一Compose 文件里的 healthcheck 一定要配不然启动顺序不可控BE 大概率注册失败。第二所有持久化卷都要显式声明容器重启后数据不丢。第三MinIO 的密钥不要用默认的虽然验证环境无所谓但养成好习惯。第四BE 的缓存目录一定要放在性能好的磁盘上机械硬盘会拖垮查询性能。还有一个技巧如果反复部署失败先把所有容器和卷删掉重来。docker compose down -v会删除容器和卷然后docker compose up -d重新拉起。这样能避免残留配置导致的奇怪问题。提示docker compose down -v会删除所有数据卷生产环境慎用。验证环境随便删。6. 集群扩展与后续优化方向6.1 增加 BE 节点实现横向扩展存算分离最大的优势就是计算节点可以随时扩展。在 Compose 文件里复制一份 BE 服务配置改一下容器名和端口映射然后docker compose up -d就能拉起新的 BE 节点。新节点启动后在 FE 里执行ALTER SYSTEM ADD BACKEND注册数据分片会自动重新平衡。扩展的时候要注意新 BE 节点的be.conf里priority_networks和共享存储配置必须和现有节点一致。端口不能冲突宿主机映射端口要错开。比如第一个 BE 映射 8040第二个就映射 8041。6.2 缓存策略调优存算分离的性能很大程度上取决于缓存策略。Doris 支持按需缓存和预加载两种模式。按需缓存是查询时自动缓存热数据预加载是提前把数据拉到本地。对于频繁查询的热数据预加载能显著降低首次查询延迟。缓存大小也要合理设置。file_cache_path所在磁盘的容量决定了缓存上限一般建议缓存容量是热数据量的 1.5 倍。太小了缓存命中率低太大了浪费磁盘。6.3 监控与日志收集生产环境一定要配监控。Doris 的 FE 和 BE 都暴露了 Prometheus 格式的指标接口FE 的接口是http://fe:8030/metricsBE 的是http://be:8040/metrics。用 Prometheus 抓取这些指标再用 Grafana 做可视化能实时看到集群状态。日志方面FE 和 BE 的日志都在容器内的/opt/apache-doris/*/log目录下。可以用 Docker 的日志驱动把日志转发到集中式日志系统或者直接挂载到宿主机目录。6.4 从验证环境到生产环境的差距Docker Compose 搭出来的环境适合验证和学习但直接上生产还有几个差距要补。首先是高可用FE 需要至少三个节点做选举BE 需要多副本。其次是存储的可靠性MinIO 单节点没有冗余生产要用分布式部署或者云对象存储。最后是网络和安全生产环境需要配置 TLS 和访问控制。我个人的建议是先用 Docker Compose 把功能跑通理解存算分离的工作原理和配置要点然后再根据实际需求设计生产架构。Docker 环境里踩过的坑在生产环境里大概率还会遇到提前熟悉能省很多时间。最后分享一个小技巧Doris 的 FE 和 BE 都支持通过环境变量覆盖配置在 Compose 文件里用environment字段就能动态调整参数不用改配置文件。这个特性在调试的时候特别方便改完重启容器就生效。
返回列表