穷鬼玩PolarDB RAC系列 | 容灾(standby)
参考文档点击文末阅读原文打开; 推荐《最好的PostgreSQL学习镜像》;
穷鬼玩PolarDB RAC系列 | 创建PolarDB 容灾(standby)节点
继续穷鬼玩PolarDB RAC一写多读集群系列, 上一篇通过《在Docker容器中用loop设备模拟共享存储》 分享了在macOS中用虚拟共享磁盘和几个容器来搭建“PolarDB 15 RAC一写多读集群”.
本篇介绍一下如何搭建PolarDB容灾(standby)节点, 需要用到上一篇的环境, 没有环境的小伙伴可以先阅读上一篇搭建一下.
搭建standby还需要参考如下文档:
https://apsaradb.github.io/PolarDB-for-PostgreSQL/zh/operation/backup-and-restore.html#%E5%A4%87%E4%BB%BD%E5%B9%B6%E6%81%A2%E5%A4%8D%E4%B8%80%E4%B8%AA-standby-%E8%8A%82%E7%82%B9
DEMO
1、在macOS宿主机创建PolarDB standby容灾节点需要使用的虚拟磁盘VirtualDisk_standby.img
cd ~/data_volumn
dd if=/dev/zero of=./VirtualDisk_standby.img bs=1m count=20480 oflag=direct
2、启动容器pb3
cd ~/data_volumn
PWD=`pwd`
docker run -d -it -v $PWD:/data -P --shm-size=1g --cap-add=SYS_PTRACE --cap-add SYS_ADMIN --privileged=true --name pb3 registry.cn-hangzhou.aliyuncs.com/polardb_pg/polardb_pg_devel:ubuntu22.04 bash
3、进入容器pb3, 查看地址
docker exec -ti pb3 bash
ip addr show
116: eth0@if117: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
4、确认pb3和pb1,pb2容器的网络正常通信.
# 安装ping 客户端
sudo apt update
sudo apt-get install -y inetutils-ping
# 确认可以连通PolarDB 主节点和replica节点
ping 172.17.0.2
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.050 ms
...
ping 172.17.0.3
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.050 ms
5、在pb3创建一个loop设备, 用于映射到虚拟磁盘VirtualDisk_standby.img
# 找一个可用的loop设备
sudo losetup -f
返回
/dev/loop2 # 使用新建的虚拟磁盘创建loop设备
sudo losetup --direct-io=on /dev/loop2 /data/VirtualDisk_standby.img
# 现在可以看到该loop设备
$ losetup -a
/dev/loop1: [0176]:36827 (/data/VirtualDisk.img)
/dev/loop2: [0176]:109941 (/data/VirtualDisk_standby.img)
/dev/loop0: [65025]:3407876 (/mount-services-cache/entries/services.iso/16203eaee29495c5a513341af851be45c30488427f5e3c87764e8b89a4a47d7a)
6、将loop设备软链到nvme2n1 (注意nvme2n1和primary & replica的nvme1n1不同, 不是必须的, 这里取nvme2n1只是区分一下), 方便使用(也不是必须的, 习惯性动作)
# 注意: 容器重启后, 这个软链就不存在了, 需重新创建该软链 sudo ln -s /dev/loop2 /dev/nvme2n1
7、使用pfs格式化 nvme2n1
sudo pfs -C disk mkfs -f nvme2n1
8、启动pfsd
sudo /usr/local/polarstore/pfsd/bin/start_pfsd.sh -p nvme2n1 -w 1
9、将编译好的polardb二进制拷贝到$HOME目录中
$ cp -r /data/polardb/tmp_polardb_pg_15_base ~/
$ which psql
/home/postgres/tmp_polardb_pg_15_base/bin/psql
10、备份PolarDB数据到本地存储和共享存储. polar_basebackup支持从pfs备份到pfs后, 用此法. 否则跳到下一个第10步.
在用于部署Standby 节点的pb3容器中执行备份,以~/standby 作为本地数据目录,以/nvme2n1/shared_data 作为共享存储目录:
polar_basebackup \
--host=172.17.0.2 \
--port=5432 \
-D /home/postgres/standby \
--polardata=/nvme2n1/shared_data/ \
--polar_storage_cluster_name=disk \
--polar_disk_name=nvme2n1 \
--polar_host_id=3 \
-X stream --progress --write-recovery-conf -v
报错如下:
看起来polar_basebackup自动创建了/nvme2n1/shared_data/, 但是没有自动创建/nvme2n1/shared_data/base
[PFSD_SDK INF Dec 17 17:42:37.947483][321]pfs_mount_prepare 103: begin prepare mount cluster(disk), PBD(nvme2n1), hostid(3),flags(0x13)
[PFSD_SDK INF Dec 17 17:42:37.947583][321]pfs_mount_prepare 165: pfs_mount_prepare success for nvme2n1 hostid 3
[PFSD_SDK INF Dec 17 17:42:37.983903][321]chnl_connection_poll_shm 1238: ack data update s_mount_epoch 1
[PFSD_SDK INF Dec 17 17:42:37.983917][321]chnl_connection_poll_shm 1266: connect and got ack data from svr, err = 0, mntid 0
[PFSD_SDK INF Dec 17 17:42:37.984060][321]pfsd_sdk_init 191: pfsd_chnl_connect success
[PFSD_SDK INF Dec 17 17:42:37.984082][321]pfs_mount_post 208: pfs_mount_post err : 0
[PFSD_SDK ERR Dec 17 17:42:37.989320][321]pfsd_opendir 1437: opendir /nvme2n1/shared_data/ error: No such file or directory
[PFSD_SDK INF Dec 17 17:42:37.989439][321]pfsd_mkdir 1320: mkdir /nvme2n1/shared_data
polar_basebackup: initiating base backup, waiting for checkpoint to complete
polar_basebackup: checkpoint completed
polar_basebackup: write-ahead log start point: 0/485F0700 on timeline 1
polar_basebackup: starting background WAL receiver
polar_basebackup: created temporary replication slot "pg_basebackup_64335"
[PFSD_SDK INF Dec 17 17:42:38.149108][321]pfsd_mkdir 1320: mkdir /nvme2n1/shared_data/pg_wal
[PFSD_SDK INF Dec 17 17:42:38.149659][321]pfsd_mkdir 1320: mkdir /nvme2n1/shared_data/pg_wal/archive_status
[PFSD_SDK INF Dec 17 17:42:38.153165][329]pfsd_open 539: open /nvme2n1/shared_data/pg_wal/000000010000000000000001 with inode 3, fd 0
polar_basebackup: error: could not create directory "/nvme2n1/shared_data/base": No such file or directory
polar_basebackup: removing data directory "/home/postgres/standby"
polar_basebackup: removing data directory "/nvme2n1/shared_data"
[PFSD_SDK INF Dec 17 17:42:38.210123][321]pfsd_rmdir 1370: rmdir /nvme2n1/shared_data/pg_wal/archive_status
[PFSD_SDK INF Dec 17 17:42:38.211285][321]pfsd_unlink 952: unlink /nvme2n1/shared_data/pg_wal/000000010000000000000001
[PFSD_SDK INF Dec 17 17:42:38.212522][321]pfsd_rmdir 1370: rmdir /nvme2n1/shared_data/pg_wal
[PFSD_SDK INF Dec 17 17:42:38.213276][321]pfsd_rmdir 1370: rmdir /nvme2n1/shared_data
创建失败, 环境已清空
$ sudo pfs -C disk ls /nvme2n1/
File 1 4194304 Wed Dec 18 09:58:16 2024 .pfs-paxos
File 1 1073741824 Wed Dec 18 09:58:17 2024 .pfs-journal
total 2105344 (unit: 512Bytes)
暂时没办法进行后续的操作, 请问该如何解决呢? 回复: polar_basebackup还没有适配共享存储, 等适配后, 需重新编译polardb二进制再试.
上述命令会将PolarDBPrimary 节点的本地数据目录备份到-D /home/postgres/standby,将PolarDB 主实例共享存储的数据备份到--polardata=/nvme2n1/shared_data/ --polar_storage_cluster_name=disk --polar_disk_name=nvme2n1 。
解决办法
在polar_basebackup支持从pfs备份到pfs之前, 可以先参考《穷鬼玩PolarDB RAC一写多读集群系列 | 在线备份》 使用polar_basebackup备份pfs到本地文件系统, 然后把共享数据拷贝到pfs, 从而实现搭建基于pfs存储的PolarDB standby.
假设你已经完成了前9步的所有操作.
10、(polar_basebackup支持从pfs备份到pfs之前, 用此法.)
首先进行备份, 假设《穷鬼玩PolarDB RAC一写多读集群系列 | 在线备份》 直到第6步已正常执行.
得到
本地数据目录: /data/backup/primary共享数据目录: /data/backup/shared_data
将本地数据目录拷贝到本地standby实例的对应目录中, 直接移动也行, 随你:
cp -r /data/backup/primary ~/standby
将共享数据目录拷贝到pfs nvme2n1中
pfs cp -r /data/backup/shared_data /nvme2n1/
拷贝完成后, 可以看到pfs中已经有共享数据内容了
postgres@9bab5d9c0b25:/data$ pfs ls /nvme2n1/
File 1 4194304 Wed Dec 18 09:58:16 2024 .pfs-paxos
File 1 1073741824 Wed Dec 18 09:58:17 2024 .pfs-journal
Dir 1 1664 Thu Dec 19 14:23:03 2024 shared_data
total 2105344 (unit: 512Bytes) postgres@9bab5d9c0b25:/data$ pfs ls /nvme2n1/shared_data
Dir 1 256 Thu Dec 19 14:22:59 2024 pg_multixact
Dir 1 256 Thu Dec 19 14:23:02 2024 pg_wal
Dir 1 0 Thu Dec 19 14:23:02 2024 pg_commit_ts
File 1 0 Thu Dec 19 14:23:02 2024 standby.signal
Dir 1 0 Thu Dec 19 14:23:02 2024 pg_replslot
Dir 1 0 Thu Dec 19 14:23:02 2024 pg_tblspc
File 1 217 Thu Dec 19 14:23:02 2024 polar_non_exclusive_backup_label
File 1 257 Thu Dec 19 14:23:02 2024 postgresql.auto.conf
Dir 1 0 Thu Dec 19 14:23:02 2024 pg_twophase
Dir 1 128 Thu Dec 19 14:23:02 2024 pg_xact
Dir 1 0 Thu Dec 19 14:23:02 2024 pg_logindex
Dir 1 7808 Thu Dec 19 14:23:03 2024 global
Dir 1 512 Thu Dec 19 14:23:04 2024 base
total 16384 (unit: 512Bytes)
11、配置standbypostgresql.conf
vi ~/standby/postgresql.conf
修改如下:
-polar_hostid=1
+polar_hostid=3
-polar_disk_name='nvme1n1'
-polar_datadir='/nvme1n1/shared_data/'
+polar_disk_name='nvme2n1'
+polar_datadir='/nvme2n1/shared_data/'
+primary_slot_name = 'standby1'
偷懒的做法: 直接append如下信息到~/standby/postgresql.conf , 因为PolarDB PostgreSQL对于postgresql.conf读取到重复配置时, 取最后的一个.
echo"
port=5432
polar_hostid=3
polar_enable_shared_storage_mode=on
polar_disk_name='nvme2n1'
polar_datadir='/nvme2n1/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='0.0.0.0'
max_connections=200
" >> ~/standby/postgresql.conf
echo"
# replication
primary_slot_name='standby1'
primary_conninfo='host=172.17.0.2 port=5432 user=postgres dbname=postgres application_name=standby1'
" >> ~/standby/postgresql.auto.conf
如果之前配置过primary相关的配置, 例如归档, 也要修改一下, 否则启动standby后可能报错.
vi postgresql.auto.confarchive_mode = 'on'# 如果配置为 always 的话, standby也会执行 archive_command
archive_command = 'true'
12、pb1 PolarDB 主实例主节点, 添加standby1 slot用于standby进行流复制
psql -c "SELECT * FROM pg_create_physical_replication_slot('standby1');"
slot_name | lsn
-----------+-----
standby1 |
(1 row)
13、pb3, 启动PolarDB standby容灾实例
pg_ctl -D $HOME/standby start
14、验证standby复制是否正常?
pb1 PolarDB 主实例主节点, 创建测试表, 写入测试数据
psql -c "CREATE TABLE t (t1 INT PRIMARY KEY, t2 INT); INSERT INTO t VALUES (1, 1),(2, 3),(3, 3);"
pb3, PolarDB standby容灾实例, 查询数据是否已复制过来?
psql -c "SELECT * FROM t;"
t1 | t2
----+----
1 | 1
2 | 3
3 | 3
(3 rows)
参考
《穷鬼玩PolarDB RAC一写多读集群系列 | 在Docker容器中用loop设备模拟共享存储》
https://apsaradb.github.io/PolarDB-for-PostgreSQL/zh/operation/backup-and-restore.html#%E5%A4%87%E4%BB%BD%E5%B9%B6%E6%81%A2%E5%A4%8D%E4%B8%80%E4%B8%AA-standby-%E8%8A%82%E7%82%B9
文末彩蛋:国产数据库周边生态
当然一款数据库要流行起来, 除了自己要强大, 还离不开生态. 用好周边生态工具, 管理水平战胜90%老司机!!! 下面简单介绍一下国产数据库周边生态.
1、管控软件
鸣嵩(前阿里云数据库总经理 / 研究员)等大佬们创业创办的云猿生, 核心产品是KubeBlocks. 他们的理念是让管理数据库和搭积木一样简单, 如果你要管理很多套并且种类(OLTP\OLAP\NoSQL\KV\TS\MQ等)很多的数据库产品, 推荐首选.
https://github.com/apecloud/kubeblocks
PG中文社区核心委员唐成老师的公司乘数开源的Clup, 专用管理PostgreSQL和PolarDB的集群管理软件, 如果你要管理很多套数据库, 推荐选择. 并且Clup还提供了企业版、自研的连接池、分布式存储、一体机、备份平台等, 是企业用户推荐之选.
https://www.csudata.com/
若航老司机开源的pigsty, 集成了300多个PG插件的PG集群和PolarDB集群管理软件, 如果你要管理很多套PG或PolarDB数据库, 且对插件有特别多的需求, 推荐选择.
https://pigsty.cc/zh/
2、审计监控诊断优化
翟总(曾经是我背后的男人)到海信聚好看后研发的 DBdoctor, 采用ebpf技术, 在对数据库几乎没有影响的情况下实时监控数据库和服务器的各项指标, 发现和诊断问题根因非常方便.
https://www.dbdoctor.cn/
天舟老哥的核心产品Bytebase 是位于您和数据库之间的中间件。它是数据库 DevOps 的 GitLab/GitHub,专为开发人员、DBA 和平台工程师打造。
https://bytebase.cc/docs/introduction/what-is-bytebase/
PawSQL, SQL优化和诊断产品.
D-Smart, Oracle老前辈白老大出品, 专注企业级市场, 将业界顶级DBA经验的产品化作品, 产品功能包括数据库监控、诊断、优化等.
https://www.modb.pro/db/567140
3、国产数据库IDE
IDE是开发者的必备工具,例如社区有pgAdmin, 国产IDE则可以看看老程序猿达刚老师的DeskUI:
https://www.deskui.com
4、数据同步&迁移&备份恢复
NineData, 老领导出去创业做的产品, 产品涵盖了数据同步、迁移、备份、比对、devops、chatDBA等.
https://www.ninedata.cloud/home
DSG, 非常老牌的数据库同步迁移企业级产品, 支持各种数据库的异构和同构迁移, 用他们的话说, 没有dsg搞不定的迁移, 比goldengate还牛.
https://www.dsgdata.com/
公开课
如果你对PolarDB学习感兴趣可以阅读这个公开课系列:
除了PolarDB还非常值得关注的几款PG栈国产数据库:
HaloDB(基于PG兼容PostgreSQL、Oracle、MySQL. http://www.halodbtech.com/ )、 IvorySQL(基于开源PG兼容PG、Oracle. https://www.ivorysql.org/zh-cn/ )、 ProtonBase(云原生分布式数仓. https://protonbase.com/ )、 成都文武数据库(https://ww-it.cn)
参考文档点击阅读原文获得
感谢关注我的github (https://github.com/digoal/blog) 及视频号: