亚马逊AWS官方博客

在 AWS Graviton2 Arm 架构上编译构建 ClickHouse

ClickHouse简介

 

ClickHouse是一种快速的、开源的、用于联机分析(OLAP)的列式数据库管理系统(DBMS),由俄罗斯的Yandex公司开发,于2016年开源。ClickHouse作为交互式分析领域的后起之秀,发展速度非常快,目前在GitHub 上已收获 14K Star。

ClickHouse主打顶尖的极致性能,每台服务器每秒钟可以处理数亿至数十亿多行或者是数十GB的数据。ClickHouse基于列式存储,通过SQL查询海量数据并实时生成分析报告。ClickHouse充分利用了所有可用的硬件优化技术,以尽可能快地处理每个查询。向量化的查询执行引入了SIMD处理器指令和运行时代码生成技术。列式存储的数据会提高CPU缓存的命中率。

在分布式集群中,副本之间的数据读取会自动保持平衡,以避免增加延迟。同时,ClickHouse支持多主异步复制模式,这种情况下所有节点角色都是相等的,可以避免出现单点故障,单个节点或整个可用区的停机时间并不会影响系统的读写可用性。

在网络和应用分析,广告网络和实时出价,电信,电子商务和金融以及商业智能等领域,ClickHouse都有很好的支持与应用,更多信息请参考ClickHouse官网。

 

AWS Graviton2

AWS Graviton 由 AWS使用 64 位 Arm Neoverse 内核定制而成,为在 Amazon EC2 中运行的云工作负载提供更高的性价比。AWS Graviton 处理器可以为客户带来更多选择,帮助客户优化性能和降低工作负载成本。

第二代AWS Graviton2 处理器不管在性能还是功能上都实现了巨大的飞跃,目前提供的实例类型包括T4g、M6g、C6g 和 R6g 实例。这些实例为各种工作负载(包括应用程序服务器、微服务、高性能计算、电子设计自动化、游戏、开源数据库和内存中的缓存)提供高达 40% 的性价比提升。AWS Graviton2 处理器也为视频编码工作负载提供增强的性能,为压缩工作负载提供硬件加速,并为基于 CPU 的机器学习推理提供支持。

ClickHouse同样提供了针对Arm处理器的支持,通过使用AWS Graviton2实例,ClickHouse不仅可以降低成本,还可以维持较高性能。客户在选择使用ClickHouse进行数据分析时,可以考虑采用不同处理器架构的混合部署模式来支持不同类型的OLAP分析。

此外,在2021年1月份,搭载AWS Graviton2处理器的Amazon EC2 M6g、C6g和R6g实例,现已在光环新网运营的AWS中国(北京)区域及西云数据运营的AWS中国(宁夏)区域正式上线。

R6g上编译ClickHouse

以下操作使用的实例类型为r6gd.8xlarge,操作系统版本为Ubuntu 20.04.1 LTS。

准备编译环境,下载需要的基础工具git、cmake、python3、ninja-build。

sudo apt-get update -y
sudo apt-get install git cmake python3 ninja-build -y

安装ClickHouse官方推荐的 clang-11,在Ubuntu或者Debian操作系统上,可以使用LLVM官方提供的自动安装脚本。

 

sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"

配置clang-11环境变量:

export CC=clang-11
export CXX=clang++-11

从GitHub上拉取官方源码:

git clone --recursive https://github.com/ClickHouse/ClickHouse.git

 

切换到ClickHouse项目目录,并创建编译文件夹:

cd ClickHouse
mkdir build-arm64

下面开始正式编译,默认编译后(cmake . -Bbuild-arm64)的输出是一个单独的clickhouse执行文件,client和server操作都是通过clickhouse这个文件的参数来指定的,这对于分发很方便,而且clickhouse执行文件提供了install参数便于安装部署。但是这意味着在每次更改时,都将重新链接整个二进制文件,会导致速度变慢并且可能会给开发带来不便,所以请根据实际情况进行选择。示例中选择使用以下配置(-DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1),创建动态加载的共享库,允许更快的增量构建:

cmake . -Bbuild-arm64 -DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1

ninja -C build-arm64 clickhouse

构建成功后的文件结构如下图所示,可以看到构建结果是有多个可执行程序组成,如果在cmake的时候不添加-DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1参数,则构建结果只有一个clickhouse执行文件。

示例采用ClickHouse默认数据目录/var/lib/clickhouse,并且由于r6gd实例类型提供了1 x 1900 NVMe SSD存储,示例选择使用这块硬盘来作为数据存储,因此首先格式化并进行挂载。

sudo mkfs.xfs /dev/nvme1n1
sudo mkdir -p /var/lib/clickhouse
sudo adduser --disabled-password --shell /bin/bash --gecos "" clickhouse
sudo chown clickhouse.clickhouse -R /var/lib/clickhouse
sudo mount /dev/nvme1n1 /var/lib/clickhouse/

下面开始安装及配置clickhouse-server和clicksehouse-client,这里参考官方release中的tgz包中自带的安装脚本,本文根据GitHub中当前最新版本使用20.13文件包进行下载,请根据实际情况进行替换。

wget https://github.com/ClickHouse/ClickHouse/releases/download/v20.13.1.5591-testing/clickhouse-client-20.13.1.5591.tgz

wget https://github.com/ClickHouse/ClickHouse/releases/download/v20.13.1.5591-testing/clickhouse-server-20.13.1.5591.tgz

tar -xzvf clickhouse-client-20.13.1.5591.tgz

tar -xzvf clickhouse-server-20.13.1.5591.tgz

编辑文件clickhouse-client-20.13.1.5591/install/inst.sh,复制以下内容,如果下载过程中使用路径不同,请根据实际情况进行替换:

#!/bin/sh
set -e

SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
for filepath in `find $SCRIPTPATH/.. -type f -or -type l | grep -v "\.\./install/"`; do
    destpath=${filepath##$SCRIPTPATH/..}
    mkdir -p $(dirname "$destpath")
    cp -r "$filepath" "$destpath"
done

mkdir -p /etc/clickhouse-client/conf.d

编辑文件clickhouse-server-20.13.1.5591/install/inst.sh,复制以下内容,如果下载过程中使用路径不同,请根据实际情况进行替换:

##!/bin/sh
set -e

SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
for filepath in `find $SCRIPTPATH/.. -type f -or -type l | grep -v "\.\./install/"`; do
    destpath=${filepath##$SCRIPTPATH/..}
    mkdir -p $(dirname "$destpath")
    cp -r -f "$filepath" "$destpath"
done

rm -f /usr/bin/clickhouse-*

cp -r -f /home/ubuntu/ClickHouse/build-arm64/programs/clickhouse-* /usr/bin/

# set -x

[ -f /usr/share/debconf/confmodule ] && . /usr/share/debconf/confmodule
[ -f /etc/default/clickhouse ] && . /etc/default/clickhouse

if [ ! -f "/etc/debian_version" ]; then
    not_deb_os=1
fi

if [ "$1" = configure ] || [ -n "$not_deb_os" ]; then
    if [ -x "/bin/systemctl" ] && [ -f /etc/systemd/system/clickhouse-server.service ] && [ -d /run/systemd/system ]; then
        # if old rc.d service present - remove it
        if [ -x "/etc/init.d/clickhouse-server" ] && [ -x "/usr/sbin/update-rc.d" ]; then
            /usr/sbin/update-rc.d clickhouse-server remove
            echo "ClickHouse init script has migrated to systemd. Please manually stop old server and restart the service: sudo killall clickhouse-server && sleep 5 && sudo service clickhouse-server restart"
        fi

        /bin/systemctl daemon-reload
        /bin/systemctl enable clickhouse-server
    else
        # If you downgrading to version older than 1.1.54336 run: systemctl disable clickhouse-server
        if [ -x "/etc/init.d/clickhouse-server" ]; then
            if [ -x "/usr/sbin/update-rc.d" ]; then
                /usr/sbin/update-rc.d clickhouse-server defaults 19 19 >/dev/null || exit $?
            else
                echo # TODO [ "$OS" = "rhel" ] || [ "$OS" = "centos" ] || [ "$OS" = "fedora" ]
            fi
        fi
    fi
fi

mkdir -p /var/log/clickhouse-server
chown clickhouse.clickhouse -R /var/log/clickhouse-server

执行以下命令进行安装:

sudo chmod +x clickhouse-client-20.13.1.5591/install/inst.sh
sudo chmod +x clickhouse-server-20.13.1.5591/install/inst.sh
sudo clickhouse-client-20.13.1.5591/install/inst.sh
sudo clickhouse-server-20.13.1.5591/install/inst.sh

启动clickhouse-server服务:

sudo systemctl start clickhouse-server

性能测试对比

在性能测试对比中,我们将首先选取ClickHouse官网提供的纽约出租车数据,该数据分析是Kaggle竞赛的著名赛题之一,也是学习数据分析的经典练习案例,项目数据可以从NYC网站上进行下载,这里使用的ClickHouse官网提供的预分区数据,数据集大小为130GB,包含约13亿行数据。

对比的对象分别是r6gd.8xlarge和r5d.8xlarge,操作系统版本为Ubuntu 20.04.1 LTS,ClickHouse版本为20.13.1 revision 54443,数据均存储在本地的NVMe SSD上,均为单机模式部署。查询语句为ClickHouse官网提供的4条SQL查询语句,如下所示:

SELECT cab_type, count(*) FROM datasets.trips_mergetree GROUP BY cab_type;

SELECT passenger_count, avg(total_amount) FROM datasets.trips_mergetree GROUP BY passenger_count;

SELECT passenger_count, toYear(pickup_date) AS year, count(*) FROM datasets.trips_mergetree GROUP BY passenger_count, year;

SELECT passenger_count, toYear(pickup_date) AS year, round(trip_distance) AS distance, count(*) FROM datasets.trips_mergetree GROUP BY passenger_count, year, distance ORDER BY year, count(*) DESC;

在r6gd.8xlarge和r5d.8xlarge首次执行结果如下所示(数值越小越好),实际测试下来可以看到针对这4条SQL查询语句r6gd.8xlarge要比r5d.8xlarge快上约30%到48%。

在r6gd.8xlarge和r5d.8xlarge缓存情况下的执行结果如下所示(数值越小越好),同样 r6gd.8xlarge要比r5d.8xlarge快上约28%到45%。

以上查询为单条语句执行,下面对比下在并发情况下的测试结果。这里使用官方提供的clickhouse-benchmark工具进行测试,将SQL语句保存在parallel_queries_file文件中并执行以下语句:

clickhouse-benchmark -c 100 -i 4 --cumulative < parallel_queries_file;

结果如下所示(数值越大越好),通过对比r6gd.8xlarge和r5d.8xlarge查询的QPS,可以看到r6gd.8xlarge比r5d.8xlarge高出22%:

除了纽约出租车数据之外,示例选取ClickHouse官网硬件测试中的数据集,其内容为1亿行Yandex.Metrica用户点击数据,数据集大小为9GB。测试语句共有43项,每一项都会记录首次查询,第二次和第三次查询时长,具体结果如下图所示(数值越小越好):

其中,84%的查询都是r6gd.8xlarge要比r5d.8xlarge更快速,所有查询整体速度要快上30%以上。

上述对比结果的原因主要是AWS Graviton2类型的EC2实例每个vCPU 都是一个单独的物理核心,而没有采用SMT同步多线程技术,同时AWS Graviton2架构上的优化使得每个物理内核通往内存和其他物理内核的路径都是完全相同的,这样进一步减少了性能损耗。此外,AWS Graviton2更是具有充足的价格优势,加上性能差异这样整体成本优势更为明显。对于ClickHouse来说,部分特定功能暂时不支持Arm,不过社区仍在积极地加速推进中。

请注意:以上测试仅供参考,根据用户的数据集和查询语句不同,实际测试对比结果也会有所出入,请结合实际情况进行更详细的测试。

 小结

本文首先简单介绍了ClickHouse及其特性和使用场景,然后介绍了AWS Graviton2 Arm架构的优势,并演示了如何在AWS Graviton2的EC2实例上进行编译安装。接着,对AWS Graviton2和x86架构的EC2实例上的ClickHouse进行了性能比对,通过结果可以看到,AWS Graviton2不仅增强了数据分析的成本优势,还给客户带来了更丰富的计算架构选项。

 

参考资料:

https://clickhouse.tech/docs/en/getting-started/example-datasets/nyc-taxi/

https://clickhouse.tech/docs/en/operations/utilities/clickhouse-benchmark/

https://clickhouse.tech/docs/en/operations/performance-test/

 

本篇作者

史天

AWS解决方案架构师。拥有丰富的云计算、大数据和机器学习经验,目前致力于数据科学、机器学习、无服务器等领域的研究和实践。译有《机器学习即服务》《基于Kubernetes的DevOps实践》《Prometheus监控实战》等。