postgres主从复制搭建教程
# 1、引言
PostgreSQL 的主从复制(Streaming Replication)是一种数据同步机制,它通过将主服务器(Primary)的数据实时复制到一个或多个从服务器(Standby)来实现高可用性、负载均衡和数据冗余。以下是主从复制的主要作用:
1. 高可用性(High Availability)
- 故障切换(Failover):当主服务器发生故障时,可以快速将从服务器提升为主服务器,确保服务不中断。
- 减少停机时间:通过自动或手动故障切换,减少因硬件故障、网络问题或维护导致的停机时间。
2. 数据冗余与灾难恢复
- 数据备份:从服务器可以作为主服务器的实时备份,防止数据丢失。
- 灾难恢复:在主服务器发生灾难性故障(如硬盘损坏、数据中心故障)时,可以从从服务器恢复数据。
3. 负载均衡
- 读操作分流:从服务器可以处理只读查询(如报表生成、数据分析),减轻主服务器的负载。
- 提高性能:通过将读操作分散到多个从服务器,提高系统的整体性能。
4. 数据一致性
- 实时同步:主从复制通过流式传输 WAL(Write-Ahead Logging)日志,确保从服务器的数据与主服务器保持实时一致。
- 事务一致性:从服务器的数据是主服务器数据的精确副本,确保事务的一致性。
5. 测试与开发
- 测试环境:从服务器可以作为测试环境,用于测试新功能或应用程序,而不会影响主服务器的生产数据。
- 数据分析:从服务器可以用于运行复杂的查询和分析任务,而不会影响主服务器的性能。
6. 地理分布
- 跨地域复制:可以将从服务器部署在不同的地理位置,实现数据的异地备份和灾难恢复。
- 本地访问:通过将数据复制到离用户更近的从服务器,减少访问延迟,提高用户体验。
7. 零停机升级
- 滚动升级:在升级 PostgreSQL 版本时,可以先升级从服务器,然后将其提升为主服务器,实现零停机升级。
8. 监控与审计
- 监控:通过监控主从复制的状态(如延迟、连接状态),可以及时发现和解决问题。
- 审计:从服务器可以用于审计和日志分析,而不会影响主服务器的性能。
主从复制的适用场景
- 高可用性要求高的系统:如金融、电商、医疗等关键业务系统。
- 读多写少的系统:如内容管理系统、新闻网站等。
- 数据备份与灾难恢复:需要实时备份和快速恢复的系统。
- 分布式系统:需要将数据复制到多个地理位置的系统。
主从复制的局限性
- 写操作无法分流:所有写操作必须在主服务器上执行,从服务器只能处理读操作。
- 复制延迟:在高负载或网络延迟较大的情况下,从服务器的数据可能会有延迟。
- 配置复杂性:主从复制的配置和维护需要一定的技术能力。
通过主从复制,可以显著提高系统的可用性、性能和可靠性。如果你有更多关于主从复制的具体问题或需要进一步的帮助,请告诉我!
# 2、创建目录结构
mkdir -p master/data slave/data
chmod -R 700 master/data slave/data
1
2
2
# 3、创建配置文件
docker-compose.yml
version: '3.8'
services:
pg_master:
image: postgres:16.4
container_name: pg_master
hostname: pg_master
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres123
POSTGRES_DB: testdb
volumes:
- ./master/data:/var/lib/postgresql/data
- ./master/init.sh:/docker-entrypoint-initdb.d/init.sh
ports:
- "5432:5432"
command:
- "postgres"
- "-c"
- "wal_level=logical"
- "-c"
- "max_wal_senders=10"
- "-c"
- "max_replication_slots=10"
- "-c"
- "hot_standby=on"
networks:
pgnet:
ipv4_address: 172.20.0.2
pg_slave:
image: postgres:16.4
container_name: pg_slave
hostname: pg_slave
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres123
POSTGRES_DB: testdb
volumes:
- ./slave/data:/var/lib/postgresql/data
ports:
- "5433:5432"
command:
- "postgres"
- "-c"
- "hot_standby=on"
networks:
pgnet:
ipv4_address: 172.20.0.3
networks:
pgnet:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
init.sh
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'repl123';
EOSQL
cat >> "/var/lib/postgresql/data/pg_hba.conf" <<EOL
host replication replicator 0.0.0.0/0 md5
host all all 0.0.0.0/0 md5
EOL
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
执行:chmod +x master/init.sh
# 4、 启动服务
启动主库
docker-compose up -d pg_master
1
等待主库完全启动后,创建初始备份
docker run --rm -it --network pg16_01_pgnet \
-v $(pwd)/slave/data:/backup postgres:16.4 \
pg_basebackup -h 172.20.0.2 -p 5432 -U replicator -D /backup -Fp -Xs -P -R -C -S replica_1 --password
1
2
3
2
3
输入密码:repl123
检查从库配置文件
cat slave/data/postgresql.auto.conf
1
确保文件包含以下内容:
primary_conninfo = 'host=172.20.0.2 port=5432 user=replicator password=repl123'
1
启动从库:
docker-compose up -d pg_slave
1
验证复制状态
docker exec -it pg_master psql -U postgres -d testdb -c "SELECT * FROM pg_stat_replication;"
1
# 5、验证操作
在主库创建测试表并插入数据
docker exec -it pg_master psql -U postgres -d testdb -c "
CREATE TABLE test_repl (id SERIAL PRIMARY KEY, name TEXT);
INSERT INTO test_repl (name) VALUES ('test1'), ('test2');
"
1
2
3
4
2
3
4
在从库查询数据验证复制是否成功:
docker exec -it pg_slave psql -U postgres -d testdb -c "SELECT * FROM test_repl;"
1
检查复制延迟:
docker exec -it pg_master psql -U postgres -d testdb -c "
SELECT client_addr,
state,
sent_lsn,
write_lsn,
flush_lsn,
replay_lsn,
(extract(epoch from write_lag))::int as write_lag_seconds,
(extract(epoch from flush_lag))::int as flush_lag_seconds,
(extract(epoch from replay_lag))::int as replay_lag_seconds
FROM pg_stat_replication;
"
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
注:重要提醒:
- 从库是只读的,不能直接在从库上写入数据
- 如果主库宕机,需要手动将从库提升为主库
- 建议定期监控复制状态和延迟
# 6、手动将从库提升到主库
1 首先确认主库确实无法恢复,然后执行以下步骤将从库提升为主库:
# 连接到从库执行以下命令
docker exec -it pg_slave bash
# 在从库上创建触发文件来促使从库退出复制模式
pg_ctl promote -D /var/lib/postgresql/data
1
2
3
4
5
2
3
4
5
2 验证从库是否已经退出恢复模式
docker exec -it pg_slave psql -U postgres -d testdb -c "SELECT pg_is_in_recovery();"
1
如果返回 false,说明从库已经成功提升为主库。
3 验证数据是否可写
docker exec -it pg_slave psql -U postgres -d testdb -c "
INSERT INTO test_repl (name) VALUES ('after_promote');
SELECT * FROM test_repl;
"
1
2
3
4
2
3
4
4 修改应用程序的连接配置,将数据库连接指向新的主库(原从库)。
5 当原主库恢复后,如果要将其作为新的从库,需要执行以下步骤:
# 停止原主库
docker-compose stop pg_master
# 清空原主库数据
rm -rf master/data/*
# 对新主库(原从库)执行基础备份
docker run --rm -it --network postgres-master-slave_pgnet \
-v $(pwd)/master/data:/backup \
postgres:16 \
pg_basebackup -h 172.20.0.3 -p 5432 -U replicator \
-D /backup -Fp -Xs -P -R \
--password
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
6 修改原主库的配置为从库配置,然后启动:
docker-compose up -d pg_master
1
重要注意事项:
- 提升操作是不可逆的,一旦从库被提升为主库,就不能再恢复为从库
- 提升前应确保从库已经接收到了主库的所有数据
- 提升后需要重新配置复制关系
- 建议在提升前备份重要数据
- 最好有预先准备好的故障转移流程
要自动化这个过程,可以考虑使用以下工具:
- Patroni:自动故障转移和集群管理
- repmgr:PostgreSQL复制管理器
- Stolon:PostgreSQL高可用集群管理器
上次更新: 2024/12/26, 16:18:59