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)
如下图所示,数据源经过各种数据集成和加工处理后,通常会入库到实时数仓 Doris 和离线湖仓(Hive, Iceberg, Hudi 中),Apache Doris 被广泛应用在以下场景中

上图是整个Doris的具体使用场景,主要是它的接收数据源,以及它的一个整体的模块,还有最后它的一个可视化的呈现。后面会有一张更详细的图去介绍它整个的来源,以及最后可以输出的数据流向。
一般情况下,用户的原始数据,比如日志或者在事务型数据库中的数据,经过流式系统或离线处理后,导入到Doris中以供上层的报表工具或者数据分析师查询使用。
Doris整体架构如下图所示,Doris 架构非常简单,只有两类进程
这两类进程都是可以横向扩展的,单集群可以支持到数百台机器,数十 PB 的存储容量。并且这两类进程通过一致性协议来保证服务的高可用和数据的高可靠。这种高度集成的架构设计极大的降低了一款分布式系统的运维成本。

在使用接口方面,Doris 采用 MySQ L 协议,高度兼容 MySQL 语法,支持标准 SQL,用户可以通过各类客户端工具来访问 Doris,并支持与 BI 工具的无缝对接。
在存储引擎方面,Doris 采用列式存储,按列进行数据的编码压缩和读取,能够实现极高的压缩比,同时减少大量非相关数据的扫描,从而更加有效利用 IO 和 CPU 资源。
Doris 也支持比较丰富的索引结构,来减少数据的扫描:
在存储模型方面,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命名子目录。
因此选择了这三种技术的组合。

Doris采用Paxos协议以及Memory+ Checkpoint + Journal的机制来确保元数据的高性能及高可靠。元数据的每次更新,都会遵照以下几步:
相当于是一个纯内存的一个结构,也就是说所有的元数据都会缓存在内存之中,从而保证FE在宕机后能够快速恢复元数据,而且不丢失元数据。
Leader、follower和 observer它们三个构成一个可靠的服务,如果发生节点宕机的情况,一般是部署一个leader两个follower,目前来说基本上也是这么部署的。就是说三个节点去达到一个高可用服务。单机的节点故障的时候其实基本上三个就够了,因为FE节点毕竟它只存了一份元数据,它的压力不大,所以如果FE太多的时候它会去消耗机器资源,所以多数情况下三个就足够了,可以达到一个很高可用的元数据服务。

OLTP是 Online Transaction Processing 的简称;OLAP 是 OnLine Analytical Processing 的简称

总结

(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 实例即可。
安装 Doris,需要先通过源码编译,主要有两种方式:使用 Docker 开发镜像编译(推
荐)、直接编译。
Docker要求Centos系统的内核版本高于3.1.0,首先查看系统内核内核版本是否满足
uname -r
sudo yum update
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y
docker -v
systemctl is-enabled docker.service 检查服务是否开机启动
systemctl enable docker.service 将服务配置成开机启动
systemctl start docker.service 启动服务
# 永久关闭
vim /etc/fstab
注释掉swap行
#/dev/mapper/centos-swap swap swap defaults 0 0

注意点:
当部署多个 FE 实例时,要保证 FE 的 http_port 配置相同。
部署前请确保各个端口在应有方向上的访问权限。
官方链接
https://archive.apache.org/dist/doris/0.15.0-incubating/
百度云盘
链接:https://pan.baidu.com/s/1eNcMR3c8o1VOttvJ0ecThA?pwd=yyds
[root@node2 opt]# tar-zxvf apache-doris-0.15.0-incubating-src.tar.gz
docker pull apache/incubator-doris:build-env-for-0.15.0
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
[root@69a41d96c87e ~]# ll
total 8
-rw------- 1 root root 3416 Nov 13 2020 anaconda-ks.cfg
drwxrwxr-x 20 root root 4096 Nov 16 2021 apache-doris-0.15.0-incubating-src
[root@69a41d96c87e ~]# cd apache-doris-0.15.0-incubating-src/
[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
vim /opt/apache-doris-0.15.0-incubating-src/fe/pom.xml
在标签下添加:
aliyun
https://maven.aliyun.com/nexus/content/groups/public/
#如果是第一次使用 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

因测试环境资源有限,FE和BE节点部署在相同服务器,生产环境建议分开

mkdir /opt/apache-doris-0.15.0
cp -r /opt/apache-doris-0.15.0-incubating-src/output/* /opt/apache-doris-0.15.0
vim /etc/security/limits.conf
#所有用户 类型 打开文件数 数量
* soft nofile 65535
* hard nofile 65535
#所有用户 类型 打开进程数 数量
* soft nproc 65535
* hard nproc 65535
mkdir -p /opt/apache-doris-0.15.0/fe/doris-meta
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 以上。

我们找到这个文件的109行,加上中括号。


这个是jdk8环境变量路径配置的不对。
#找当前JAVA_HOME路径
echo $JAVA_HOME
#修改//etc/profile.d/文件夹里sh文件夹里的java环境变量配置
分发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 /opt/apache-doris-0.15.0/be/doris-storage1
mkdir /opt/apache-doris-0.15.0/be/doris-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
检查当前系统是否安装过 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 node2 -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
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
#启动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直接访问了,新建查询如图所示

错误提示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
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-0.15.0-incubating-src/fs_brokers/apache_hdfs_broker/output/apache_hdfs_broker /opt/apache-doris-0.15.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

在生产环境中,所有实例都应使用守护进程启动,以保证进程退出后,会被自动拉起,如 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就可以管理它对应的进程。
#安装
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 Get status for a single process
status :* Get status for all processes in a group
status Get status for multiple named processes
status Get all process status info
# supervisorctl start 启动进程
start Start a process
start :* Start all processes in a group
start Start multiple processes or groups
start all Start all processes
# supervisorctl stop 停止进程
stop Stop a process
stop :* Stop all processes in a group
stop Stop multiple processes or groups
stop all Stop all processes
# supervisorctl restart 重启进程
restart Restart a process
restart :* Restart all processes in a group
restart 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 [...] 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都不会自动重启
[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结束的配置文件
;[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 ;
新建子配置文件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秒后,如果还是运行状态才认为进程已经启动
刷新配置
supervisorctl update
查看状态
supervisorctl status

新建子配置文件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就好了。
如果上面的命令确保可以跑,但还是没法正常运行,也看不到自己程序的报错(不然你就能根据报错解决问题了),那么恭喜,你遇到了跟我一样的情况。我的解决办法很诡异,尝试把[program:XXX]中的名字换成了一个跟启动命令不一样的另一个名字(不要太短),reload之后居然就可以跑了。。。。嗯,很不合常理,但是对我来说确实管用了。

新建子配置文件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

修改主配置文件,放开[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

可以通过将 FE 扩容至 3 个以上节点来实现 FE 的高可用。FE 节点的扩容和缩容过程,不影响当前系统运行
在之前的操作中,我们在node2主机上搭建了FE,BE,BROKER,使用 MySQL 登录客户端后,可以使用 sql 命令查看 FE 状态,目前就一台 在node2主机上的FE
参考前面的章节,编译好FE,并修改元数据存储位置和ip
priority_networks = 192.168.33.101/24
meta_dir = /opt/apache-doris-0.15.0/fe/doris-meta

mysql -uroot -h node2 -P 9030 -p
ALTER SYSTEM ADD FOLLOWER "node1:9010 ";
ALTER SYSTEM ADD OBSERVER "node3:9010 ";
分别在node1和node3执行以下命令,只有第一次执行的时候添加–helper ,其余时间不需要
sh /opt/apache-doris-0.15.0/fe/bin/start_fe.sh --helper node2:9010 --daemon