前言
在前面一篇文章里,已经初步学习了如何部署PolarDB的开源版本PolarDB-X,这一篇,我想把重点放在PolarDB的另一个开源版本——PolarDB-PG上。重点在于体验PolarDB-PG的高性能处理能力、企业级特性,以及它在复杂查询处理和高可用部署方面的独特优势。
PolarDB-PG
PolarDB PostgreSQL版(下文简称为 PolarDB-PG)是一款阿里云自主研发的云原生关系型数据库产品,100% 兼容 PostgreSQL,高度兼容Oracle语法(公有云版支持Oracle语法);采用基于 Shared-Storage 的存储计算分离架构,具有极致弹性、毫秒级延迟、HTAP 的能力和高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB 具有大规模并行计算能力,可以应对OLTP与OLAP混合负载。
产品特性
极致弹性:存储与计算能力均可独立地横向扩展。
当计算能力不够时,可以单独扩展计算集群,数据无需复制。
当存储容量或 I/O 不够时,可以单独扩展存储集群,而不中断业务。
毫秒级延迟:
WAL 日志存储在共享存储上,RW 到所有 RO 之间仅复制 WAL 的元数据。
独创的 LogIndex 技术,实现了 Lazy 回放和 Parallel 回放,理论上最大程度地缩小了 RW 和 RO 节点间的延迟。
HTAP 能力:基于 Shared-Storage 的分布式并行执行框架,加速在 OLTP 场景下的 OLAP 查询。一套 OLTP 型的数据,可支持 2 套计算引擎:
单机执行引擎:处理高并发的 TP 型负载。
分布式执行引擎:处理大查询的 AP 型负载。
PolarDB-PG 还支持时空、GIS、图像、向量、搜索、图谱等多模创新特性,应对企业对数据处理日新月异的需求。
PolarDB-PG 支持多种部署形态:单机本地部署、存储计算分离部署、X-Paxos三节点部署。
架构简介
PolarDB for PostgreSQL 采用了基于 Shared-Storage 的存储计算分离架构。数据库由传统的 Shared-Nothing 架构,转变成了 Shared-Storage 架构——由原来的 N 份计算 + N 份存储,转变成了 N 份计算 + 1 份存储;而 PostgreSQL 使用了传统的单体数据库架构,存储和计算耦合在一起。
为保证所有计算节点能够以相同的可见性视角访问分布式块存储设备,PolarDB 需要使用分布式文件系统 PolarDB File System(PFS) 来访问块设备,其实现原理可参考发表在 2018 年 VLDB 上的论文polarfs-paper;如果所有计算节点都可以本地访问同一个块存储设备,那么也可以不使用 PFS,直接使用本地的单机文件系统(如 ext4)。这是与 PostgreSQL 的不同点之一。
使用Docker直接部署PolarDB for PostgreSQL实例
PolarDB for PostgreSQL的本地安装部署依赖Docker,需要在机器上预装Docker。
执行如下命令,配置Docker的yum软件源。
yum install -y yum-utils
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
执行如下命令,安装Docker。
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
执行如下命令,启动Docker系统服务。
systemctl start docker
执行如下命令,测试Docker是否安装成功。
docker run hello-world
返回结果如下,表示Docker已经安装成功。
DockerHub上已有内含PolarDB-PG多形态实例的镜像。直接拉取镜像并运行,即可启动PolarDB实例。
执行如下命令,拉取PolarDB-PG实例镜像。
docker pull polardb/polardb_pg_local_instance
执行如下命令,创建运行并进入容器。
docker run \
-it --cap-add=SYS_PTRACE --privileged=true \
--name polardb_pg_htap \
polardb/polardb_pg_local_instance \
bash
执行如下命令,使用psql客户端工具连接PolarDB-PG并执行SQL。
psql -h 127.0.0.1 -c 'select version();'
返回结果如下,表示PolarDB-PG单节点实例连接成功,并且查看到版本号。
输入exit并回车,退出容器。
使用Docker在开发镜像中源码编译部署PolarDB for PostgreSQL实例
DockerHub上已有包含源码编译PolarDB for PostgreSQL所需所有工具和依赖的开发镜像。拉取镜像并启动容器,克隆代码,然后从源码编译出 PolarDB for PostgreSQL的各种形态的实例。本步骤指导您如何使用Docker在开发镜像中源码编译部署PolarDB for PostgreSQL单节点实例、双节点(一主一备)实例和HTAP 实例(一主两备)。
执行如下命令,拉取PolarDB-PG开发镜像。
docker pull polardb/polardb_pg_devel
执行如下命令,创建并启动容器。
docker run -it \
--cap-add=SYS_PTRACE --privileged=true \
--name polardb_pg \
polardb/polardb_pg_devel bash
执行如下命令,从GitHub上克隆PolarDB-PG稳定分支源码。
git clone -b POLARDB_11_STABLE https://github.com/ApsaraDB/PolarDB-for-PostgreSQL.git
执行如下命令,进入源码目录。
cd PolarDB-for-PostgreSQL/
部署PolarDB for PostgreSQL单节点实例
./polardb_build.sh
返回结果如下,表示PolarDB for PostgreSQL单节点实例部署成功。
执行如下命令,使用psql客户端工具连接单节点并执行SQL语句。
psql -h 127.0.0.1 -p5432 -c 'select version();'
返回结果如下,表示PolarDB for PostgreSQL单节点连接成功,并且查看到版本号。
部署PolarDB for PostgreSQL双节点(一主一备)实例
执行如下命令,部署PolarDB for PostgreSQL双节点(一主一备)实例。
./polardb_build.sh --withrep --repnum=1
返回结果如下,表示PolarDB for PostgreSQL双节点(一主一备)实例部署成功。
执行如下命令,分别连接两个节点并执行SQL语句。
psql -h 127.0.0.1 -p5432 -c 'select version();
psql -h 127.0.0.1 -p5433 -c 'select version();'
返回结果如下,表示PolarDB for PostgreSQL双节点连接成功,并且查看到版本号。
部署PolarDB for PostgreSQL HTAP实例(一主两备)
执行如下命令,部署PolarDB for PostgreSQL HTAP实例(一主两备)。
./polardb_build.sh --initpx
返回结果如下,表示PolarDB for PostgreSQL HTAP实例(一主两备)部署成功。
执行如下命令,分别连接三个节点并执行SQL语句。
psql -h 127.0.0.1 -p5432 -c 'select version();
'psql -h 127.0.0.1 -p5433 -c 'select version();
'psql -h 127.0.0.1 -p5434 -c 'select version();'
返回结果如下,表示PolarDB for PostgreSQL三节点连接成功,并且查看到版本号。
以上就是基于docker的快速部署方式。
快速部署只适用于小型项目或原型验证环境。由于其便捷的特性,可以在短时间内快速搭建起开发、测试乃至演示环境。这种方式能够极大地节省时间与资源,使得开发者能够更加专注于业务逻辑的实现,而非环境配置与依赖管理。
然而,快速部署并不总是适用于所有场景,特别是对于大型企业级应用或者对安全性、稳定性有严格要求的生产环境。在这些情况下,通常需要更细致的规划、更复杂的部署流程以及一系列的监控、备份、故障转移等策略来确保服务的高可用性和数据的安全性。
下面就来介绍正式环境下的部署方式及最佳实践:
部署 PolarDB PostgreSQL版需要在以下三个层面上做准备:
块存储设备层:用于提供存储介质。可以是单个物理块存储设备(本地存储),也可以是多个物理块设备构成的分布式块存储。
文件系统层:由于 PostgreSQL 将数据存储在文件中,因此需要在块存储设备上架设文件系统。根据底层块存储设备的不同,可以选用单机文件系统(如 ext4)或分布式文件系统 PolarDB File System(PFS)。
数据库层:PolarDB for PostgreSQL 的编译和部署环境。
以下表格给出了三个层次排列组合出的的不同实践方
基于阿里云ECS+ESSD云盘共享存储搭建PolarDB for PostgreSQL
最佳实践手册参考如下:https://openpolardb.com/document?type=PolarDB-PG
首先需要准备两台或以上的 阿里云 ECS。目前,ECS 对支持 ESSD 多重挂载的规格有较多限制,详情请参考 使用限制。仅 部分可用区、部分规格(ecs.g7se、ecs.c7se、ecs.r7se)的 ECS 实例可以支持 ESSD 的多重挂载。如图,请务必选择支持多重挂载的 ECS 规格:
这里要注意的只有两点:第一,按量付费节约钱;第二,特殊型号 ecs.g7se系列。
这里我把系统盘缩了一半,再节约一点资源,其他的都不变了。
选择自定义密码,输入两次密码。
在同一个可用区下创建两台,如下所示:
接下来开始准备 ESSD 云盘,在阿里云 ECS 的管理控制台中,选择【存储与快照】下的【云盘】,点击【创建云盘】。在与已经建好的 ECS 所在的相同可用区内,选择建立一个 ESSD 云盘,并勾选 多实例挂载。如果您的 ECS 不符合多实例挂载的限制条件,则该选框不会出现。
购买后如下图所示,显示待挂载:
点击挂载:
接下来,把这个云盘分别挂载到两台 ECS 上:
挂载完毕后,查看该云盘,将会显示该云盘已经挂载的两台 ECS 实例:
然后再分别进到两台服务器中去查看,执行如下命令:
lsblk
接下来,将在两台 ECS 上分别部署 PolarDB 的主节点和只读节点。作为前提,需要在 ECS 共享的 ESSD 块设备上 格式化并挂载 PFS,并且,还需要完成部署docker。
PolarDB File System,简称 PFS 或 PolarFS,是由阿里云自主研发的高性能类 POSIX 的用户态分布式文件系统,服务于阿里云数据库 PolarDB 产品。使用 PFS 对共享存储进行格式化并挂载后,能够保证一个计算节点对共享存储的写入能够立刻对另一个计算节点可见。
推荐使用 DockerHub 上的 PolarDB for PostgreSQL 可执行文件镜像,目前支持 linux/amd64 和 linux/arm64 两种架构,其中已经包含了编译完毕的 PFS 工具,无需手动编译安装。通过以下命令进入容器即可:
docker pull polardb/polardb_pg_binary
docker run -it \
--cap-add=SYS_PTRACE \
--privileged=true \
--name polardb_pg \
--shm-size=512m \
polardb/polardb_pg_binary \
bash
使用任意一台主机,在共享存储块设备上格式化 PFS 分布式文件系统即可:
sudo pfs -C disk mkfs nvme1n1
分别在两个节点上启动PFS 守护进程,挂载 PFS 文件系统:
sudo /usr/local/polarstore/pfsd/bin/start_pfsd.sh -p nvme1n1 -w 2
接下来开始准备数据库相关方面。
从 GitHub 上下载 PolarDB for PostgreSQL 的源代码,稳定分支为 POLARDB_11_STABLE。如果因网络原因不能稳定访问 GitHub,则可以访问 Gitee 国内镜像。
git clone -b POLARDB_11_STABLE https://gitee.com/mirrors/PolarDB-for-PostgreSQL
开始编译部署polarDB。具体使用命令可以参考:
在主节点上,编译 PolarDB 内核。
./polardb_build.sh --with-pfsd
上述脚本在编译完成后,会自动部署一个基于 本地文件系统 的实例,运行于5432 端口上。手动键入以下命令停止这个实例,以便 在 PFS 和共享存储上重新部署实例:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/pg_ctl-D $HOME/tmp_master_dir_polardb_pg_1100_bld/ stop
此时两个节点间还无法识别,所以下来需要进行一些初始化配置。
初始化读写节点的本地数据目录 ~/primary/:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/initdb -D $HOME/primary
在共享存储的 /nvme1n1/shared_data/ 路径上创建共享数据目录,然后使用 polar-initdb.sh 脚本初始化共享数据目录:
# 使用 pfs 创建共享数据目录
sudo pfs -C disk mkdir /nvme1n1/shared_data
# 初始化 db 的本地和共享数据目录
sudo $HOME/tmp_basedir_polardb_pg_1100_bld/bin/polar-initdb.sh \
$HOME/primary/ /nvme1n1/shared_data/
编辑读写节点的配置。打开 ~/primary/postgresql.conf,增加配置项:
port=5432
polar_hostid=1
polar_enable_shared_storage_mode=on
polar_disk_name='nvme1n1'
polar_datadir='/nvme1n1/shared_data/'
polar_vfs.localfs_mode=off
shared_preload_libraries='$libdir/polar_vfs,$libdir/polar_worker'
polar_storage_cluster_name='disk'
logging_collector=on
log_line_prefix='%p\t%r\t%u\t%m\t'
log_directory='pg_log'
listen_addresses='*'
max_connections=1000
synchronous_standby_names='replica1'
编辑读写节点的客户端认证文件 ~/primary/pg_hba.conf,增加以下配置项,允许只读节点进行物理复制:
host replication postgres 0.0.0.0/0 trust
最后,启动读写节点:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/pg_ctl start -D $HOME/primary
检查读写节点能否正常运行:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/psql \
-p 5432 \
-d postgres \
-c 'SELECT version();'
在读写节点上,为对应的只读节点创建相应的复制槽,用于只读节点的物理复制:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/psql \
-p 5432 \
-d postgres \
-c "SELECT pg_create_physical_replication_slot('replica1');"
pg_create_physical_replication_slot
下面来配置只读节点。
在只读节点本地磁盘的 ~/replica1 路径上创建一个空目录,然后通过 polar-replica-initdb.sh 脚本使用共享存储上的数据目录来初始化只读节点的本地目录。初始化后的本地目录中没有默认配置文件,所以还需要使用 initdb 创建一个临时的本地目录模板,然后将所有的默认配置文件拷贝到只读节点的本地目录下:
mkdir -m 0700 $HOME/replica1
sudo ~/tmp_basedir_polardb_pg_1100_bld/bin/polar-replica-initdb.sh \
/nvme1n1/shared_data/ $HOME/replica1/
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/initdb -D /tmp/replica1
cp /tmp/replica1/*.conf $HOME/replica1/
编辑只读节点的配置。打开 ~/replica1/postgresql.conf,增加配置项:
port=5433
polar_hostid=2
polar_enable_shared_storage_mode=on
polar_disk_name='nvme1n1'
polar_datadir='/nvme1n1/shared_data/'
polar_vfs.localfs_mode=off
shared_preload_libraries='$libdir/polar_vfs,$libdir/polar_worker'
polar_storage_cluster_name='disk'
logging_collector=on
log_line_prefix='%p\t%r\t%u\t%m\t'
log_directory='pg_log'
listen_addresses='*'
max_connections=1000
创建只读节点的复制配置文件 ~/replica1/recovery.conf,增加读写节点的连接信息,以及复制槽名称:
polar_replica='on'
recovery_target_timeline='latest'
primary_slot_name='replica1'
primary_conninfo='host=[读写节点所在IP] port=5432 user=postgres dbname=postgres application_name=replica1'
最后,启动只读节点:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/pg_ctl start -D $HOME/replica1
检查只读节点能否正常运行:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/psql \
-p 5433 \
-d postgres \
-c 'SELECT version();'
最后开展集群测试。部署完成后,需要进行实例检查和测试,确保读写节点可正常写入数据、只读节点可以正常读取。
登录 读写节点,创建测试表并插入样例数据:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/psql -q \
-p 5432 \
-d postgres \
-c "CREATE TABLE t (t1 INT PRIMARY KEY, t2 INT); INSERT INTO t VALUES (1, 1),(2, 3),(3, 3);"
登录 只读节点,查询刚刚插入的样例数据:
$HOME/tmp_basedir_polardb_pg_1100_bld/bin/psql -q \
-p 5433 \
-d postgres \
-c "SELECT * FROM t;"
t1 | t2
在读写节点上插入的数据对只读节点可见,这意味着基于共享存储的 PolarDB 计算节点集群搭建成功。
结语
在PolarDB-PG的部署上没有碰见那么多稀奇古怪的问题,花费时间比较多的反而是在datahub上拉镜像,这个过程由于网络因素显得不那么顺畅,建议能把PolarDB-PG的镜像托管到阿里自己的容器服务里面,进一步简化部署与管理流程,让开发者能够更加专注于业务逻辑本身,而不是被基础设施的细节所牵绊。这样的改进无疑将极大提升用户的整体体验,促进PolarDB-PG在开源社区的推广与应用。
值得表扬的是,我个人认为PG版的文档写的比polar-X要详细一些,不仅覆盖了从基础安装到高级配置的每一个步骤,还包含了丰富的示例和解释,大大降低了入门门槛,使得开发者能够更加专注于技术的探索与应用。当然,要说到最佳实践的话其实也还有很大的进步空间,增加更多实战案例分析、性能调优指南以及与第三方工具和服务的集成教程,让文档不仅仅是操作手册,更成为开发者解决问题、提升技能的宝典。
PolarDB-X和PolarDB-PG,它们各自承载了阿里云在数据库技术领域的深厚积累与创新,分别针对不同的应用场景和用户需求,展示了阿里云在数据库领域的全面布局和技术实力。未来,期待PolarDB系列在不断优化产品功能、强化社区互动与合作中,持续引领数据库技术的前沿发展,开启数据库技术的新篇章。
在此,致谢!