postgres高可用(热备-监控-修复)

1. 简介

官方文档关于postgres的HA有多种方式,笔者通过比较之后决定使用流复制(9.x版本以后引入),主要原因是低延迟(默认异步)。为了避免很多处理环境的很多问题,本文使用docker部署,只挂载出数据盘。

2. 热备(流复制

流复制允许一台后备服务器比使用基于文件的日志传送更能保持为最新的状态。 后备服务器连接到主服务器, 主服务器则在 WAL 记录产生时即将它们以流式传送给后备服务器而不必等到 WAL 文件被填充。

  1. 主节点(171):

    1.1 创建容器

    docker run --name postgresPrimary -p 5432:5432 -v <data_path>:/var/lib/postgresql/data -e POSTGRES_PASSWORD=<passwd> -d postgres:9.5.6-alpine
    

    1.2 进入容器,创建一个数据库用户供主从同步使用

    # 进入容器
    docker exec -it postgresPrimary  bash
    # 进入数据库 
    bash-4.3# psql -U postgres
    # 创建用户
    postgres=# CREATE ROLE replica login replication encrypted password 'replica'
    

    1.3 修改<data_path>/pg_hba.conf,允许replica用户来同步

    host     all             all          192.168.1.172/32          trust   #允许172连接到主服务器
    host   replication      replica       192.168.1.172/32          md5   #允许172使用replica用户来复制
    

    1.4 修改<data_path>/postgresql.conf

    listen_addresses = '*'   # 监听所有IP
    archive_mode = on  # 允许归档
    archive_command = 'cp %p <archive_path>/%f'  # 用该命令来归档logfile segment
    wal_level = hot_standby 
    max_wal_senders = 32 # 这个设置了可以最多有几个流复制连接,差不多有几个从,就设置几个wal_keep_segments = 256 # 设置流复制保留的最多的xlog数目
    wal_sender_timeout = 60s # 设置流复制主机发送数据的超时时间
    max_connections = 100 # 这个设置要注意下,从库的max_connections必须要大于主库的
    

    1.5 重启postgres

    docker restart postgresPrimary
    
  2. 备节点(172)

    2.1 启动一个临时容器用于拷贝主节点数据

    docker run -it -rm -v <data_path>:/var/lib/temp -e POSTGRES_PASSWORD=<passwd> postgres:9.5.6-alpine bash
    # 拷贝主节点数据
    bash-4.3# cd /var/lib/temp
    bash-4.3# pg_basebackup -h 192.168.1.171 -U replica -D . -X stream -P
    bash-4.3# exit
    

    2.2 配置<data_path>/recovery.conf

    standby_mode = on   # 说明该节点是从服务器
    primary_conninfo = 'host=192.168.1.171 port=5432 user=replica password=replica'  # 主服务器的信息以及连接的用户
    recovery_target_timeline = 'latest'  # 同步目标是到最新
    

    2.3 配置postgresql.conf

    wal_level = hot_standby
    max_connections = 1000 # 一般查多于写的应用从库的最大连接数要比较大
    hot_standby = on # 说明这台机器不仅仅是用于数据归档,也用于数据查询
    max_standby_streaming_delay = 30s # 数据流备份的最大延迟时间
    wal_receiver_status_interval = 10s # 多久向主报告一次从的状态,当然从每次数据复制都会向主报告状态,这里只是设置最长的间隔时间
    hot_standby_feedback = on # 如果有错误的数据复制,是否向主进行反馈
    

    2.4 启动postgres

    docker run --name postgresSecondary -p 5432:5432 -v <data_path>:/var/lib/postgresql/data -e POSTGRES_PASSWORD=<passwd> -d postgres:9.5.6-alpine
    
  3. 验证部署是否成功

    连接主节点数据库,查询是否已经连通:

    postgres=# select client_addr,sync_state from pg_stat_replication;
     client_addr   | sync_state 
    ---------------+------------
     192.168.1.172 | async
     (1 rows)
    
3. 监控

postgres有自带的一些方法可以监控数据sync的情况,主要有主节点的pg_stat_replication视图,从节点的pg_is_in_recovery()、pg_last_xact_replay_timestamp()、pg_last_xlog_replay_location()等。

  1. 主节点
    1.1 连接主节点,查看pg_stat_replication 中的状态

    postgres=# select * from pg_stat_replication;
    

    1.2 在master判断recovery的滞后程度,以字节为单位

    postgres=# select pg_xlog_location_diff(sent_location, replay_location) from pg_stat_replication;
      pg_xlog_location_diff 
    -----------------------
                   124
    postgres=# select pg_xlog_location_diff(sent_location, replay_location) from pg_stat_replication;
      pg_xlog_location_diff 
    -----------------------
                   120
    
  2. 备节点

    1.1 判断recovery是否处于工作状态,当Streaming Replication在复制的时候,replay_timestamp和pg_last_xlog_replay_location会一直增长。

    postgres=# select pg_last_xact_replay_timestamp();
     pg_last_xact_replay_timestamp 
    -------------------------------
     2019-01-31 04:23:10.893194+00
    (1 row)
    
    postgres=# select pg_last_xact_replay_timestamp();
     pg_last_xact_replay_timestamp 
    -------------------------------
     2019-01-31 04:23:18.393878+00
    (1 row)
    postgres=# select pg_last_xlog_replay_location();
     pg_last_xlog_replay_location 
    ------------------------------
     5/7C6F6850
    (1 row)
    
    postgres=# select pg_last_xlog_replay_location();
     pg_last_xlog_replay_location 
    ------------------------------
     5/7C6FA258
    (1 row)
    

    2.2 查看recovery的延时情况

     postgres=# SELECT CASE WHEN pg_last_xlog_receive_location() = pg_last_xlog_replay_location() THEN 0 ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp()) END AS log_delay;
    
    # 如果receive和replay是同一个位置,延时为0;否则当前时间减去最后一个事务的时间为延时
     log_delay 
    -----------
          0
    (1 row)
    
4. 主从不一致预防与修复

主从不一致基本上都是由于在主库产生了大量xlog,由于postgreSQL在执行事务时,在提交时才发送到备库。由于该事务需要执行的时间过长,超过了checkpoint的默认间隔,所以导致有的xlog还未发送到备库却被remove掉了。

  1. 一般报错

    could not receive data from WAL stream:FATAL:  requested WAL segment 0000000*** has already been removed
    
  2. 预防

    2.1 调整wal_keep_segments的值(无法根治)

    将GUC参数wal_keep_segments设大一些,比如设置为2000,而每个segment默认值为16MB,就相当于有32000MB,即大概30多个GB的空间作为缓存空间。

    2.2 启用归档

    归档,就是将未发送到备库的xlog备份到某个目录下,待重启数据库时再将其恢复到备库中去。

    本文做热备的时候就已经启动了归档。

    2.3 启用replication slot(pg9.4以后才有, 根本方法)

    这个不会造成xlog的丢失。也就是说,在xlog被拷贝之前,不会删除。

    1. 在主库postgresql.conf中添加 max_replication_slots = 2000
    2. 在拷贝到备库之前,主库要创建一个slot
      postgres=# SELECT * FROM pg_create_physical_replication_slot('node_a_slot');
        slot_name  | xlog_position
      -------------+---------------
       node_a_slot |
      
      postgres=# SELECT * FROM pg_replication_slots;
        slot_name  | slot_type | datoid | database | active | xmin | restart_lsn
      -------------+-----------+--------+----------+--------+------+-------------
       node_a_slot | physical  |        |          | f      |      |
      (1 row)
      
    3. 在备库的recovery.conf文件中添加一行: primary_slot_name = 'node_a_slot'
  3. 修复
    3.1 如果有归档,可以用主节点的归档来恢复备节点

    scp <archive_path>/000000*** root@192.168.1.172:<data_path>/pg_xlog/ 
    

    3.2 如果没有归档,只能重建备节点(按照上面的热备备节点操作)

参考:
PostgreSQL主从流复制部署
PostgreSQL 9.3 Streaming Replication 状态监控
PostgreSQL:“ FATAL: requested WAL segment00800002A0 has already been removed”

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值