PolarDB开源数据库进阶课10 计算节点全毁, 灾难恢复

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介: 本文介绍了在PolarDB RAC一写多读集群中,当所有计算节点(主机)故障仅剩共享存储时的修复方法。实验基于Docker容器和loop设备模拟共享存储环境。通过重建计算节点、恢复PolarDB实例及配置相关参数,最终成功恢复RW和RO节点的功能,确保数据完整性和集群正常运行。视频回放可在B站和YouTube上查看。

背景

穷鬼玩PolarDB RAC一写多读集群系列已经写了几篇:

本篇文章介绍一下如果PolarDB的主机(计算节点)全挂了, 只剩共享存储, 应该如何修复集群? 实验环境依赖 《在Docker容器中用loop设备模拟共享存储》 , 如果没有环境, 请自行参考以上文章搭建环境.

视频回放

b站视频链接

Youtube视频链接

捣毁主机

1、破坏pb1 PolarDB RW节点

pg_ctl stop -m fast -D ~/primary  
  
rm -rf ~/primary

2、破坏pb2 PolarDB RO节点

pg_ctl stop -m fast -D ~/replica1  
  
rm -rf ~/replica1

现在只剩下共享存储, PolarDB 还能抢救吗?

3、索性破坏彻底一点, 把pb1, pb2容器都删掉, 彻底没了就更好玩了.

docker stop pb1  
docker stop pb2  
  
docker rm pb1  
docker rm pb2

把macOS上的Docker Desktop也重启一下, 连loop块设备都没了.

现在只剩下模拟成共享盘的这个文件, 接下来一步一步恢复.

$ cd ~/data_volumn/  
$ ll VirtualDisk.img   
-rw-r--r--  1 digoal  staff    20G Dec 24 11:29 VirtualDisk.img

DEMO

和原来的计算节点一样, 使用 polardb_pg_devel:ubuntu22.04 镜像, 自带pfs, 无需再安装pfs.

1、启动容器pb1

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 pb1 registry.cn-hangzhou.aliyuncs.com/polardb_pg/polardb_pg_devel:ubuntu22.04 bash

记录容器pb1 IP地址

进入容器pb1    
docker exec -ti pb1 bash    
    
ip addr show    
172.17.0.2

2、启动容器pb2

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 pb2 registry.cn-hangzhou.aliyuncs.com/polardb_pg/polardb_pg_devel:ubuntu22.04 bash

记录容器pb2 IP地址

进入容器pb2    
docker exec -ti pb2 bash    
    
ip addr show    
172.17.0.3

3、在pb1中使用共享的VirtualDisk.img文件创建loop设备, 需要找到一个空闲的loop设备, 从loop0开始找, 逐渐增加数字. 直到创建loopN成功.

使用 losetup -f 找第一个未使用的loop设备.  
$ losetup -f  
/dev/loop1  
  
创建loop设备  
$ sudo losetup --direct-io=on /dev/loop1 /data/VirtualDisk.img    
  
$ ll /dev/loop1    
brw-rw-rw- 1 root root 7, 1 Dec 16 13:52 /dev/loop1

将loop设备软链到nvme1n1方便使用, 如果你的容器内已经有这个名字, 可以换一个例如nvme2n1.

# 注意: 容器重启后, 这个软链就不存在了, 需重新创建该软链     
  
sudo ln -s /dev/loop1 /dev/nvme1n1

4、pb2直接使用pb1创建的loop1即可. (由于我这个环境任何一个容器创建了loop block设备其他容器都能看到. 在实际的生产环境中, 创建loop设备的过程对应的是SAN给主机分配LUN的过程.)

将loop设备软链到nvme1n1方便使用, 如果你的容器内已经有这个名字, 可以换一个例如nvme2n1.

# 注意: 容器重启后, 这个软链就不存在了, 需重新创建该软链     
  
sudo ln -s /dev/loop1 /dev/nvme1n1

5、在pb1, pb2都启动pfsd, -w为工作进程数量, 数字越大IO性能越好, 这里受制于容器资源限制设置为1.

pb1 , pb2

sudo /usr/local/polarstore/pfsd/bin/start_pfsd.sh -p nvme1n1 -w 1

现在共享盘都挂好了, pfsd也启动了, 可以看到共享盘中的数据都还在.

$ sudo pfs -C disk ls /nvme1n1/  
  
  File  1     4194304           Tue Dec 24 09:45:40 2024  .pfs-paxos  
  File  1     1073741824        Tue Dec 24 09:45:41 2024  .pfs-journal  
   Dir  1     1536              Tue Dec 24 09:52:24 2024  shared_data  
total 2105344 (unit: 512Bytes)

接下来就安装PolarDB 二进制, 创建计算节点, 恢复PolarDB集群.

6、编译polardb 15.

之前编译过, 直接从共享盘拷贝二进制. 如果你想体验一下编译过程请参考: 《穷鬼玩PolarDB RAC一写多读集群系列 | 在Docker容器中用loop设备模拟共享存储》

pb1, pb2. 拷贝PolarDB二进制.

$ cp -r /data/polardb/tmp_polardb_pg_15_base ~/
# 或者使用软链也可以, 软链还有个好处, 编译插件时只需要编译一次即可:   
$ ln -s /data/polardb/tmp_polardb_pg_15_base ~/  
    
    
$ which psql    
/home/postgres/tmp_polardb_pg_15_base/bin/psql

7、pb1 恢复primary节点

实际参考了增加replica节点的步骤, 只是把配置文件修改了一下.

mkdir -m 0700 $HOME/primary    
sudo /home/postgres/tmp_polardb_pg_15_base/bin/polar-initdb.sh $HOME/primary/ /nvme1n1/shared_data/ replica    
sudo chmod -R 700 $HOME/primary    
sudo chown -R postgres:postgres  $HOME/primary

生成配置文件模板

initdb -D /tmp/primary    
cp /tmp/primary/*.conf $HOME/primary/  
rm -rf /tmp/primary

修改配置文件

postgresql.conf

echo "    
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='0.0.0.0'    
max_connections=200  
# 下面几个参数解决replica不能promote的问题, 因为RO依赖logindex.  
polar_logindex_mem_size=64MB  
polar_xlog_queue_buffers=64MB  
polar_xlog_page_buffers=64MB  
# 使用pfs时可以关掉 full page write 和 polar_has_partial_write , 否则请打开这两   
full_page_writes = off  
polar_has_partial_write = off
polar_resource_manager.enable_resource_manager=off
" >> ~/primary/postgresql.conf

pg_hba.conf

echo "      
host all all 0.0.0.0/0 md5      
host  replication postgres  172.17.0.0/16 trust      
" >> ~/primary/pg_hba.conf

启动RW节点

pg_ctl start -D $HOME/primary

PolarDB实例里的数据都还在, slot也还在, 启动后standby立刻就连上来了.

$ psql  
psql (PostgreSQL 15.10 (PolarDB 15.10.2.0 build d4f5477d debug) on aarch64-linux-gnu)  
Type "help" for help.  
  
postgres=# \dt  
        List of relations  
 Schema | Name | Type  |  Owner     
--------+------+-------+----------  
 public | t    | table | postgres  
 public | t1   | table | postgres  
 public | t2   | table | postgres  
 public | tbl  | table | postgres  
(4 rows)  
  
  
postgres=# select * from pg_stat_replication;  
 pid | usesysid | usename  | application_name | client_addr | client_hostname | client_port |         backend_start         | backend_xmin |   state   |  sent_lsn  | write_lsn  | flush_lsn  | replay_lsn  
 |    write_lag    |    flush_lag    |   replay_lag    | sync_priority | sync_state |          reply_time             
-----+----------+----------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------+------------+-----------  
-+-----------------+-----------------+-----------------+---------------+------------+-------------------------------  
 794 |       10 | postgres | standby1         | 172.17.0.4  |                 |       57176 | 2024-12-24 11:24:41.435003+08 |              | streaming | 0/40945898 | 0/40945898 | 0/40945898 | 0/40945898  
 | 00:00:00.000545 | 00:00:00.000579 | 00:00:00.000822 |             0 | async      | 2024-12-24 11:24:52.820741+08  
(1 row)  
  
  
postgres=# select * from pg_replication_slots ;  
 slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase   
-----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------  
 replica1  |        | physical  |        |          | f         | f      |            |      |              | 0/409455B0  |                     | reserved   |               | f  
 standby1  |        | physical  |        |          | f         | t      |        794 |      |              | 0/40945898  |                     | reserved   |               | f  
(2 rows)

RW节点启动过后, 写入一些数据

postgres=# \d t1  
                 Table "public.t1"  
 Column |  Type   | Collation | Nullable | Default   
--------+---------+-----------+----------+---------  
 id     | integer |           |          |   
  
postgres=# insert into t1 values (100);  
INSERT 0 1  
postgres=# select * from t1;  
 id    
-----  
   1  
 100  
(2 rows)

pb3 standby 节点立即就能查到新增的数据. (由于docker desktop重启过, pb3的loop设备可能要新建, nvme软链也要新建, pfsd要启动, 再启动standby.)

$ sudo losetup --direct-io=on /dev/loop2 /data/VirtualDisk_standby.img   
$ sudo ln -s /dev/loop2 /dev/nvme2n1    
$ sudo /usr/local/polarstore/pfsd/bin/start_pfsd.sh -p nvme2n1 -w 1   
$ pg_ctl start -D ~/standby   
  
$ psql  
psql (PostgreSQL 15.10 (PolarDB 15.10.2.0 build d4f5477d debug) on aarch64-linux-gnu)  
Type "help" for help.  
  
postgres=# select * from t1;  
 id    
-----  
   1  
 100  
(2 rows)

到此RW节点就恢复正常了.

8、pb2 恢复replica节点

mkdir -m 0700 $HOME/replica1    
sudo /home/postgres/tmp_polardb_pg_15_base/bin/polar-initdb.sh $HOME/replica1/ /nvme1n1/shared_data/ replica    
sudo chmod -R 700 $HOME/replica1    
sudo chown -R postgres:postgres  $HOME/replica1

生成配置文件模板

initdb -D /tmp/replica1    
cp /tmp/replica1/*.conf $HOME/replica1/  
rm -rf /tmp/replica1

修改配置文件

postgresql.conf 与primary略有不同,

echo "    
port=5432    
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='0.0.0.0'    
max_connections=200  
# 下面几个参数解决replica不能promote的问题, 因为RO依赖logindex.  
polar_logindex_mem_size=64MB  
polar_xlog_queue_buffers=64MB  
polar_xlog_page_buffers=64MB  
# 使用pfs时可以关掉 full page write 和 polar_has_partial_write , 否则请打开这两   
full_page_writes = off  
polar_has_partial_write = off
polar_resource_manager.enable_resource_manager=off
  
# replication  # 注意  
primary_slot_name='replica1'    
primary_conninfo='host=172.17.0.2 port=5432 user=postgres dbname=postgres application_name=replica1'    
" >> ~/replica1/postgresql.conf

pg_hba.conf

echo "      
host all all 0.0.0.0/0 md5      
host  replication postgres  172.17.0.0/16 trust      
" >> ~/replica1/pg_hba.conf

标识节点以 Replica 模式启动

touch $HOME/replica1/replica.signal

启动RO节点

pg_ctl start -D $HOME/replica1

在pb1 RW节点, 检查slot状态是否正常, 修改数据

postgres=# select * from pg_stat_replication;  
 pid  | usesysid | usename  | application_name | client_addr | client_hostname | client_port |         backend_start         | backend_xmin |   state   |  sent_lsn  | write_lsn  | flush_lsn  | replay_ls  
n |    write_lag    |    flush_lag    |   replay_lag    | sync_priority | sync_state |          reply_time             
------+----------+----------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------+------------+----------  
--+-----------------+-----------------+-----------------+---------------+------------+-------------------------------  
 6299 |       10 | postgres | replica1         | 172.17.0.3  |                 |       53504 | 2024-12-24 14:13:34.411357+08 |              | streaming | 0/40945F50 | 0/40945F50 | 0/40945F50 | 0/40945F5  
0 | 00:00:00.000111 | 00:00:00.000111 | 00:00:00.000328 |             0 | async      | 2024-12-24 14:14:01.09425+08  
  215 |       10 | postgres | standby1         | 172.17.0.4  |                 |       53910 | 2024-12-24 14:07:11.652935+08 |              | streaming | 0/40945F50 | 0/40945F50 | 0/40945F50 | 0/40945F5  
0 | 00:00:00.000422 | 00:00:00.000468 | 00:00:00.000696 |             0 | async      | 2024-12-24 14:14:01.094546+08  
(2 rows)  
  
postgres=# insert into t1 values (200);  
INSERT 0 1  
postgres=# select * from t1;  
 id    
-----  
   1  
 100  
 200  
(3 rows)

在pb2 检查修改已生效

postgres=# select * from t1;  
 id    
-----  
   1  
 100  
 200  
(3 rows)

到此RO节点完成修复.

参考

《穷鬼玩PolarDB RAC一写多读集群系列 | 在Docker容器中用loop设备模拟共享存储》

《穷鬼玩PolarDB RAC一写多读集群系列 | 如何搭建PolarDB容灾(standby)节点》

《穷鬼玩PolarDB RAC一写多读集群系列 | 共享存储在线扩容》

《穷鬼玩PolarDB RAC一写多读集群系列 | 计算节点 Switchover》

《穷鬼玩PolarDB RAC一写多读集群系列 | 在线备份》

《穷鬼玩PolarDB RAC一写多读集群系列 | 在线归档》

《穷鬼玩PolarDB RAC一写多读集群系列 | 实时归档》

《穷鬼玩PolarDB RAC一写多读集群系列 | 时间点恢复(PITR)》

《穷鬼玩PolarDB RAC一写多读集群系列 | 读写分离》

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
2月前
|
Cloud Native 关系型数据库 分布式数据库
世界第一!阿里云PolarDB刷新全球数据库性能及性价比记录
世界第一!阿里云PolarDB刷新全球数据库性能及性价比记录
|
2月前
|
关系型数据库 分布式数据库 数据库
喜报|PolarDB开源社区荣获“2024数据库国内活跃开源项目”奖
喜报|PolarDB开源社区荣获“2024数据库国内活跃开源项目”奖
|
2月前
|
关系型数据库 分布式数据库 数据库
首届全国大学生计算机系统能力大赛PolarDB数据库创新设计赛(天池杯)圆满收官
首届全国大学生计算机系统能力大赛PolarDB数据库创新设计赛(天池杯)圆满收官
|
2月前
|
Cloud Native 关系型数据库 分布式数据库
世界第一!阿里云PolarDB登顶全球数据库性能及性价比排行榜!
2月26日,阿里云PolarDB在2025开发者大会上登顶全球数据库性能及性价比排行榜。此次突破标志着中国基础软件取得里程碑成就,PolarDB凭借创新的云原生架构,成功应对全球最大规模并发交易峰值,在性能、可扩展性等方面领先全球。
|
2月前
|
存储 关系型数据库 分布式数据库
PolarDB开源数据库进阶课18 通过pg_bulkload适配pfs实现批量导入提速
本文介绍了如何修改 `pg_bulkload` 工具以适配 PolarDB 的 PFS(Polar File System),从而加速批量导入数据。实验环境依赖于 Docker 容器中的 loop 设备模拟共享存储。通过对 `writer_direct.c` 文件的修改,替换了一些标准文件操作接口为 PFS 对应接口,实现了对 PolarDB 15 版本的支持。测试结果显示,使用 `pg_bulkload` 导入 1000 万条数据的速度是 COPY 命令的三倍多。此外,文章还提供了详细的步骤和代码示例,帮助读者理解和实践这一过程。
87 1
|
2月前
|
Cloud Native 关系型数据库 分布式数据库
世界第一!阿里云PolarDB刷新全球数据库性能及性价比记录
世界第一!阿里云PolarDB刷新全球数据库性能及性价比记录
|
2月前
|
存储 NoSQL 关系型数据库
PolarDB开源数据库进阶课17 集成数据湖功能
本文介绍了如何在PolarDB数据库中接入pg_duckdb、pg_mooncake插件以支持数据湖功能, 可以读写对象存储的远程数据, 支持csv, parquet等格式, 支持delta等框架, 并显著提升OLAP性能。
119 1
|
2月前
|
存储 容灾 关系型数据库
PolarDB开源数据库进阶课11 激活容灾(Standby)节点
本文介绍了如何激活PolarDB容灾(Standby)节点,实验环境依赖于Docker容器中用loop设备模拟共享存储。通过`pg_ctl promote`命令可以将Standby节点提升为主节点,使其能够接收读写请求。激活后,原Standby节点不能再成为PolarDB集群的Standby节点。建议删除对应的复制槽位以避免WAL文件堆积。相关操作和配置请参考系列文章及视频教程。
66 1
|
2月前
|
存储 关系型数据库 分布式数据库
PolarDB开源数据库进阶课5 在线备份
本文介绍了如何在PolarDB RAC一写多读集群中进行在线备份,特别针对共享存储模式。通过使用`polar_basebackup`工具,可以将实例的本地数据和共享数据备份到本地盘中。实验环境依赖于Docker容器中用loop设备模拟的共享存储。
65 1
|
2月前
|
存储 关系型数据库 分布式数据库
PolarDB开源数据库进阶课15 集成DeepSeek等大模型
本文介绍了如何在PolarDB数据库中接入私有化大模型服务,以实现多种应用场景。实验环境依赖于Docker容器中的loop设备模拟共享存储,具体搭建方法可参考相关系列文章。文中详细描述了部署ollama服务、编译并安装http和openai插件的过程,并通过示例展示了如何使用这些插件调用大模型API进行文本分析和情感分类等任务。此外,还探讨了如何设计表结构及触发器函数自动处理客户反馈数据,以及生成满足需求的SQL查询语句。最后对比了不同模型的回答效果,展示了deepseek-r1模型的优势。
157 0

相关产品

  • 云原生数据库 PolarDB
  • 下一篇
    oss创建bucket