今天我们在上次搭建环境的基础上继续工作,一个单一的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 表示这个从库现在是异步的,但可能在当前的同步库失效时变成同步的。
通常我们搭建主从,除了做数据备份之外(防止主库数据丢失我有别的库能恢复) 更多的是去做读写分离(即 写操作发送到主库,大量的查询操作发送到从库执行) 因为主从库的数据完全一致,所以这种方式能极大的减少主库的压力。
但是,异步主从复制是不能保证数据实时一致的,所以这种简易的主从会出现主从查询数据不一致。
如何搭建一个同步集群呢?主从复制又是怎么工作的?我们下集接着说!