Skip to content

PostgreSQL 同步复制与异步复制

核心概念

1. 异步复制

异步复制是PostgreSQL默认的复制模式,主库在将WAL日志写入本地磁盘后立即向客户端返回成功,不需要等待从库确认接收或应用WAL日志。

异步复制的特点

  • 主库性能高,写入延迟低
  • 存在数据丢失风险:如果主库崩溃,尚未同步到从库的WAL日志会丢失
  • 从库可能存在复制延迟
  • 配置简单,无需额外设置

2. 同步复制

同步复制要求主库在将WAL日志写入本地磁盘后,必须等待至少一个从库确认已接收并写入磁盘,才向客户端返回成功。

同步复制的特点

  • 数据安全性高,无数据丢失风险
  • 主库写入延迟增加,性能可能下降
  • 从库复制延迟极小
  • 需要额外配置,指定同步从库

3. 关键区别

特性异步复制同步复制
数据安全性较低(可能丢失数据)极高(无数据丢失)
主库性能高(写入延迟低)较低(写入延迟高)
从库一致性最终一致强一致
配置复杂度简单复杂
适用场景对性能要求高,可接受少量数据丢失对数据安全性要求极高,可接受一定性能损失

异步复制配置

1. 基础配置

异步复制是PostgreSQL的默认复制模式,无需特殊配置,只需按照物理复制的基础配置即可实现。

bash
# 主库配置文件postgresql.conf中的默认设置
# 无需额外配置,异步复制默认启用

2. 验证异步复制状态

sql
-- 在主库上查看复制状态
SELECT 
    application_name,
    state,
    sync_state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn
FROM pg_stat_replication;

-- sync_state字段为async表示异步复制

同步复制配置

1. 配置步骤

1.1 主库配置

bash
# 修改主库postgresql.conf
cat >> /var/lib/postgresql/15/main/postgresql.conf << EOF
# 启用同步复制
# 设置同步从库名称,可以是具体的从库名称或表达式
# FIRST 1表示至少1个从库确认,ANY 2表示任意2个从库确认
synchronous_standby_names = 'FIRST 1 ("standby1", "standby2")'
EOF

# 重启主库使配置生效
pg_ctl restart -D /var/lib/postgresql/15/main

1.2 从库配置

bash
# 在recovery.signal或postgresql.auto.conf中设置从库应用名称
# 确保应用名称与主库的synchronous_standby_names配置匹配
cat >> /var/lib/postgresql/15/main/postgresql.auto.conf << EOF
# 设置从库应用名称
primary_conninfo = 'host=主库IP port=5432 user=replication_user password=replication_pass application_name=standby1'
EOF

# 重启从库使配置生效
pg_ctl restart -D /var/lib/postgresql/15/main

2. 验证同步复制状态

sql
-- 在主库上查看复制状态
SELECT 
    application_name,
    state,
    sync_state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn
FROM pg_stat_replication;

-- sync_state字段为sync表示同步复制
-- sync_priority字段显示同步优先级
-- sync_state为potential表示备选同步从库

高级配置选项

1. 同步复制模式

PostgreSQL支持多种同步复制模式,通过synchronous_standby_names参数配置:

sql
-- 模式1:指定具体从库,至少1个确认
ALTER SYSTEM SET synchronous_standby_names = '"standby1", "standby2"';

-- 模式2:FIRST N表示前N个从库确认
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 2 ("standby1", "standby2", "standby3")';

-- 模式3:ANY N表示任意N个从库确认
ALTER SYSTEM SET synchronous_standby_names = 'ANY 2 ("standby1", "standby2", "standby3")';

-- 模式4:使用通配符匹配从库名称
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 1 ("standby*")';

-- 应用配置
SELECT pg_reload_conf();

2. 同步提交级别

sql
-- 设置同步提交级别
-- on:完全同步,等待WAL写入从库磁盘
-- remote_write:等待WAL写入从库操作系统缓冲区
-- off:异步复制
ALTER SYSTEM SET synchronous_commit = 'on';

-- 应用配置
SELECT pg_reload_conf();

性能优化

1. 异步复制优化

bash
# 主库配置优化
cat >> /var/lib/postgresql/15/main/postgresql.conf << EOF
# 异步复制性能优化
wal_compression = on
checkpoint_timeout = 30min
max_wal_size = 4GB
checkpoint_completion_target = 0.9
EOF

# 从库配置优化
cat >> /var/lib/postgresql/15/main/postgresql.conf << EOF
# 异步复制从库优化
hot_standby = on
hot_standby_feedback = on
max_standby_streaming_delay = 30s
EOF

2. 同步复制优化

bash
# 同步复制性能优化
cat >> /var/lib/postgresql/15/main/postgresql.conf << EOF
# 减少同步复制延迟
wal_writer_delay = 20ms
commit_delay = 10
commit_siblings = 5

# 优化WAL发送
max_wal_senders = 10
wal_keep_size = 2GB
EOF

3. 网络优化

  • 使用专用网络连接主从库
  • 增加网络带宽
  • 优化网络路由,减少网络延迟
  • 考虑使用压缩传输(适用于远距离复制)

监控与管理

1. 复制状态监控

sql
-- 监控复制状态
SELECT 
    application_name,
    state,
    sync_state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn,
    (sent_lsn - replay_lsn) AS replay_lag
FROM pg_stat_replication;

-- 监控同步复制等待时间
SELECT 
    pid,
    state,
    wait_event,
    wait_event_type,
    query
FROM pg_stat_activity
WHERE wait_event_type = 'Replication';

2. 复制延迟监控

sql
-- 在从库上查看复制延迟
SELECT 
    now() - pg_last_xact_replay_timestamp() AS replication_delay;

-- 监控WAL生成和应用速率
SELECT 
    pg_current_wal_lsn(),
    pg_last_wal_receive_lsn(),
    pg_last_wal_replay_lsn();

3. 同步复制故障处理

3.1 同步从库不可用

sql
-- 当同步从库不可用时,主库会等待超时
-- 可以临时切换到异步复制模式
ALTER SYSTEM SET synchronous_standby_names = '';
SELECT pg_reload_conf();

-- 当从库恢复后,重新启用同步复制
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 1 ("standby1", "standby2")';
SELECT pg_reload_conf();

3.2 同步复制延迟过高

bash
# 1. 检查网络状态
ping 主库IP
netstat -s

# 2. 检查从库负载
top
psql -h 从库IP -U postgres -c "SELECT * FROM pg_stat_activity;"

# 3. 优化从库配置
# 增加从库的CPU和内存资源
# 优化从库的WAL应用配置

最佳实践

1. 复制模式选择建议

业务场景推荐复制模式配置建议
电商交易系统同步复制FIRST 1 ("standby1", "standby2")
内容管理系统异步复制默认配置
金融核心系统同步复制ANY 2 ("standby1", "standby2", "standby3")
日志分析系统异步复制默认配置,增加wal_keep_size
混合业务系统半同步复制(后续文档介绍)-

2. 配置最佳实践

  • 使用多个从库:配置2-3个从库,提高系统可用性
  • 合理设置同步条件:根据业务需求选择FIRST或ANY模式,以及合适的从库数量
  • 配置复制槽:防止WAL日志丢失,尤其是异步复制
  • 监控复制状态:定期检查复制状态和延迟,设置告警阈值
  • 测试故障切换:定期测试故障切换流程,确保在主库故障时能够快速恢复

3. 运维最佳实践

  • 文档化配置:详细记录复制配置和管理流程
  • 定期备份:无论使用哪种复制模式,都要定期进行数据库备份
  • 培训团队:确保运维团队熟悉复制管理和故障处理
  • 版本兼容性:确保主从库版本一致,或在支持的版本范围内

常见问题(FAQ)

Q1:同步复制和异步复制如何选择?

A1:选择复制模式主要取决于业务对数据安全性和性能的要求:

  • 如果业务对数据安全性要求极高(如金融、交易系统),应选择同步复制
  • 如果业务对性能要求较高,可接受少量数据丢失(如内容管理、日志系统),应选择异步复制
  • 对于混合业务场景,可以考虑使用半同步复制(后续文档介绍)

Q2:同步复制会影响主库性能吗?

A2:是的,同步复制会增加主库的写入延迟,主要影响因素包括:

  • 网络延迟:主从库之间的网络延迟越大,同步复制的性能影响越大
  • 从库数量:配置的同步从库数量越多,主库等待时间越长
  • 从库性能:从库的WAL接收和应用性能会影响主库等待时间

Q3:如何降低同步复制对主库性能的影响?

A3:可以采取以下措施降低同步复制的性能影响:

  • 使用高性能网络连接主从库
  • 优化从库配置,提高WAL接收和应用速度
  • 合理设置同步条件,减少同步从库数量
  • 考虑使用remote_write同步级别,而非完全同步
  • 对非关键业务表使用异步复制,关键业务表使用同步复制(通过逻辑复制实现)

Q4:异步复制的数据丢失风险有多大?

A4:异步复制的数据丢失风险取决于:

  • 主库的WAL生成速率
  • 从库的复制延迟
  • 主库的故障类型(如突然断电、硬件故障)

通过配置合适的wal_keep_size和使用复制槽,可以降低数据丢失风险,但无法完全消除。

Q5:如何在同步复制和异步复制之间切换?

A5:可以通过修改主库的synchronous_standby_names参数在两种模式之间切换:

sql
-- 切换到异步复制
ALTER SYSTEM SET synchronous_standby_names = '';
SELECT pg_reload_conf();

-- 切换到同步复制
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 1 ("standby1", "standby2")';
SELECT pg_reload_conf();

Q6:同步复制中的从库优先级如何设置?

A6:同步从库的优先级由synchronous_standby_names参数中从库的顺序决定,排在前面的从库优先被选为同步从库。

sql
-- standby1优先级高于standby2
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 1 ("standby1", "standby2")';
SELECT pg_reload_conf();

Q7:如何监控同步复制的性能?

A7:可以通过以下方式监控同步复制的性能:

sql
-- 监控主库写入等待时间
SELECT 
    pid,
    state,
    wait_event,
    wait_event_type,
    query,
    now() - query_start AS query_duration
FROM pg_stat_activity
WHERE wait_event_type = 'Replication';

-- 监控复制延迟
SELECT 
    application_name,
    sync_state,
    (sent_lsn - replay_lsn) AS replay_lag
FROM pg_stat_replication;

Q8:同步复制是否支持多个从库?

A8:是的,同步复制支持配置多个从库,可以通过synchronous_standby_names参数指定:

sql
-- 等待任意2个从库确认
ALTER SYSTEM SET synchronous_standby_names = 'ANY 2 ("standby1", "standby2", "standby3")';

-- 等待前2个从库确认
ALTER SYSTEM SET synchronous_standby_names = 'FIRST 2 ("standby1", "standby2", "standby3")';

同步复制与异步复制的应用场景

1. 异步复制应用场景

  • 内容管理系统(CMS)
  • 日志分析系统
  • 数据仓库系统
  • 开发测试环境
  • 对性能要求高,可接受少量数据丢失的业务

2. 同步复制应用场景

  • 金融交易系统
  • 电子商务系统
  • 医疗数据系统
  • 政府政务系统
  • 对数据安全性要求极高,可接受一定性能损失的业务

通过合理选择和配置同步复制与异步复制,可以在数据安全性和性能之间取得平衡,满足不同业务场景的需求。