Linux 系统搭建PostgreSQL 集群 - 异步主从 (二)

2,866

今天我们在上次搭建环境的基础上继续工作,一个单一的PostgreSQL 实例我们测试可能够用了,但是作为要部署生产环境的我们,怎么可能不去搭建集群呢?

今天我们就来从最基础的异步主从开始,逐步搭建postgreSQL的主从环境

1. 创建主从复制的用户, 我们用repl

既然是用来主从复制的用户,那么我们只要给复制的权限就行啦!

create user repl with replication;

2. 创建从库的相关目录

我们这里搭建一个1主1从,两个实例的PG集群,后面我们会搭建更复杂的集群以及更稳健的集群模式

(1). 修改主库的配置文件,并重启主库

 cluster_name = 'prd'		# 配置主库的name 给每个库配置一个名字后面主从的时候能用上
 log_timezone = 'Asia/Shanghai'	# 修改时区,方便出问题的时候根据时间定位日志
 timezone = 'Asia/Shanghai'

 archive_mode = 'on'   # 开启wal段文件归档操作 可以选择不开启
 archive_command = 'cp %p /chason/postgres/instances/pg6100/wal/%f' #  具体怎么进行归档 上面如果是off 则下面也不用配置
      
 wal_keep_size = 16  # 从 PG13.0以后开始 将wal_keep_segment 更名为 wal_keep_size 表示保存过去wal文件的数量

(2)修改 pg_hba.conf

在文件最后加上下面的配置给 repl 用户复制的权限

host    replication     repl            0.0.0.0/0               md5

PS: 如果上面配置了archive_command 那么其中对应的目录需要提前手工创建

3. 使用主从流复制 从主库上复制一个 backup 形成从库

pg_basebackup -h 127.0.0.1 -U repl -p 6100 -F p -X s -v -P -R -D /chason/postgres/instances/pg6101/data 

PS: 参数解读

 -h --host  很好理解  ip
 -U --username 用户名  一般是用于专门主从复制的用户
 -p --port  master的端口号
 -F --format 可选 p plain 或者 t tar
 -X --wal-method  wal 主从复制的方式  一般有none fetch stream  我们一般选择stream
 -v --verbose  相当于输出更详细的信息 类似于日志模式的debug
 -P --progress 展示progress的一些信息
 -R --write-recovery-conf 这是一个核心配置,虽然13.8这个版本已经没有recovery.conf 但是会在从库中出现一个standby.signal文件,有这个文件表示这是一个从库
 -D --pgdata  pg的data路径 这个路径是你准备将主库复制到哪里,就是你从库的data目录 

如果执行backup不出问题,那么就应该像下面一样

[postgres@localhost ~]$ pg_basebackup -h 127.0.0.1 -U repl -p 6100 -F p -X s -v -P -R -D /chason/postgres/instances/pg6101/data
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/3000028 on timeline 1
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_85992"
24288/24288 kB (100%), 1/1 tablespace                                         
pg_basebackup: write-ahead log end point: 0/3000138
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: syncing data to disk ...
pg_basebackup: renaming backup_manifest.tmp to backup_manifest
pg_basebackup: base backup completed

4. 修改从库的配置文件 postgresql.conf

cluster_name = 'ldr'	# 给从库起个新名字

data_directory = '/chason/postgres/instances/pg6101/data'   		# 从库的路径都需要修改
hba_file = '/chason/postgres/instances/pg6101/data/pg_hba.conf'
ident_file = '/chason/postgres/instances/pg6101/data/pg_ident.conf'

port = 6101 		# 修改从库的服务端口

archive_command = 'cp %p /chason/postgres/instances/pg6101/wal/%f'	# 如果开启了archive 这里也需要修改

5. 启动从库

[postgres@localhost data]$ pg_ctl start -D /chason/postgres/instances/pg6101/data/
waiting for server to start....2023-02-07 09:53:06.326 CST [86097] FATAL:  data directory "/chason/postgres/instances/pg6101/data" has invalid permissions
2023-02-07 09:53:06.326 CST [86097] DETAIL:  Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).
 stopped waiting
pg_ctl: could not start server
Examine the log output.

报错了,是因为从库的data 文件夹权限有要求,他需要700 或者750 权限,我们来看看我们的。

[postgres@localhost pg6101]$ ll -a
total 4
drwxrwxr-x.  4 postgres postgres   29 Feb  7 09:45 .
drwxrwxr-x.  5 postgres postgres   48 Feb  6 10:05 ..
drwxrwxr-x. 19 postgres postgres 4096 Feb  7 09:51 data
drwxrwxr-x.  2 postgres postgres    6 Feb  7 09:45 wal

我们的文件夹是775肯定不行 我们修改data 文件夹权限

[postgres@localhost pg6101]$ chmod 700 data/

再次尝试启动从库

[postgres@localhost pg6101]$ pg_ctl start -D /chason/postgres/instances/pg6101/data/
waiting for server to start....2023-02-07 09:55:44.205 CST [86155] LOG:  starting PostgreSQL 13.8 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16), 64-bit
2023-02-07 09:55:44.207 CST [86155] LOG:  listening on IPv4 address "0.0.0.0", port 6101
2023-02-07 09:55:44.207 CST [86155] LOG:  listening on IPv6 address "::", port 6101
2023-02-07 09:55:44.210 CST [86155] LOG:  listening on Unix socket "/tmp/.s.PGSQL.6101"
2023-02-07 09:55:44.216 CST [86156] LOG:  database system was interrupted; last known up at 2023-02-07 09:46:49 CST
2023-02-07 09:55:44.224 CST [86156] LOG:  entering standby mode
2023-02-07 09:55:44.226 CST [86156] LOG:  redo starts at 0/3000028
2023-02-07 09:55:44.227 CST [86156] LOG:  consistent recovery state reached at 0/3000138
2023-02-07 09:55:44.227 CST [86155] LOG:  database system is ready to accept read only connections
2023-02-07 09:55:44.237 CST [86160] LOG:  started streaming WAL from primary at 0/4000000 on timeline 1
 done
server started

发现从库启动成功

6. 验证主从是否连接上了

我们的登录主库

[postgres@localhost pg6101]$ psql -h127.0.0.1 -Upostgres -p6100
psql (13.8)
Type "help" for help.

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 | repla
y_lag | sync_priority | sync_state |          reply_time           
-------+----------+---------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+-----------+-----------+-----------+------------+-----------+-----------+------
------+---------------+------------+-------------------------------
 86161 |    16384 | repl    | ldr              | 127.0.0.1   |                 |       47060 | 2023-02-07 09:55:44.232031+08 |              | streaming | 0/4000148 | 0/4000148 | 0/4000148 | 0/4000148  |           |           |      
      |             0 | async      | 2023-02-07 09:57:04.444961+08
(1 row)

postgres=#

发现我们的ldr已经挂上去了,这样一个主从就搭建完成了,如果你想搭建一主多从的集群,重复上面的操作即可。

7. 一些后话

发现没, PG搭建主从其实非常简单,只要执行复制,然后修改配置文件,最后启动起来就行了,但是,我们搭建的这个从库他是个异步的主库,从什么地方看呢?

我们根据 pg_stat_replciation 这张表的字段 sync_state 来判断

postgres=# select application_name, sync_state from pg_stat_replication;
 application_name | sync_state 
------------------+------------
 ldr              | async
(1 row)

这个状态一般有三种:

  • async 表示异步
  • sync 表示优先级最高的同步节点
  • potential 表示这个从库现在是异步的,但可能在当前的同步库失效时变成同步的。

通常我们搭建主从,除了做数据备份之外(防止主库数据丢失我有别的库能恢复) 更多的是去做读写分离(即 写操作发送到主库,大量的查询操作发送到从库执行) 因为主从库的数据完全一致,所以这种方式能极大的减少主库的压力。

但是,异步主从复制是不能保证数据实时一致的,所以这种简易的主从会出现主从查询数据不一致。

如何搭建一个同步集群呢?主从复制又是怎么工作的?我们下集接着说!