暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何创建RDS PG 的秒级 flashback闪回实例, 实时容灾实例 - zfs - snapshot - clone - standby - compress

digoal 2020-03-21
1184

作者

digoal

日期

2020-03-21

标签

PostgreSQL , 闪回 , zfs


背景

阿里云 rds pg 12为例, 创建RDS PG 的秒级 flashback闪回实例, 实时容灾实例.

技术点:

zfs - snapshot - clone - postgresql stream standby - compress

例子

1、申请ecs

规格, 可用区, vpc, vswitch 建议与RDS PG相同

存储根据主库的读写压力配置, 能满足容灾库的恢复效率就可以

如果需要将容灾实例设置在跨region的机房, 建议 VPC网络打通

2、部署系统, 建议centos 7 x64

配置sysctl, limits等配置参考:

https://github.com/digoal/blog/blob/master/202002/20200229_01.md

3、部署zfs, 开启压缩

```

cat /etc/redhat-release

CentOS Linux release 7.7.1908 (Core)
```

https://github.com/openzfs/zfs/wiki/RHEL-and-CentOS

```
wget http://download.zfsonlinux.org/epel/zfs-release.el7_7.noarch.rpm

rpm -ivh zfs-release.el7_7.noarch.rpm

yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

yum install -y "kernel-devel-uname-r == $(uname -r)" zfs
```

查看日志,是否有报错,正常情况下没有报错

4、测试zfs是否可用

配置系统启动时自动加载zfs

vi /etc/rc.local /sbin/modprobe zfs

chmod +x /etc/rc.local

测试zfs是否正常

```

modprobe zfs

zpool list

no pools available

reboot

```

5、安装pg 12

https://www.postgresql.org/download/linux/redhat/

```
yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

yum install postgresql12*

su - postgres
配置环境变量

vi ~/.bash_profile

追加

export PS1="$USER@/bin/hostname -s-> "
export LANG=en_US.utf8
export PGHOME=/usr/pgsql-12
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=date +"%Y%m%d%H%M"
export PATH=$PGHOME/bin:$PATH:.
export MANPATH=$PGHOME/share/man:$MANPATH
alias rm='rm -i'
alias ll='ls -lh'
unalias vi
```

6、插件安装(根据你在RDS里面使用的插件安装, 有些插件可能是RDS独有的, 那么目前在容灾端将无法调用这些插件, 但是不影响容灾恢复)

7、配置zpool, zfs

假设/dev/vdc是新增的云盘, 如果你的云盘不是vdc请更换, zfs也支持管多快云盘, 请自行查阅zfs手册不再赘述.

```
parted -a optimal -s /dev/vdc mklabel gpt mkpart primary 1MiB 100%FREE

zpool create zp1 -f -o ashift=13 vdc1

zfs set canmount=off zp1
```

8、创建存放数据文件的目录

zfs create -o mountpoint=/zpdata01 -o recordsize=8K -o atime=off -o primarycache=metadata -o logbias=throughput -o secondarycache=none zp1/zpdata01

9、创建存放wal归档文件的目录

```
zfs create -o mountpoint=/zpdata02 -o recordsize=8K -o atime=off -o primarycache=metadata -o logbias=throughput -o secondarycache=none -o compression=on zp1/zpdata02

zfs set compression=on zp1/zpdata02

zfs list

NAME USED AVAIL REFER MOUNTPOINT
zp1 1.29M 1.42T 192K /zp1
zp1/zpdata01 192K 1.42T 192K /zpdata01
zp1/zpdata02 192K 1.42T 192K /zpdata02
```

10、创建rds实例rds_superuser用户

```
在控制台可创建:

user: rep
pwd: xxxxxx
```

11、配置rds白名单

允许该ecs连接

12、创建rds pg 12从库

```
mkdir /zpdata01/pg12_1921_data

mkdir /zpdata02/pg12_1921_wal

chown -R postgres:postgres /zpdata01/pg12_1921_data
chown -R postgres:postgres /zpdata02/pg12_1921_wal
```

```
su - postgres

export PGPASSWORD=pwd
nohup pg_basebackup -D /zpdata01/pg12_1921_data -F p -R -c fast -X stream -h pgm-bp1wv687i955y998129390.pg.rds.aliyuncs.com -p 1433 -U rep >./bak.log 2>&1 &
```

13、配置从库, 包括application_name、开启归档等

su - postgres cd /zpdata01/pg12_1921_data

注视postgresql.conf如下配置

```
grep "^#" postgresql.conf

Fri Mar 13 09:55:03 CST 2020

ssl_key_file='server.key'

huge_pages=try

auto_explain.sample_rate=1

zhparser.multi_zall=off

shared_preload_libraries='pg_stat_statements,auth_delay,auto_explain,zhparser,timescaledb,pg_pathman'

promote_trigger_file='/data/postgresql.trigger'

ssl=off

rds_max_log_files=20

pg_pathman.enable_auto_partition=on

shared_buffers=32768MB

zhparser.punctuation_ignore=off

pg_pathman.override_copy=on

port=1922

pg_stat_statements.max=5000

auth_delay.milliseconds=3s

auto_explain.log_nested_statements=off

track_io_timing=on

zhparser.multi_zmain=off

auto_explain.log_analyze=off

archive_mode=on

ssl_cert_file='server.crt'

zhparser.multi_short=off

zhparser.dict_in_memory=off

auto_explain.log_format=text

auto_explain.log_min_duration=-1

rds.rds_max_non_super_conns=12800

pg_pathman.enable=on

archive_command='/bin/date'

auto_explain.log_verbose=off

log_line_prefix='\1\n\t%p\t%r\t%u\t%d\t%t\t%e\t%T\t%S\t%U\t%E\t\t'

pg_pathman.enable_runtimemergeappend=on

zhparser.extra_dicts='dict_extra.xdb'

auto_explain.log_buffers=off

pg_stat_statements.track=top

jit_provider='llvmjit'

pg_pathman.enable_partitionrouter=off

pg_stat_statements.track_utility=off

pg_stat_statements.save=off

zhparser.dicts_type='EXTRA'

auto_explain.log_timing=on

pg_pathman.enable_runtimeappend=on

zhparser.seg_with_duality=off

rds.rds_max_super_conns=100

pg_pathman.enable_partitionfilter=on

log_destination='stderr,csvlog'

zhparser.multi_duality=off

pg_pathman.insert_into_fdw='postgres'

pg_pathman.enable_bounds_cache=on

rds.rds_max_non_super_wal_snd=32

auto_explain.log_triggers=off

rds_sync_replication_timeout=0

```

修改配置参数如下(如果没有则新增这个文件)

```
su - postgres
cd /zpdata01/pg12_1921_data

vi postgresql.auto.conf

primary_conninfo = 'user=rep password=''pwd'' host=''pgm-bp1wv687i955y998129390.pg.rds.aliyuncs.com'' port=1433 application_name=hello_rds_pg12'
port=1922
shared_buffers=32GB
log_destination='csvlog'
archive_mode=always
archive_command='test ! -f /zpdata02/pg12_1921_wal/%f && cp %p /zpdata02/pg12_1921_wal/%f'
```

14、改一下目录权限

chmod 700 /zpdata02/pg12_1921_wal chmod 700 /zpdata01/pg12_1921_data

15、启动从库

pg_ctl start -D /zpdata01/pg12_1921_data

16、配置自动启动从库

vi /etc/rc.local su - postgres -c "pg_ctl start -D /zpdata01/pg12_1921_data"

17、配置数据文件目录自动快照(归档目录不需要快照)

创建脚本, 配置执行权限

`` vi /etc/snap.sh STIME=date +%F%T`
/usr/sbin/zfs snapshot zp1/zpdata01@$STIME

chmod 500 /etc/snap.sh
```

测试快照是否正常

```
/etc/snap.sh

zfs list -t snapshot

NAME USED AVAIL REFER MOUNTPOINT
zp1/zpdata01@2020-03-2117:06:47 144K - 770M -
```

自动启动crond配置

```

systemctl start crond

systemctl enable crond

systemctl status crond

● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2020-03-21 16:16:08 CST; 53min ago
Main PID: 2526 (crond)
CGroup: /system.slice/crond.service
└─2526 /usr/sbin/crond -n

Mar 21 16:16:08 iZbp135pwcjjoxqgfpw9k1Z systemd[1]: Started Command Scheduler.
Mar 21 16:16:09 iZbp135pwcjjoxqgfpw9k1Z crond[2526]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 85% if used.)
Mar 21 16:16:09 iZbp135pwcjjoxqgfpw9k1Z crond[2526]: (CRON) INFO (running with inotify support)
```

配置crontab自动任务, 例如每天1点1分打快照, 你可以根据实际需求自己配置.

```

crontab -e

1 1 * * * /etc/snap.sh

crontab -l -u root

1 1 * * * /etc/snap.sh
```

18、配置自动清理快照

略, 手工执行清理的例子如下

```
[root@iZbp135pwcjjoxqgfpw9k1Z pg12_1921_data]# zfs list -t snapshot
zNAME USED AVAIL REFER MOUNTPOINT
zp1/zpdata01@2020-03-2117:06:47 144K - 770M -
zp1/zpdata01@2020-03-2117:17:01 0B - 786M -

[root@iZbp135pwcjjoxqgfpw9k1Z pg12_1921_data]# zfs destroy zp1/zpdata01@2020-03-2117:06:47

[root@iZbp135pwcjjoxqgfpw9k1Z pg12_1921_data]# zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
zp1/zpdata01@2020-03-2117:17:01 0B - 786M -
```

19、配置自动清理归档

[root@iZbp135pwcjjoxqgfpw9k1Z pg12_1921_data]# cd /zpdata02/pg12_1921_wal/ [root@iZbp135pwcjjoxqgfpw9k1Z pg12_1921_wal]# ll total 49 -rw------- 1 postgres postgres 16777216 Mar 21 17:06 000000010000011D00000097

手工执行例子如下, 删除7天前的wal归档文件例子

find /zpdata02/pg12_1921_wal/ -type f -mtime +7 -exec rm -f {} \;

自动化方法:

创建脚本, 配置脚本执行权限

配置crontab

20、校验备份集可用性, 参考:

https://github.com/digoal/blog/blob/master/201608/20160823_06.md

21、检测主从延迟 (primary, standby)

查询主库即可

```
postgres=> select pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_flush_lsn(),sent_lsn)) as sent_delay,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_flush_lsn(),replay_lsn)) as replay_dealy,*
from pg_stat_replication ;

-[ RECORD 1 ]----+------------------------------
sent_delay | 0 bytes
replay_dealy | 0 bytes
pid | 84098
usesysid | 886185
usename | rep
application_name | hello_rds_pg12
client_addr | 192.168.0.173
client_hostname |
client_port | 60402
backend_start | 2020-03-21 16:59:01.890775+08
backend_xmin |
state | streaming
sent_lsn | 11D/97002068
write_lsn | 11D/97002068
flush_lsn | 11D/97002068
replay_lsn | 11D/97002068
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2020-03-21 17:01:17.198139+08
```

闪回例子

1、列出快照, 注意快照的时间点

```

zfs list -t snapshot

NAME USED AVAIL REFER MOUNTPOINT
zp1/zpdata01@2020-03-2117:17:01 312K - 786M -
```

2、选出需要恢复的目标时间点之前的一个快照, 最好选离恢复时间最近的(但是一定要之前的, 如果你选择的快照不够前(至少距离一个checkpoint检查点), 则重新选择更前的).

基于快照克隆一个zfs文件系统

```

zfs clone -o mountpoint=/test_recovery zp1/zpdata01@2020-03-2117:17:01 zp1/zpdata_test

[root@iZbp135pwcjjoxqgfpw9k1Z pg12_1921_wal]# cd /test_recovery
[root@iZbp135pwcjjoxqgfpw9k1Z test_recovery]# ll
total 17
drwx------ 20 postgres postgres 35 Mar 21 16:59 pg12_1921_data
```

3、配置, 包括端口, 恢复目标recovery_target_time等

```
su - postgres
cd /test_recovery/pg12_1921_data

vi postgresql.auto.conf

port=1923
shared_buffers=32GB
log_destination='csvlog'
recovery_end_command = 'cp /zpdata02/pg12_1921_wal/%f %p'
recovery_target_time = '2020-03-21 17:28:37.670338+08'
recovery_target_timeline = 'latest'
recovery_target_action = 'pause'
```

如果你的服务器内存不足, 可以设置较小的shared_buffer

4、删除克隆文件系统中的socket, pid等文件

rm -f /test_recovery/pg12_1921_data/.s.* rm /test_recovery/pg12_1921_data/postmaster.pid

5、启动恢复

pg_ctl start -D /test_recovery/pg12_1921_data

6、打开恢复库

```
psql -h /test_recovery/pg12_1921_data -p 1923 -U rep postgres
psql (12.1)
Type "help" for help.

postgres=> \dt
List of relations
Schema | Name | Type | Owner
--------+------------------+-------+--------
public | pgbench_branches | table | digoal
public | pgbench_history | table | digoal
public | pgbench_tellers | table | digoal
(3 rows)
```

克隆库用完后, 停库, 清理克隆的test_recovery文件系统即可。

```
su - postgres

pg_ctl stop -m fast -D /test_recovery/pg12_1921_data

sudo

zfs destroy zp1/zpdata_test
```

小结

使用这个方法, 在zfs文件系统中创建了一个实时standby, 使用cron定期打快照(不管多少数据量, 秒级快照), 恢复时找到最近的快照, 可以快速恢复.

zfs是个不错的文件系统, 支持快照, 压缩等功能, 非常棒.

参考

https://github.com/openzfs/zfs/wiki/FAQ

https://github.com/digoal/blog/blob/master/201809/20180919_01.md

PostgreSQL 许愿链接

您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.

9.9元购买3个月阿里云RDS PostgreSQL实例

PostgreSQL 解决方案集合

德哥 / digoal's github - 公益是一辈子的事.

digoal's wechat

文章转载自digoal,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论