下载安装 postgresql-14
# Install the repository RPM:
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Install PostgreSQL:
sudo yum install -y postgresql14-server
# Optionally initialize the database and enable automatic start:
sudo /usr/pgsql-14/bin/postgresql-14-setup initdb
修改配置文件
"/var/lib/pgsql/14/data/postgresql.conf"
listen_addresses = '*' # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost'; use '*' for all
# (change requires restart)
port = 5432 # (change requires restart)
"/var/lib/pgsql/14/data/pg_hba.conf"
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
host all all 0.0.0.0/0 md5
启动 postgresql-14 服务
启动命令:systemctl start postgresql-14
重启命令:systemctl restart postgresql-14
停止命令:systemctl stop postgresql-14
切换到安装自动创建的 postgres 用户,修改密码(默认无密码)
[root@localhost ~]# su - postgres
-bash-4.2$ psql
psql (14.5)
输入 "help" 来获取帮助信息.
postgres=# ALTER USER postgres ENCRYPTED PASSWORD '961231zqf';
ALTER ROLE
postgres=# exit
-bash-4.2$ exit
登出
使用连接工具 navicat 进行测试,注意关闭防火墙
systemctl stop firewalld.service
systemctl disable firewalld.service
执行安装,centOS 中没有对应的安装包,需进行配置
在 root 用户下输入下列命令并执行
yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{centos})-x86_64/pgdg-redhat-repo-latest.noarch.rpm
配置 timescaledb 仓库
tee /etc/yum.repos.d/timescale_timescaledb.repo <<EOL
[timescale_timescaledb]
name=timescale_timescaledb
baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
EOL
更新本地仓库列表
yum update
执行安装
yum install timescaledb-2-postgresql-14
修改配置文件/var/lib/pgsql/14/data/postgresql.conf
,配置时序库
shared_preload_libraries = 'timescaledb' # (change requires restart)
创建目录,并将修改后的配置文件复制到该目录下
mkdir -p /etc/postgresql/14/main/
cp /var/lib/pgsql/14/data/postgresql.conf /etc/postgresql/14/main/
使用 navicat 连接数据库,首先创建新的数据库 timescaledb
CREATE DATABASE timescaledb;
连接到新创建的数据库,进行扩展
CREATE EXTENSION IF NOT EXISTS timescaledb;
主库 | 从库 |
---|---|
192.168.86.133 | 192.168.86.131 |
修改配置文件:"/var/lib/pgsql/14/data/postgresql.conf"
,主要关注wal_level
属性
wal_level = replica # minimal, replica, or logical
# (change requires restart)
在主库中创建一个用于复制的账号,用户名密码均为 repl
[root@localhost ~]# su - postgres
上一次登录:四 11月 3 17:11:18 CST 2022pts/1 上
-bash-4.2$ psql
psql (14.5)
输入 "help" 来获取帮助信息.
postgres=# create role repl login replication encrypted password 'repl';
CREATE ROLE
postgres=# exit
-bash-4.2$ exit
登出
修改配置文件:"/var/lib/pgsql/14/data/pg_hba.conf"
,添加下列配置
host replication repl 192.168.86.131/32 md5
重启主库服务
systemctl restart postgresql-14
至此主库配置完毕
首先停止从库服务
systemctl stop postgresql-14
删除数据库主目录 data
[root@localhost ~]# cd /var/lib/pgsql/14
[root@localhost 14]# rm -rf data
使用pg_basebackup
命令同步数据库
[root@localhost 14]# pg_basebackup -h 192.168.86.133 -p 5432 -U repl -R -F p -P -D data
参数说明:
选项 说明
-p 主库数据库端口
-U 流复制用户
-W 使用密码验证,要用replica的密码
-Fp 备份输出正常的数据库目录
-Xs 使用流复制的方式进行复制
-Pv 输出复制过程的详细信息
-R 为备库创建recovery.conf文件。但是pgsql 10以后的新版本的pgsql不需要这个文件了。
-D 指定创建的备库的数据库目录
重新启动从库数据库服务
systemctl restart postgresql-14
若存在启动失败问题,则可能是权限问题导致
[root@localhost 14]# systemctl restart postgresql-14
Job for postgresql-14.service failed because the control process exited with error code. See "systemctl status postgresql-14.service" and "journalctl -xe" for details.
[root@localhost 14]# systemctl status postgresql-14
● postgresql-14.service - PostgreSQL 14 database server
Loaded: loaded (/usr/lib/systemd/system/postgresql-14.service; disabled; vendor preset: disabled)
Active: failed (Result: exit-code) since 五 2022-11-04 08:37:21 CST; 35s ago
Docs: https://www.postgresql.org/docs/14/static/
Process: 1392 ExecStartPre=/usr/pgsql-14/bin/postgresql-14-check-db-dir ${PGDATA} (code=exited, status=1/FAILURE)
11月 04 08:37:21 localhost.localdomain systemd[1]: Starting PostgreSQL 14 database server...
11月 04 08:37:21 localhost.localdomain systemd[1]: postgresql-14.service: control process exited, code=exited status=1
11月 04 08:37:21 localhost.localdomain systemd[1]: Failed to start PostgreSQL 14 database server.
11月 04 08:37:21 localhost.localdomain systemd[1]: Unit postgresql-14.service entered failed state.
11月 04 08:37:21 localhost.localdomain systemd[1]: postgresql-14.service failed.
重新为 postgres 用户授权,启动服务成功
[root@localhost 14]# chown -R postgres:postgres /var/lib/pgsql/14/data
[root@localhost 14]# systemctl start postgresql-14
至此简单的主从流复制配置完成,可连接数据库进行操作进行检验,从库为只读库,可以在主库执行下列命令查询从库相关信息
select pid,state,client_addr,sync_priority,sync_state,sent_lsn,write_lsn from pg_stat_replication;
流复制分为同步流复制和异步流复制:
同步流复制:可以在主库故障时确保数据的一致,但是当网络或者备库出现问题时,会导致主库的事务 hang 住;
异步流复制:不会影响主库的性能,但是在主库故障时,可能会丢掉小部分数据;
上述的流复制配置过程为异步流复制的配置过程,可以通过指令查看当前的数据库状态
使用 postgres 用户登录数据库,执行查询,可以看到sync_state
对应的值为async
select * from pg_stat_replication;
修改主库配置文件/var/lib/pgsql/14/data/postgresql.conf
,配置ynchronous_standby_names
属性
synchronous_standby_names = 'slave'
重新启动主数据库
cd /usr/pgsql-14/bin/
./pg_ctl restart
使用 postgres 用户登录备用数据库,查询备库状态,保存conninfo
字段的信息
select * from pg_stat_wal_receiver;
修改备库的系统设置,新值为上一步保存的conninfo
字段信息加上application_name=slave
alter system set primary_conninfo = 'application_name=slave user=repl password=repl channel_binding=disable host=192.168.86.133 port=5432 sslmode=disable sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any';
重新启动从数据库
cd /usr/pgsql-14/bin/
./pg_ctl restart
重新查看主库状态
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
------+----------+---------+------------------+----------------+-----------------+-------------+-------------------------------+--------------+-----------+------------+------------
+------------+------------+-----------------+-----------------+-----------------+---------------+------------+-------------------------------
1915 | 24577 | repl | slave | 192.168.86.131 | | 47664 | 2022-11-09 09:52:11.088431+08 | | streaming | 0/DD99DFA8 | 0/DD99DFA8
| 0/DD99DFA8 | 0/DD99DFA8 | 00:00:00.001495 | 00:00:00.002756 | 00:00:00.003071 | 1 | sync | 2022-11-09 09:52:11.469006+08
(1 行记录)
重新查看备库状态
postgres=# select * from pg_stat_wal_receiver ;
pid | status | receive_start_lsn | receive_start_tli | written_lsn | flushed_lsn | received_tli | last_msg_send_time | last_msg_receipt_time | latest_end_ls
n | latest_end_time | slot_name | sender_host | sender_port |
conninfo
------+-----------+-------------------+-------------------+-------------+-------------+--------------+-------------------------------+-------------------------------+--------------
--+-----------------------------+-----------+----------------+-------------+--------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------
1626 | streaming | 0/DD000000 | 1 | 0/DD99DFA8 | 0/DD99DFA8 | 1 | 2022-11-09 09:52:41.495931+08 | 2022-11-09 09:52:41.491104+08 | 0/DD99DFA8
| 2022-11-09 09:52:11.4719+08 | | 192.168.86.133 | 5432 | user=repl password=******** channel_binding=disable dbname=replication host=192.168.86.133 port=5432 ap
plication_name=slave fallback_application_name=walreceiver sslmode=disable sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_
session_attrs=any
(1 行记录)
至此异步流复制切换同步流复制完成,可以使用客户端连接进行验证测试。
日志级别wal_level
:该参数决定了有多少信息写入 WAL 日志
默认值replica
,该模式支持流复制与归档,同时支持备库的只读查询;
minimal
:对实例 crash 恢复所需要的进行记录,其余不记录日志,该模式记录的日志信息不足以支撑 WAL 的流复制与归档;
logic
:在 replica 的基础上增加一些信息以支持逻辑解码,该模式会增大 WAL 日志,尤其是大量 update、delete 的库;
同步模式synchronous_commit
:该参数决定数据同步的模式
off
:对于本机的 WAL 日志不需要写入到磁盘就可以提交,是一种异步模式,存在数据丢失的风险;
local
:不管有没有从库,只需要保证本机的 WAL 日志写入到磁盘就可以提交;
remote_write
:等待主库的日志写入到磁盘,同时日志传送到从库的缓存当中才能提交,生产环境下一般选择该模式;
on
:若不存在从库,则需要本机 WAL 写入磁盘后才能提交;若存在同步从库,则需要等待远程从库的 WAL 也写入到磁盘后才能提交;
remote_apply
:PG 高版本的功能,需要从库将更改写入磁盘并回放日志成功,用于负载均衡、读写分离等;
从机复制列表synchronous_standby_names
:该参数用于在主机上配置从机的复制列表
synchronous_standby_names=‘s1’
代表 s1 备机返回就可以提交(s1 为备机名);
synchronous_standby_names=’*’
代表匹配任意主机,也就是任意主机返回就可以提交;
max_wal_senders
:指定 WAL 日志发送进程的最大并发连接数,设置为 0 表示禁用 replication;
checkpoint_timeout
:自动 WAL 检查点之间的最长时间,合理值为 30s 到 1day 之间,默认值 5min。增加这个参数的值会增加崩溃恢复所需的时间。
checkpoint_completion_target
:指定检查点完成的目标,该值在 0 - 1 之间。假如我的 checkpoint_timeout 设置是 30min,而 WAL 日志生成了10G,那么设置成 0.5 就允许在 15min 内完成 checkpoint,调大这个值就可以降低c heckpoint 对性能的影响,但是万一数据库出现故障,那么这个值设置越大数据就越危险。
max_wal_size
:在自动检查点之间允许 WAL 日志的最大容量,默认为 1 GB,增加这个参数的值会增加崩溃恢复所需的时间。
在 PostgreSQL 9.1 版本之前,主从复制以 WAL 日志为基本单位,主库写完一个 WAL 日志后才传送到备库,这导致主备数据库之间的延迟很大。
PostgreSQL 9.1 引入了主备流复制,传输的单位时 WAL 日志的 record,备库不断从主库同步相应的数据。
PostgreSQL 的流复制实际上就是通过 WAL 日志进行数据同步的过程。WAL 全称 Write Ahead Log,即预写式日志。
WAL 日志十分重要,其核心思想就是:先写入日志文件,再写入数据。
当数据库中的数据发生变更时,主要存在下列几个重要的节点:
change 发生时:数据库首先将变更的内容计入 wal buffer,再将变更后的数据写入 data buffer;
commit 发生时:数据库将 wal buffer 中的数据刷新到磁盘;
checkpoint 发生时:数据库将所有的 data buffer 刷新到磁盘;
PostgreSQL 主从流复制的核心主要包括三个进程:
主从数据库启动后,备库启动 walreceiver 进程,向主库发送请求连接;
主库接收到请求后,启动 walsender 进程,与 walreceiver 建立 TCP 连接;
从库发送最新的 WAL LSN 给主库(LSN 可以理解为日志的偏移量);
主库进行 LSN 对比,同时定期向从库发送心跳信息来确认备库的可用性,并将没有传递的 WAL 日志发送;
从库调用函数将 WAL 写入缓存,然后将 WAL 刷新到磁盘;
docker swarm 集群的搭建过程参照:docker swarm 集群搭建
编写 docker compose 模板文件,对服务进行配置。本配置启动一主一从两个数据库,直接使用时序库官方提供的 timescaledb 镜像
version: "3"
services:
# postgres-1 服务
postgres-1:
image: timescale/timescaledb:latest-pg14
networks:
- my-multi-host-network
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=961231zqf
volumes:
- /root/postgresql/data:/var/lib/postgresql/data
ports:
- 5432:5432
deploy:
placement:
constraints:
- node.hostname == node01
# postgres-2 服务
postgres-2:
image: timescale/timescaledb:latest-pg14
networks:
- my-multi-host-network
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=961231zqf
volumes:
- /root/postgresql/data:/var/lib/postgresql/data
ports:
- 5433:5432
deploy:
placement:
constraints:
- node.hostname == node02
# 网络配置
networks:
my-multi-host-network:
driver: overlay
分别在 node 1 节点与 node 2 节点新建映射卷文件夹,映射路径需要与配置文件中路径相对应,同时在两个节点新建名为 postgres 的用户
mkdir -p /root/postgres/data
useradd postgres
在主节点 master 按照上述 compose 文件启动服务
docker stack deploy -c docker_postgres.yml postgres
使用下列命令可以查看服务的运行情况
docker service ls
在主数据库节点 node 1 进行配置,使用下列指令查询当前节点正在运行的容器
docker ps
以 postgres 用户进入 timescale/timescaledb:latest-pg14 容器,其中e052dfa54dbf
为容器的 CONTAINER ID
docker exec -it -u postgres e052dfa54dbf /bin/bash
进入/var/lib/postgresql/data/
,修改配置文件postgresql.conf
cd /var/lib/postgresql/data/
vi postgresql.conf
主要修改wal_level
属性,取消对应行前面的注释
wal_level = replica # minimal, replica, or logical
# (change requires restart)
进入/var/lib/postgresql/data/
,修改配置文件pg_hba.conf
cd /var/lib/postgresql/data/
vi postgresql.conf
在文件末尾添加如下配置
host replication repl 0.0.0.0/0 md5
登录数据库,创建用于复制的账号,用户名与密码均为 repl
bash-5.1$ psql
psql (14.1)
Type "help" for help.
postgres=# create role repl login replication encrypted password 'repl';
CREATE ROLE
postgres=# exit
在容器内重新启动主数据库
pg_ctl restart
重新查看 node 1 的服务,查看数据库是否启动成功,若启动成功则主库配置完毕
在从数据库节点 node 2 进行配置,使用下列指令查询当前节点正在运行的容器
docker ps
以 postgres 用户进入容器
docker exec -it -u postgres d853cdb73a76 /bin/bash
进入/var//lib/postgresql/
,清空 data 文件夹中的所有数据
cd /var/lib/postgresql/
rm -rf data/*
利用pg_basebackup
指令从主数据库将数据复制到从库,使用 repl 账号,密码为 repl
pg_basebackup -h 192.168.86.131 -p 5432 -U repl -R -F p -P -D data
执行完成后,等待容器自动重启,重启时将会退出容器。退出容器后查看 node 2 节点运行的容器状态,此时容器 ID 将会变换,若容器正常运行则主从异步流复制配置完毕
使用 navicat 连接两个数据库,在主库中使用下列语句查询主从配置信息
select * from pg_stat_replication;
在主库中执行相应的增删改语句,查看从库的复制情况,从库为只读库
CREATE TABLE test(id INT);
DROP TABLE test;
在主库节点 node 1 查询当前数据库的主从复制状态,此时sync_state
字段值为async
select usename, application_name, client_addr, state, sync_state from pg_stat_replication;
使用 postgres 用户进入主库节点 node 1 的 pg 库容器内部进行配置
docker ps
docker exec -it -u postgres 01e4813649de /bin/bash
修改配置文件postgresql.conf
cd /var/lib/postgresql/data/
vi postgresql.conf
配置属性synchronous_standby_names
synchronous_standby_names = 'slave' # standby servers that provide sync rep
# method to choose sync standbys, number of sync standbys,
# and comma-separated list of application_name
# from standby(s); '*' = all
配置完成后重新启动主数据库并查看容器运行情况,主库配置完成
使用 navicat 等工具连接从库,使用下列语句查询复制信息
select * from pg_stat_wal_receiver;
记录查询结果中connifo
字段值,并在原始值字段前添加application_name=slave
,然后执行系统变量的更新(application_name
属性的值为之前设置的synchronous_standby_names
属性值)
alter system set primary_conninfo = 'application_name=slave user=repl password=repl channel_binding=prefer dbname=replication host=192.168.86.131 port=5432 fallback_application_name=walreceiver sslmode=prefer sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres target_session_attrs=any';
使用 postgres 用户进入从库容器内部,重新启动数据库
docker ps
docker exec -it -u postgres b4bff118dae5 /bin/bash
pg_ctl restart
重新查询从库节点 node 2 容器运行状态,若正常运行则从库配置完毕
在主库中重新查询数据库复制信息,此时sync_state
字段值变为sync
,配置成功
select usename, application_name, client_addr, state, sync_state from pg_stat_replication;