概述
文章目录
- 第 1 章 Doris 简介
- 1.1 Doris 概述
- 1.2 使用场景
- 1.3 技术概述
- 1.4 元数据结构
- 1.5 数据分发
- 1.6 OLAP与OLTP
- 1.7 环境准备
- 第2章 编译与安装
- 2.1 安装Docker环境
- 2.2 端口说明
- 2.3 Doris编译
- 2.4 集群部署
- 2.4.1 创建目录并拷贝编译后的文件
- 2.4.2 部署FE
- 2.4.3 启动FE报错
- 2.4.4 部署BE
- 2.4.5 在FE中添加BE节点
- 2.4.6 启动BE(三个节点)
- 2.4.7 启动BE报错
- 2.4.8 部署 FS_Broker(可选)
- 第3章 Supervisor配置drois
- 3.1 安装supervisor
- 3.2 配置文件解析
- 3.2.1 主配置文件解析
- 3.2.2 子配置文件解析
- 3.1.1 配置FE自启动
- 3.1.2 配置BE自启动
- 3.1.3 配置broker自启动
- 3.2 配置webui监控
- 3.3 集群服务统一监控
- 3.3.1 部署
- 3.3.2 将nginx纳入集群统一管理
- 第4章 集群扩容与缩容
- 4.1 FE扩容与缩容
- 4.2 BE扩容与缩容
- 4.3 Broaker扩容
- 4.4 集群启动脚本
第 1 章 Doris 简介
1.1 Doris 概述
Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库,以极速易用的特点被人们所熟知,仅需亚秒级响应时间即可返回海量数据下的查询结果,不仅可以支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。基于此,Apache Doris 能够较好的满足报表分析、即席查询、统一数仓构建、数据湖联邦查询加速等使用场景,用户可以在此之上构建用户行为分析、AB 实验平台、日志检索分析、用户画像分析、订单分析等应用。
Apache Doris 最早是诞生于百度广告报表业务的 Palo 项目,2017 年正式对外开源,2018 年 7 月由百度捐赠给 Apache 基金会进行孵化,之后在 Apache 导师的指导下由孵化器项目管理委员会成员进行孵化和运营。目前 Apache Doris 社区已经聚集了来自不同行业近百家企业的 300 余位贡献者,并且每月活跃贡献者人数也接近 100 位。 2022 年 6 月,Apache Doris 成功从 Apache 孵化器毕业,正式成为 Apache 顶级项目(Top-Level Project,TLP)
1.2 使用场景
如下图所示,数据源经过各种数据集成和加工处理后,通常会入库到实时数仓 Doris 和离线湖仓(Hive, Iceberg, Hudi 中),Apache Doris 被广泛应用在以下场景中
上图是整个Doris的具体使用场景,主要是它的接收数据源,以及它的一个整体的模块,还有最后它的一个可视化的呈现。后面会有一张更详细的图去介绍它整个的来源,以及最后可以输出的数据流向。
一般情况下,用户的原始数据,比如日志或者在事务型数据库中的数据,经过流式系统或离线处理后,导入到Doris中以供上层的报表工具或者数据分析师查询使用。
- 报表分析
- 实时看板 (Dashboards)
- 面向企业内部分析师和管理者的报表
- 面向用户或者客户的高并发报表分析(Customer Facing Analytics)。比如面向网站主的站点分析、面向广告主的广告报表,并发通常要求成千上万的 QPS ,查询延时要求毫秒级响应。著名的电商公司京东在广告报表中使用 Apache Doris ,每天写入 100 亿行数据,查询并发 QPS 上万,99 分位的查询延时 150ms。
- 即席查询(Ad-hoc Query):面向分析师的自助分析,查询模式不固定,要求较高的吞吐。小米公司基于 Doris
构建了增长分析平台(Growing Analytics,GA),利用用户行为数据对业务进行增长分析,平均查询延时 10s,95
分位的查询延时 30s 以内,每天的 SQL 查询量为数万条。 - 统一数仓构建 :一个平台满足统一的数据仓库建设需求,简化繁琐的大数据软件栈。海底捞基于 Doris 构建的统一数仓,替换了原来由
Spark、Hive、Kudu、Hbase、Phoenix 组成的旧架构,架构大大简化。 - 数据湖联邦查询:通过外表的方式联邦分析位于 Hive、Iceberg、Hudi 中的数据,在避免数据拷贝的前提下,查询性能大幅提升。
1.3 技术概述
Doris整体架构如下图所示,Doris 架构非常简单,只有两类进程
- Frontend(FE),主要负责用户请求的接入、查询解析规划、元数据的管理、节点管理相关工作。 FE主要有两个角色,一个是follower,另一个是observer。多个follower组成选举组,会选出一个master,master是follower的一个特例,Master跟follower,主要是用来达到元数据的高可用,保证单节点宕机的情况下,元数据能够实时地在线恢复,而不影响整个服务。
- 另一个是 Backend(BE),主要负责数据存储、查询计划的执行。Observer节点仅从 leader 节点进行元数据同步,不参与选举。可以横向扩展以提供元数据的读服务的扩展性。
这两类进程都是可以横向扩展的,单集群可以支持到数百台机器,数十 PB 的存储容量。并且这两类进程通过一致性协议来保证服务的高可用和数据的高可靠。这种高度集成的架构设计极大的降低了一款分布式系统的运维成本。
在使用接口方面,Doris 采用 MySQ L 协议,高度兼容 MySQL 语法,支持标准 SQL,用户可以通过各类客户端工具来访问 Doris,并支持与 BI 工具的无缝对接。
在存储引擎方面,Doris 采用列式存储,按列进行数据的编码压缩和读取,能够实现极高的压缩比,同时减少大量非相关数据的扫描,从而更加有效利用 IO 和 CPU 资源。
Doris 也支持比较丰富的索引结构,来减少数据的扫描:
- Sorted Compound Key
Index,可以最多指定三个列组成复合排序键,通过该索引,能够有效进行数据裁剪,从而能够更好支持高并发的报表场景 - Z-order Index :使用 Z-order 索引,可以高效对数据模型中的任意字段组合进行范围查询
- Min/Max :有效过滤数值类型的等值和范围查询
- Bloom Filter :对高基数列的等值过滤裁剪非常有效
- Invert Index :能够对任意字段实现快速检索
在存储模型方面,Doris 支持多种存储模型,针对不同的场景做了针对性的优化:
-
Aggregate Key 模型:相同 Key 的 Value 列合并,通过提前聚合大幅提升性能
-
Unique Key 模型:Key 唯一,相同 Key 的数据覆盖,实现行级别数据更新
-
Duplicate Key 模型:明细数据模型,满足事实表的明细存储
Doris 也支持强一致的物化视图,物化视图的更新和选择都在系统内自动进行,不需要用户手动选择,从而大幅减少了物化视图维护的代价。
在查询引擎方面,Doris 采用 MPP 的模型,节点间和节点内都并行执行,也支持多个大表的分布式 Shuffle Join,从而能够更好应对复杂查询。
Doris 查询引擎是向量化的查询引擎,所有的内存结构能够按照列式布局,能够达到大幅减少虚函数调用、提升 Cache 命中率,高效利用 SIMD 指令的效果。在宽表聚合场景下性能是非向量化引擎的 5-10 倍。
oris 采用了 Adaptive Query Execution 技术, 可以根据 Runtime Statistics 来动态调整执行计划,比如通过 Runtime Filter 技术能够在运行时生成生成 Filter 推到 Probe 侧,并且能够将 Filter 自动穿透到 Probe 侧最底层的 Scan 节点,从而大幅减少 Probe 的数据量,加速 Join 性能。Doris 的 Runtime Filter 支持 In/Min/Max/Bloom Filter。
在优化器方面 Doris 使用 CBO 和 RBO 结合的优化策略,RBO 支持常量折叠、子查询改写、谓词下推等,CBO 支持 Join Reorder。目前 CBO 还在持续优化中,主要集中在更加精准的统计信息收集和推导,更加精准的代价模型预估等方面。
Doris主要整合了Google Mesa(数据模型),Apache Impala(MPP Query Engine)和Apache ORCFile (存储格式,编码和压缩) 的技术。
为什么要将这三种技术整合? -
Mesa可以满足我们许多存储需求的需求,但是Mesa本身不提供SQL查询引擎。
-
Impala是一个非常好的MPP SQL查询引擎,但是缺少完美的分布式存储引擎。
-
自研列式存储:存储层对存储数据的管理通过storage_root_path路径进行配置,路径可以是多个。存储目录下一层按照分桶进行组织,分桶目录下存放具体的tablet,按照tablet_id命名子目录。
因此选择了这三种技术的组合。
1.4 元数据结构
Doris采用Paxos协议以及Memory+ Checkpoint + Journal的机制来确保元数据的高性能及高可靠。元数据的每次更新,都会遵照以下几步:
- 首先写入到磁盘的日志文件中
- 然后再写到内存中
- 最后定期checkpoint到本地磁盘上
相当于是一个纯内存的一个结构,也就是说所有的元数据都会缓存在内存之中,从而保证FE在宕机后能够快速恢复元数据,而且不丢失元数据。
Leader、follower和 observer它们三个构成一个可靠的服务,如果发生节点宕机的情况,一般是部署一个leader两个follower,目前来说基本上也是这么部署的。就是说三个节点去达到一个高可用服务。单机的节点故障的时候其实基本上三个就够了,因为FE节点毕竟它只存了一份元数据,它的压力不大,所以如果FE太多的时候它会去消耗机器资源,所以多数情况下三个就足够了,可以达到一个很高可用的元数据服务。
1.5 数据分发
- 数据主要都是存储在BE里面,BE节点上物理数据的可靠性通过多副本来实现,默认是3副本,副本数可配置且可随时动态调整,满足不同可用性级别的业务需求。FE调度BE上副本的分布与补齐。
- 如果说用户对可用性要求不高,而对资源的消耗比较敏感的话,我们可以在建表的时候选择建两副本或者一副本。比如在百度云上我们给用户建表的时候,有些用户对它的整个资源消耗比较敏感,因为他要付费,所以他可能会建两副本。但是我们一般不太建议用户建一副本,因为一副本的情况下可能一旦机器出问题了,数据直接就丢了,很难再恢复。一般是默认建三副本,这样基本可以保证一台机器单机节点宕机的情况下不会影响整个服务的正常运作。
1.6 OLAP与OLTP
OLTP是 Online Transaction Processing 的简称;OLAP 是 OnLine Analytical Processing 的简称
- OLTP的查询一般只会访问少量的记录,且大多时候都会利用索引。比如最常见的基于主键的 CRUD 操作
- OLAP 的查询一般需要 Scan 大量数据,大多时候只访问部分列,聚合的需求(Sum,Count,Max,Min
等)会多于明细的需求(查询原始的明细数据)
总结
- 数据压缩率Clickhouse好
- ClickHouse单表查询性能优势巨大
- Join查询两者各有优劣,数据量小情况下Clickhouse好,数据量大Doris好
- Doris对SQL支持情况要好
1.7 环境准备
(1)FE 的磁盘空间主要用于存储元数据,包括日志和 image。通常从几百 MB 到几个
GB 不等。
(2)BE 的磁盘空间主要用于存放用户数据,总磁盘空间按用户总数据量* 3(3 副本)
计算,然后再预留额外 40%的空间用作后台 compaction 以及一些中间数据的存放。
(3)一台机器上可以部署多个 BE 实例,但是只能部署一个 FE。如果需要 3 副本数
据,那么至少需要 3 台机器各部署一个 BE 实例(而不是 1 台机器部署 3 个 BE 实例)。多
个 FE 所在服务器的时钟必须保持一致(允许最多 5 秒的时钟偏差)
(4)测试环境也可以仅适用一个 BE 进行测试。实际生产环境,BE 实例数量直接决定
了整体查询延迟。
(5)所有部署节点关闭 Swap。
(6)FE 节点数据至少为 1(1 个 Follower)。当部署 1 个 Follower 和 1 个 Observer 时,可以实现读高可用。当部署 3 个 Follower 时,可以实现读写高可用(HA)。
(7)Follower 的数量必须为奇数,Observer 数量随意。
(8)根据以往经验,当集群可用性要求很高时(比如提供在线业务),可以部署 3 个Follower 和 1-3 个 Observer。如果是离线业务,建议部署 1 个 Follower 和 1-3 个 Observer。
(9)Broker 是用于访问外部数据源(如 HDFS)的进程。通常,在每台机器上部署一个 broker 实例即可。
- 通常我们建议 10 ~ 100 台左右的机器,来充分发挥 Doris 的性能(其中 3 台部署 FE(HA),剩余的部署 BE)
- 当然,Doris的性能与节点数量及配置正相关。在最少4台机器(一台 FE,三台 BE,其中一台 BE 混部一个 Observer FE提供元数据备份),以及较低配置的情况下,依然可以平稳的运行 Doris。
- 如果 FE 和 BE 混部,需注意资源竞争问题,并保证元数据目录和数据目录分属不同磁盘。
Broker 部署
Broker 是用于访问外部数据源(如 hdfs)的进程。通常,在每台机器上部署一个 broker 实例即可。
第2章 编译与安装
安装 Doris,需要先通过源码编译,主要有两种方式:使用 Docker 开发镜像编译(推
荐)、直接编译。
2.1 安装Docker环境
Docker要求Centos系统的内核版本高于3.1.0,首先查看系统内核内核版本是否满足
uname -r
- yum 包更新到最新
sudo yum update
- 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2
- 设置yum源为阿里云
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 安装docker
yum install docker-ce -y
- 安装后查看docker版本
docker -v
- 设置开机自启
systemctl is-enabled docker.service 检查服务是否开机启动
systemctl enable docker.service 将服务配置成开机启动
systemctl start docker.service 启动服务
- 关闭swap
# 永久关闭
vim /etc/fstab
注释掉swap行
#/dev/mapper/centos-swap swap swap defaults 0 0
2.2 端口说明
注意点:
当部署多个 FE 实例时,要保证 FE 的 http_port 配置相同。
部署前请确保各个端口在应有方向上的访问权限。
2.3 Doris编译
- 下载源码并解压到/opt/目录
官方链接
https://archive.apache.org/dist/doris/1.1/
百度云盘
链接:https://pan.baidu.com/s/1eNcMR3c8o1VOttvJ0ecThA?pwd=yyds
[root@node2 opt]# tar-zxvf apache-doris-0.15.0-incubating-src.tar.gz
- 拉取docker镜像
docker pull apache/doris:build-env-for-1.1.0
- 挂载本地目录镜像
以挂载本地 Doris 源码目录的方式运行镜像,这样编译的产出二进制文件会存储在宿主
机中,不会因为镜像退出而消失。同时将镜像中 maven 的 .m2 目录挂载到宿主机目录,以
防止每次启动镜像编译时,重复下载 maven 的依赖库。
docker run -it
-v /opt/.m2:/root/.m2
-v /opt/apache-doris-0.15.0-incubating-src/:/root/apache-doris-0.15.0-incubating-src/
apache/incubator-doris:build-env-for-0.15.0
- 切换到JDK8
[root@node0 opt]# docker run -it
> -v /opt/apache-maven-3.8.6/data:/root/.m2
> -v /opt/apache-doris-1.1.0-src/:/root/doris-1.1.0/apache-doris-1.1.0-src/
> apache/doris:build-env-for-1.1.0
[root@6bcfc5e4af15 ~]# ll
total 8
-rw------- 1 root root 3416 Nov 13 2020 anaconda-ks.cfg
drwxr-xr-x 3 root root 4096 Oct 29 06:13 doris-1.1.0
[root@6bcfc5e4af15 ~]# cd doris-1.1.0/
[root@6bcfc5e4af15 doris-1.1.0]# ll
total 4
drwxrwxr-x 22 root root 4096 Jul 10 13:14 apache-doris-1.1.0-src
[root@6bcfc5e4af15 doris-1.1.0]# java -version
openjdk version "11.0.15" 2022-04-19 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.15+9-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.15+9-LTS, mixed mode, sharing)
[root@6bcfc5e4af15 doris-1.1.0]# alternatives --set java java-1.8.0-openjdk.x86_64
[root@6bcfc5e4af15 doris-1.1.0]# alternatives --set javac java-1.8.0-openjdk.x86_64
[root@6bcfc5e4af15 doris-1.1.0]# export JAVA_HOME=/usr/lib/jvm/java-1.8.0
[root@6bcfc5e4af15 doris-1.1.0]# echo $JAVA_HOME
/usr/lib/jvm/java-1.8.0
[root@6bcfc5e4af15 doris-1.1.0]# java -version
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)
[root@6bcfc5e4af15 doris-1.1.0]#
- 修改maven配置
vim /opt/apache-doris-0.15.0-incubating-src/fe/pom.xml
在<repositories>标签下添加:
<repository>
<id>aliyun</id>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
- 编译 Doris
编译过程会下载很多依赖,第一次会非常慢
#如果是第一次使用 build-env-for-0.15.0 或之后的版本,第一次编译的时候要使用如下命令:
#进入到目录
cd apache-doris-0.15.0-incubating-src
[root@4b63e155ebce apache-doris-0.15.0-incubating-src]# sh build.sh --clean --be --fe --ui
[root@4b63e155ebce apache-doris-0.15.0-incubating-src]# sh build.sh
2.4 集群部署
因测试环境资源有限,FE和BE节点部署在相同服务器,生产环境建议分开
2.4.1 创建目录并拷贝编译后的文件
- 创建目录并拷贝编译后的文件
mkdir -p /opt/apache-doris-1.1.0
cp -r /opt/apache-doris-1.1.0-src/output/* /opt/apache-doris-1.1.0
- 修改可打开文件数(每个节点)
vim /etc/security/limits.conf
#所有用户 类型 打开文件数 数量
* soft nofile 65535
* hard nofile 65535
#所有用户 类型 打开进程数 数量
* soft nproc 65535
* hard nproc 65535
2.4.2 部署FE
- 创建 fe 元数据存储的目录
mkdir -p /opt/apache-doris-0.15.0/fe/doris-meta
- 修改fe的配置文件
vim /opt/apache-doris-0.15.0/fe/conf/fe.conf
#配置文件中指定元数据路径:
meta_dir = /opt/apache-doris-0.15.0/fe/doris-meta
#修改绑定 ip(每台机器修改成自己的 ip)
priority_networks = 192.168.33.101/24
注意:
⚫ 生产环境强烈建议单独指定目录不要放在 Doris 安装目录下,最好是单独的磁盘(如果有 SSD 最好)。
⚫ 如果机器有多个 ip, 比如内网外网, 虚拟机 docker 等, 需要进行 ip 绑定,才能正确识 别。
⚫ JAVA_OPTS 默认 java 最大堆内存为 4GB,建议生产环境调整至 8G 以上。
- 启动master FE
sh /opt/doris/fe/bin/start_fe.sh --daemon
2.4.3 启动FE报错
我们找到这个文件的109行,加上中括号。
这个是jdk8环境变量路径配置的不对。
#找当前JAVA_HOME路径
echo $JAVA_HOME
#修改//etc/profile.d/文件夹里sh文件夹里的java环境变量配置
2.4.4 部署BE
分发BE
scp -r /opt/apache-doris-0.15.0/be node2:/opt/apache-doris-0.15.0
scp -r /opt/apache-doris-0.15.0/be node3:/opt/apache-doris-0.15.0
创建目录
配置文件为 be/conf/be.conf。主要是配置 storage_root_path:数据存放目录。默认在be/storage下,需要手动创建该目录。多个路径之间使用 ; 分隔(最后一个目录后不要加 ;)
mkdir -p /opt/apache-doris-1.1.0/be/storage1
mkdir -p /opt/apache-doris-1.1.0/be/storage2
修改BE的配置文件
vim /opt/apache-doris-0.15.0/be/conf/be.conf
#修改配置文件中指定数据存放路径
storage_root_path = /opt/apache-doris-0.15.0/be/doris-storage1;/opt/apache-doris-0.15.0/be/doris-storage2
#修改绑定 ip(每台机器修改成自己的 ip)
priority_networks = 192.168.33.101/24
⚫ 可以通过路径区别存储目录的介质,HDD 或 SSD。可以添加容量限制在每个路径的末
尾,通过英文状态逗号,隔开,如:
storage_root_path=/home/disk1/doris.HDD,50;/home/disk2/doris.SSD,10;/home/disk2/doris
说明:
/home/disk1/doris.HDD,50,表示存储限制为 50GB,HDD;
/home/disk2/doris.SSD,10,存储限制为 10GB,SSD;
/home/disk2/doris,存储限制为磁盘最大容量,默认为 HDD
2.4.5 在FE中添加BE节点
检查当前系统是否安装过 MySQL
删除操作系统自带的mysql库文件
rpm -qa | grep mariadb
rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64
安装mysql-client
#切换到mysql的存放目录
rpm -ivh ./*
使用 MySQL Client 连接 FE
#第一次连接
mysql -h node1 -P 9030 -uroot
#默认 root 无密码,通过以下命令修改 root 密码。
SET PASSWORD FOR 'root' = PASSWORD('123456');
mysql -h 127.0.0.1 -P 9030 -uroot -p123456
mysql -h node2 -P 9030 -uroot -p123456
报错请先启动FE
因为这里用到了FE的9030端口。
sh /opt/apache-doris-0.15.0/fe/bin/start_fe.sh --daemon
使用navicat连接
添加BE
ALTER SYSTEM ADD BACKEND "node1:9050";
ALTER SYSTEM ADD BACKEND "node2:9050";
ALTER SYSTEM ADD BACKEND "node3:9050";
#查看be状态
SHOW PROC '/backends';
FE前端访问地址
http://192.168.33.102:8030/system?path=//frontends
http://192.168.33.102:8030/frontend
2.4.6 启动BE(三个节点)
#启动be
sh /opt/apache-doris-0.15.0/be/bin/start_be.sh --daemon
#查看 BE 状态
mysql -h node2 -P 9030 -uroot -p
SHOW PROC '/backends';
在启动完be后,就可以用navicat直接访问了,新建查询如图所示
2.4.7 启动BE报错
错误提示cluster id无效,那么就把be存储目录storage下的相关文件cluster_id删除,注意前面我们BE配置了两个storage目录,里面的cluster id文件都要删除
[root@node3 be]# bin/stop_be.sh
stop palo_be, and remove pid file.
[root@node3 be]# ls
bin conf lib log storage www
[root@node3 be]# rm -rf storage/cluster_id
[root@node3 be]# sh bin/start_be.sh --daemon
2.4.8 部署 FS_Broker(可选)
Broker 以插件的形式,独立于 Doris 部署。如果需要从第三方存储系统导入数据,需要部署相应的 Broker,默认提供了读取 HDFS、百度云 BOS 及 Amazon S3 的 fs_broker。fs_broker 是无状态的,建议每一个 FE 和 BE 节点都部署一个 Broker。
docker编译
首先查看有没有后台运行的drois容器,如果有,重新进入容器
docker attach 容器id
如果没有,则执行以下命令
docker run -it
-v /opt/.m2:/root/.m2
-v /opt/apache-doris-0.15.0-incubating-src/:/root/apache-doris-0.15.0-incubating-src/
apache/incubator-doris:build-env-for-0.15.0
我们之前编译FE的时候,设置了容器内的环境变量为JDK8,但是退出后再次进入JDK版本回滚到JDK11,所以这里需要再次设置。
[root@69a41d96c87e apache-doris-0.15.0-incubating-src]# alternatives --set java java-1.8.0-openjdk.x86_64
[root@69a41d96c87e apache-doris-0.15.0-incubating-src]# alternatives --set javac java-1.8.0-openjdk.x86_64
[root@69a41d96c87e apache-doris-0.15.0-incubating-src]# export JAVA_HOME=/usr/lib/jvm/java-1.8.0
[root@69a41d96c87e apache-doris-0.15.0-incubating-src]# echo $JAVA_HOME
/usr/lib/jvm/java-1.8.0
编译,在线编译比较费时间,很可能会失败,在这里提供百度网盘doris0.15源码和maven仓库压缩包。
#进入到源码目录
cd apache-doris-0.15.0-incubating-src/fs_brokers/apache_hdfs_broker
#编译
sh build.sh
本地编译成功标志
拷贝
拷贝源码 fs_broker 的 output 目录下的相应 Broker 目录到需要部署的所有节点上,改名为: apache_hdfs_broker。建议和 BE 或者 FE 目录保持同级。
cp -r /opt/apache-doris-1.1.0-src/fs_brokers/apache_hdfs_broker/output/apache_hdfs_broker /opt/apache-doris-1.1.0
添加broker
使用mysql客户端访问pe,添加broker节点
mysql -uroot -h node2 -P 9030 -p123456
要让 Doris 的 FE 和 BE 知道 Broker 在哪些节点上,通过 sql 命令添加 Broker 节点列表
ALTER SYSTEM ADD BROKER broker_name "node1:8000","node2:8000","node3:8000";
其中 host 为 Broker 所在节点 ip;port 为 Broker 配置文件中的 broker_ipc_port。
启动broker
sh /opt/apache-doris-0.15.0/apache_hdfs_broker/bin/start_broker.sh --daemon
第3章 Supervisor配置drois
在生产环境中,所有实例都应使用守护进程启动,以保证进程退出后,会被自动拉起,如 Supervisor。如需使用守护进程启动,在 0.9.0 及之前版本中,需要修改各个 start_xx.sh 脚本,去掉最后的 & 符号。从 0.10.0 版本开始,直接调用 sh start_xx.sh 启动即可。
Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。
3.1 安装supervisor
#安装
yum -y install epel-release
yum -y install supervisor
#修改主配置文件
vi /etc/supervisord.conf
minfds=655350 ; (min. avail startup file descriptors;default 1024)
minprocs=65535 ; (min. avail process descriptors;default 200)
#开机自启动
systemctl enable supervisord
#启动supervisord服务
systemctl start supervisord
#查看supervisord服务状态
systemctl status supervisord
#重启supervisord
systemctl restart supervisord
命令扩充
# supervisorctl status:查看进程的状态
supervisorctl status
status <name> Get status for a single process
status <gname>:* Get status for all processes in a group
status <name> <name> Get status for multiple named processes
status Get all process status info
# supervisorctl start 启动进程
start <name> Start a process
start <gname>:* Start all processes in a group
start <name> <name> Start multiple processes or groups
start all Start all processes
# supervisorctl stop 停止进程
stop <name> Stop a process
stop <gname>:* Stop all processes in a group
stop <name> <name> Stop multiple processes or groups
stop all Stop all processes
# supervisorctl restart 重启进程
restart <name> Restart a process
restart <gname>:* Restart all processes in a group
restart <name> <name> Restart multiple processes or groups
restart all Restart all processes
Note: restart does not reread config files. For that, see reread and update.
# supervisorctl update 配置文件修改后可以使用该命令加载新的配置
update Reload config and add/remove as necessary, and will restart affected programs
update all Reload config and add/remove as necessary, and will restart affected programs
update <gname> [...] Update specific groups
supervisorctl reload: 重新启动配置中的所有程序
常见的命令如下:
supervisord 初始启动Supervisord,启动、管理配置中设置的进程
supervisorctl stop programxxx 停止某一个进程(programxxx),programxxx为[program:chatdemon]里配置的值,这个示例就是chatdemon
supervisorctl start programxxx 启动某个进程
supervisorctl restart programxxx 重启某个进程
supervisorctl stop groupworker 重启所有属于名为groupworker这个分组的进程(start,restart同理)
supervisorctl stop all 停止全部进程,注:start、restart、stop都不会载入最新的配置文件
supervisorctl reload 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程
supervisorctl update 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启。注意:显示用stop停止掉的进程,用reload或者update都不会自动重启
3.2 配置文件解析
3.2.1 主配置文件解析
[unix_http_server]
file=/tmp/supervisor.sock ;UNIX socket 文件,supervisorctl 会使用
;chmod=0700 ;socket文件的mode,默认是0700
;chown=nobody:nogroup ;socket文件的owner,格式:uid:gid
;[inet_http_server] ;HTTP服务器,提供web管理界面
;port=9001 ;Web管理后台运行的IP和端口,如果开放到公网,需要注意安全性
;username=user ;登录管理后台的用户名
;password=123 ;登录管理后台的密码
[supervisord]
logfile=/tmp/supervisord.log ;日志文件,默认是 $CWD/supervisord.log
logfile_maxbytes=50MB ;日志文件大小,超出会rotate,默认 50MB,如果设成0,表示不限制大小
logfile_backups=10 ;日志文件保留备份数量默认10,设为0表示不备份
loglevel=info ;日志级别,默认info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ;pid 文件
nodaemon=false ;是否在前台启动,默认是false,即以 daemon 的方式启动
minfds=1024 ;可以打开的文件描述符的最小值,默认 1024
minprocs=200 ;可以打开的进程数的最小值,默认 200
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ;通过UNIX socket连接supervisord,路径与unix_http_server部分的file一致
;serverurl=http://127.0.0.1:9001 ; 通过HTTP的方式连接supervisord
; [program:xx]是被管理的进程配置参数,xx是进程的名称
[program:xx]
command=/opt/apache-tomcat-8.0.35/bin/catalina.sh run ; 程序启动命令
autostart=true ; 在supervisord启动的时候也自动启动
startsecs=10 ; 启动10秒后没有异常退出,就表示进程正常启动了,默认为1秒
autorestart=true ; 程序退出后自动重启,可选值:[unexpected,true,false],默认为unexpected,表示进程意外杀死后才重启
startretries=3 ; 启动失败自动重试次数,默认是3
user=tomcat ; 用哪个用户启动进程,默认是root
priority=999 ; 进程启动优先级,默认999,值小的优先启动
redirect_stderr=true ; 把stderr重定向到stdout,默认false
stdout_logfile_maxbytes=20MB ; stdout 日志文件大小,默认50MB
stdout_logfile_backups = 20 ; stdout 日志文件备份数,默认是10
; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out
stopasgroup=false ;默认为false,进程被杀死时,是否向这个进程组发送stop信号,包括子进程
killasgroup=false ;默认为false,向进程组发送kill信号,包括子进程
;包含其它配置文件
[include]
files = supervisord.d/*.ini ;可以指定一个或多个以.ini结束的配置文件
3.2.2 子配置文件解析
;[program:theprogramname] ;这个就是咱们要管理的子进程了,":"后面的是名字,最好别乱写和实际进程
有点关联最好。这样的program我们可以设置一个或多个,一个program就是
要被管理的一个进程
;command=/bin/cat ; 这个就是我们的要启动进程的命令路径了,可以带参数
例子:/home/test.py -a 'hehe'
有一点需要注意的是,我们的command只能是那种在终端运行的进程,不能是
守护进程。这个想想也知道了,比如说command=service httpd start。
httpd这个进程被linux的service管理了,我们的supervisor再去启动这个命令
这已经不是严格意义的子进程了。
这个是个必须设置的项
;process_name=%(program_name)s ; 这个是进程名,如果我们下面的numprocs参数为1的话,就不用管这个参数
了,它默认值%(program_name)s也就是上面的那个program冒号后面的名字,
但是如果numprocs为多个的话,那就不能这么干了。想想也知道,不可能每个
进程都用同一个进程名吧。
;numprocs=1 ; 启动进程的数目。当不为1时,就是进程池的概念,注意process_name的设置
默认为1 。。非必须设置
;directory=/tmp ; 进程运行前,会前切换到这个目录
默认不设置。。。非必须设置
;umask=022 ; 进程掩码,默认none,非必须
;priority=999 ; 子进程启动关闭优先级,优先级低的,最先启动,关闭的时候最后关闭
默认值为999 。。非必须设置
;autostart=true ; 如果是true的话,子进程将在supervisord启动后被自动启动
默认就是true 。。非必须设置
;autorestart=unexpected ; 这个是设置子进程挂掉后自动重启的情况,有三个选项,false,unexpected
和true。如果为false的时候,无论什么情况下,都不会被重新启动,
如果为unexpected,只有当进程的退出码不在下面的exitcodes里面定义的退
出码的时候,才会被自动重启。当为true的时候,只要子进程挂掉,将会被无
条件的重启
;startsecs=1 ; 这个选项是子进程启动多少秒之后,此时状态如果是running,则我们认为启
动成功了
默认值为1 。。非必须设置
;startretries=3 ; 当进程启动失败后,最大尝试启动的次数。。当超过3次后,supervisor将把
此进程的状态置为FAIL
默认值为3 。。非必须设置
;exitcodes=0,2 ; 注意和上面的的autorestart=unexpected对应。。exitcodes里面的定义的
退出码是expected的。
;stopsignal=QUIT ; 进程停止信号,可以为TERM, HUP, INT, QUIT, KILL, USR1, or USR2等信号
默认为TERM 。。当用设定的信号去干掉进程,退出码会被认为是expected
非必须设置
;stopwaitsecs=10 ; 这个是当我们向子进程发送stopsignal信号后,到系统返回信息
给supervisord,所等待的最大时间。 超过这个时间,supervisord会向该
子进程发送一个强制kill的信号。
默认为10秒。。非必须设置
;stopasgroup=false ; 这个东西主要用于,supervisord管理的子进程,这个子进程本身还有
子进程。那么我们如果仅仅干掉supervisord的子进程的话,子进程的子进程
有可能会变成孤儿进程。所以咱们可以设置可个选项,把整个该子进程的
整个进程组都干掉。 设置为true的话,一般killasgroup也会被设置为true。
需要注意的是,该选项发送的是stop信号
默认为false。。非必须设置。。
;killasgroup=false ; 这个和上面的stopasgroup类似,不过发送的是kill信号
;user=chrism ; 如果supervisord是root启动,我们在这里设置这个非root用户,可以用来
管理该program
默认不设置。。。非必须设置项
;redirect_stderr=true ; 如果为true,则stderr的日志会被写入stdout日志文件中
默认为false,非必须设置
;stdout_logfile=/a/path ; 子进程的stdout的日志路径,可以指定路径,AUTO,none等三个选项。
设置为none的话,将没有日志产生。设置为AUTO的话,将随机找一个地方
生成日志文件,而且当supervisord重新启动的时候,以前的日志文件会被
清空。当 redirect_stderr=true的时候,sterr也会写进这个日志文件
;stdout_logfile_maxbytes=1MB ; 日志文件最大大小,和[supervisord]中定义的一样。默认为50
;stdout_logfile_backups=10 ; 和[supervisord]定义的一样。默认10
;stdout_capture_maxbytes=1MB ; 这个东西是设定capture管道的大小,当值不为0的时候,子进程可以从stdout
发送信息,而supervisor可以根据信息,发送相应的event。
默认为0,为0的时候表达关闭管道。。。非必须项
;stdout_events_enabled=false ; 当设置为ture的时候,当子进程由stdout向文件描述符中写日志的时候,将
触发supervisord发送PROCESS_LOG_STDOUT类型的event
默认为false。。。非必须设置
;stderr_logfile=/a/path ; 这个东西是设置stderr写的日志路径,当redirect_stderr=true。这个就不用
设置了,设置了也是白搭。因为它会被写入stdout_logfile的同一个文件中
默认为AUTO,也就是随便找个地存,supervisord重启被清空。。非必须设置
;stderr_logfile_maxbytes=1MB ; 这个出现好几次了,就不重复了
;stderr_logfile_backups=10 ; 这个也是
;stderr_capture_maxbytes=1MB ; 这个一样,和stdout_capture一样。 默认为0,关闭状态
;stderr_events_enabled=false ; 这个也是一样,默认为false
;environment=A="1",B="2" ; 这个是该子进程的环境变量,和别的子进程是不共享的
;serverurl=AUTO ;
3.1.1 配置FE自启动
警告:在配置FE的时候,请务必关闭FE,否则会启动不成功,配置完后会自动自动
创建FE自启动日志目录
mkdir /var/log/supervisor/doris_fe
新建子配置文件vi /etc/supervisord.d/doris_fe.ini
doris_fe.ini内容
[program:doris_fe]
environment = JAVA_HOME="/opt/jdk1.8.0_333"
process_name=%(program_name)s ;进程名称
directory=/opt/apache-doris-0.15.0/fe ;工作目录
command=sh /opt/apache-doris-0.15.0/fe/bin/start_fe.sh ;运行的命令
autostart=true ;自动开启
autorestart=true ;自动重启
user=root ;用户
numprocs=1 ;进程数
startretries=3 ;启动重试次数
stopasgroup=true ;是否停止子进程
killasgroup=true ;是否杀死子进程
;startsecs=10 ;启动10秒后,如果还是运行状态才认为进程已经启动
stdout_logfile=/var/log/supervisor/doris_fe/doris_fe.log
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=10
刷新配置
supervisorctl update
或者执行重启命令
supervisorctl reload
查看状态
supervisorctl status
3.1.2 配置BE自启动
警告:在配置BE的时候,请务必关闭FE,否则会启动不成功,配置完后会自动自动
创建BE自启动日志目录
mkdir /var/log/supervisor/doris_be
新建子配置文件vi /etc/supervisord.d/doris_be.ini
doris_be.ini内容
[program:doris_be]
environment = JAVA_HOME="/opt/jdk1.8.0_333"
process_name=%(program_name)s ;进程名称
directory=/opt/apache-doris-0.15.0/be ;工作目录
command=sh /opt/apache-doris-0.15.0/be/bin/start_be.sh ;运行的命令
autostart=true ;自动开启
autorestart=true ;自动重启
user=root ;用户
numprocs=1 ;进程数
startretries=3 ;启动重试次数
stopasgroup=true ;是否停止子进程
killasgroup=true ;是否杀死子进程
;startsecs=1 ;启动10秒后,如果还是运行状态才认为进程已经启动
stdout_logfile=/var/log/supervisor/doris_be/doris_be.log
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=10
报错
Exited too quickly (process log may have details
先确认[program:XXX]中自己的程序的command=<启动命令>和 directory=<运行命令的路径>没有问题,python是不是用的自己要的环境的python(比如虚拟环境的),log文件的文件夹是不是已经创建(没创建的话supervisor没权限生成log文件),以及改log文件是不是授权给所有用户了(可参考前面的解决办法chmod +x aaaaa.log)
确保用上面的配置中的command在指定路径可以直接运行不会报错,这时候一般就不会有什么问题了。这时候tail你自己的log文件一般就能看到log信息,启动失败报错的信息也会在你的log文件中,照着解决后supervisorctl reload就好了。
如果上面的命令确保可以跑,但还是没法正常运行,也看不到自己程序的报错(不然你就能根据报错解决问题了),那么恭喜,你遇到了跟我一样的情况。请删除**/opt/apache-doris-0.15.0/fe/doris-meta**目录里的所有数据即可,这是由于doris-meta目录是由别的机器发过来的,保留了别的机器ip等配置信息。
3.1.3 配置broker自启动
创建broker自启动日志目录
mkdir /var/log/supervisor/doris_broker/
新建子配置文件vi /etc/supervisord.d/doris_be.ini
doris_broker.ini内容
[program:doris_broker]
environment = JAVA_HOME="/opt/jdk1.8.0_333"
process_name=%(program_name)s ;进程名称
directory=/opt/apache-doris-0.15.0/apache_hdfs_broker/bin ;工作目录
command=sh /opt/apache-doris-0.15.0/apache_hdfs_broker/bin/start_broker.sh ;运行的命令
autostart=true ;自动开启
autorestart=true ;自动重启
user=root ;用户
numprocs=1 ;进程数
startretries=1 ;启动重试次数
stopasgroup=true ;是否停止子进程
killasgroup=true ;是否杀死子进程
;startsecs=10 ;启动10秒后,如果还是运行状态才认为进程已经启动
stdout_logfile=/var/log/supervisor/doris_broker/doris_boker.log
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=10
修改完毕后执行
#根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启。注意:显示用stop停止掉的进程,用reload或者update都不会自动重启
supervisorctl update
3.2 配置webui监控
修改主配置文件,放开[inet_http_server] 注释
[inet_http_server] ; inet (TCP) server disabled by default
port=0.0.0.0:9001 ; (ip_address:port specifier, *:port for all iface)
username=user ; (default is no username (open server))
password=123 ; (default is no password (open server))
修改后启动服务
supervisorctl reload
在浏览器输入服务器ip:9001
3.3 集群服务统一监控
3.3.1 部署
supervisor-monitor是通过RPC远程调用进行管理多台服务器上的supervisor服务进程的,如果不使用它,假如一个公司有多个服务器,每个上面都部署了supervisor服务,那么管理起来就很不方便,每次需要逐个登录所有的supervisor服务去进行管理,而如果使用了supervisor-monitor,通过简单配置就能将所有服务器上的supervisor服务呈现在一个web管理面板上,管理效率就会大大提升。如下图,supervisor-monitor通过supervisor管理服务器集群上的进程。
supervisord-monitor github地址
https://github.com/mlazarov/supervisord-monitor
安装步骤
- supervisor-monitor是使用php语言开发的,所以我们需要安装php环境
yum -y install php-fpm
yum install php-xml.x86_64
- 更改nginx默认用户
useradd nginx -s /sbin/nologin -M
重新加载
usr/local/nginx/sbin/nginx -s reload
- 修改php配置文件中的用户,保持和nginx用户一致,我们这里使用root用户,大约在39行40行左右
vim /etc/php-fpm.d/www.conf
- 修改完毕,启动
#启动
systemctl start php-fpm.service
#设置开机自启
systemctl enable php-fpm.service
- 修改nginx配置文件中的用户,新增supervisor.conf配置文件的引用
vim /usr/local/nginx/conf/nginx.conf
#新增nginx用户
user nginx nginx;
#新增子配置文件
include /usr/local/nginx/conf/conf.d/supervisor.conf;
- 新增supervisor.conf配置文件
supervisor.conf 文件的路径为上一步nginx主配置文件中的绝对路径
touch /usr/local/nginx/conf/conf.d/supervisor.conf
将以下内容复制
server {
listen 8082 default_server;
server_name 192.168.33.100;
root /opt/supervisord-monitor-master/public_html;
location / {
index index.php index.html;
}
location /control/ {
index index.php;
rewrite /(.*)$ /index.php?$1 last;
}
location ~ .php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCHEME $scheme;
include fastcgi_params;
}
}
- 上传supervisor-monitor前端文件到服务器上,解压到指定目录
我们在第6步中,指定了supervisor-monitor的端口号为8082,静态文件路径为,请保持一致
/opt/supervisord-monitor-master
- 修改第7步上传的文件中的配置文件
切换到配置文件目录
#切换
cd /opt/supervisord-monitor-master/application/config
#复制并重命名
cp supervisor.php.example supervisor.php
#编译supervisor.php
vim supervisor.php
配置文件全文如图,我这里有三个服务器,node1,node2,node3,账号密码就是对应supervisor节点上的http服务中配置的账号密码。
<?php
// Dashboard columns. 2 or 3
$config['supervisor_cols'] = 2;
// Refresh Dashboard every x seconds. 0 to disable
$config['refresh'] = 10;
// Enable or disable Alarm Sound
$config['enable_alarm'] = true;
// Show hostname after server name
$config['show_host'] = false;
$config['supervisor_servers'] = array(
'node1' => array(
'url' => 'http://192.168.33.100/RPC2',
'port' => '9001',
'username' => 'user',
'password' => '123'
),
'node2' => array(
'url' => 'http://192.168.33.101/RPC2',
'port' => '9001',
'username' => 'user',
'password' => '123'
),
'node3' => array(
'url' => 'http://192.168.33.102/RPC2',
'port' => '9001',
'username' => 'user',
'password' => '123'
),
);
// Set timeout connecting to remote supervisord RPC2 interface
$config['timeout'] = 3;
// Path to Redmine new issue url
$config['redmine_url'] = 'http://redmine.url/path_to_new_issue_url';
// Default Redmine assigne ID
$config['redmine_assigne_id'] = '69';
- 重启nginx
#浏览器输入
192.168.33.100:8082
3.3.2 将nginx纳入集群统一管理
- 创建日志目录
mkdir /var/log/supervisor/nginx
2.新建子配置文件vi /etc/supervisord.d/nginx.ini
nginx.ini内容
[program:nginx]
command=/usr/local/nginx/sbin/nginx -g 'daemon off;'
stdout_logfile=/var/log/supervisor/nginx/nginx.log
stdout_logfile_maxbytes=50
stderr_logfile=/var/log/supervisor/nginx/nginx_err.log
user=root
stderr_logfile_maxbytes=50
autostart=true
autorestart=true
startsecs=1
- 刷新配置文件
supervisorctl update
- 效果
第4章 集群扩容与缩容
4.1 FE扩容与缩容
可以通过将 FE 扩容至 3 个以上节点来实现 FE 的高可用。FE 节点的扩容和缩容过程,不影响当前系统运行
#登录到node0数据库
mysql -uroot -h node0 -P 9030 -p123456
#扩容FOLLOWER
ALTER SYSTEM ADD FOLLOWER "node1:9010";
#扩容OBSERVER
ALTER SYSTEM ADD FOLLOWER "node2:9010";
#第一次启动
sh /opt/doris-0.15.5/fe/bin/start_fe.sh --helper node1:9010 --daemon
#后续启动
sh /opt/doris-0.15.5/fe/bin/start_fe.sh --daemon
#缩容
ALTER SYSTEM DROP FOLLOWER "node1:9010";
4.2 BE扩容与缩容
ALTER SYSTEM ADD BACKEND "node2:9050";
ALTER SYSTEM ADD BACKEND "node3:9050";
#启动
sh /opt/doris-0.15.5/be/bin/start_be.sh --daemon
#缩容
ALTER SYSTEM DECOMMISSION BACKEND "node1:9010";
4.3 Broaker扩容
#新增
ALTER SYSTEM ADD BROKER broker_name "node0:8000";
ALTER SYSTEM ADD BROKER broker_name "node1:8000";
ALTER SYSTEM ADD BROKER broker_name "node2:8000";
删除
ALTER SYSTEM DROP BROKER broker_name "node1:8000";
#删除所有
ALTER SYSTEM DROP ALL BROKER broker_name;
4.4 集群启动脚本
脚本存放位置,脚本命名为doris,并给与执行权限。
/usr/local/bin/
# dorisCluster.sh
#/bin/bash
###################################################################################
#脚本名:doris集群管理脚本
#zuthor: 许晨
#功 能:启动和停止doris集群
#命 令: dorisCluster.sh start | stop | restart
###################################################################################
cmd=$1
subCmd="status"
function usage() {
echo "usage: $0 start | stop | restart"
}
nodeExecutorCmd() {
for i in {0..2}
do
ssh -tt node$i << EOF
echo into node$i
source /etc/profile
$subCmd
sleep 2
echo "**************************************"
exit
EOF
done
}
function caseCmd() {
case $cmd in
"start")
echo "正在开启drois集群服务"
subCmd="/opt/doris-0.15.5/fe/bin/start_fe.sh --daemon;/opt/doris-0.15.5/be/bin/start_be.sh --daemon"
nodeExecutorCmd
;;
"stop")
echo "正在停止drois集群服务"
subCmd="/opt/doris-0.15.5/fe/bin/stop_fe.sh --daemon;/opt/doris-0.15.5/be/bin/stop_be.sh --daemon"
nodeExecutorCmd
;;
"status")
echo "正在查询集群节点状态"
mysql -h node0 -P 9030 -uroot -p123456 -e "show PROC '/brokers'; show PROC '/backends'"
;;
*)
echo "parameter [ $cmd ] error!"
usage
esac
}
if (( $# < 1 ))
then
echo "$0 need a parameter!!!"
usage
else
caseCmd
fi
最后
以上就是慈祥马里奥为你收集整理的【博学谷学习记录】超强总结,用心分享丨大数据超神之路(七):Apache Doris上篇第 1 章 Doris 简介第2章 编译与安装第3章 Supervisor配置drois第4章 集群扩容与缩容的全部内容,希望文章能够帮你解决【博学谷学习记录】超强总结,用心分享丨大数据超神之路(七):Apache Doris上篇第 1 章 Doris 简介第2章 编译与安装第3章 Supervisor配置drois第4章 集群扩容与缩容所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复