PostgreSQL10 物理流复制实战:构建高可用数据库架构!

[复制链接]
发表于 2025-10-23 18:49:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
配景

PostgreSQL 10 在高可用架构中提供了物理复制,也称为流复制(Streaming Replication),用于实实际例级别的数据同步。PostgreSQL 复制机制告急包罗物理复制和逻辑复制:物理复制依靠 WAL 日志日志举行物理块级别的同步,可以大概包管备库与主库的数据完全同等,实用于高可用、读写分离、灾备切换等场景。相比之下,逻辑复制则更机动,支持表级数据同步。在高并发业务中,物理复制因其高效、低耽误的特性,广泛用于保障数据库的高可用性。
流复制先容

什么是流复制?
基于流复制协议的WAL日志日志从主节点到备节点实时复制传输与复用;
为了实现数据库的容灾备份,我们必要搭建主库和备库;
流复制是搭建主备库的一种有效方式;
两套数据库之间的数据,通过WAL日志日志,配景主动同步;
对外部的应用步调而言,可以看作是两套数据库,必要根据业务必要,表现分别毗连差别的数据库;
获取共同其他中心件使用,比方PGPOOL实现负载均很和故障主动切换。

流复制劈头

PostgreSQL自从2010年推出的9.0版本开始,支持流式物理复制,用户可以通过流式复制,构建只读备库(主备物理复制,块级别同等)。流式物理复制可以做到极低的耽误(通常在毫秒以内)。
同步流复制

2011年推出的9.1版本,支持同步复制,其时只支持一个同步流复制备节点(比方设置了3个备,只有一个是同步模式的,其他都是异步模式)。
在同步复制模式下,当用户提交变乱时,必要期待这笔变乱的WAL日志复制到同步流复制备节点,才会返回提交乐成的ACK给客户端。
同步模式下,可以确保数据的0丢失。(只要客户端收到了变乱提交乐成的ACK,这笔变乱的WAL就有两份。)
级联流复制

2012年推出的9.2版本,支持级联流复制。意思是备库还可以再连备库。
级联复制特殊适当跨机房的使用,比方主库在A机房,备库在B机房,但是B机房必要创建多个备库时,那么B机房只必要创建一个直连主库的备库,其他的备库可以通过B机房的这个备库级联产生。从而镌汰网络开销。
流式假造备库

2012年推出的9.2版本,除了支持级联复制,还支持假造备库,什么是假造备库呢?就是只有WAL,没有数据文件的备库。
通过假造备库,可以流式的吸收WAL,举行实时的流式WAL归档。进步备份或归档的实时性。
逻辑复制的底子

2014年推出的9.4版本,在WAL中增长了逻辑复制必要的底子信息,通过插件,可以实现逻辑复制。
逻辑复制可以做到对主库的部门复制,比方表级复制,而不是整个集群的块级同等复制。逻辑复制的备库不但仅是只读的,也可以实验写操纵。
WAL日志

WAL(Write-Ahead Logging,预写式日志),生存了对数据库的操纵记载,包管了PG的变乱长期性和数据完备性,同时制止了频仍的I/O对数据库性能的影响。
WAL机制的理念是,对数据文件的操纵,比方表和索引,都应该先将操纵日志写入磁盘中的WAL日志文件,而Data Buffer中的脏页耽误至checkpoint发生的时间才革新到磁盘中的数据文件。

  • 革新数据页涉及大量的随机I/O,即革新脏页需对硬盘中的多个分散的数据块举行写操纵,这里会涉及硬盘磁头的寻道操纵,非常耗时;相比之下革新WAL是把记载追加到WAL文件上,属于连续写,服从要高得多。
  • 日志先被长期化,纵然数据库发生宕机,纵然Data Buffer存在未革新到数据文件的数据页,当数据库重新启动后,那些未革新的数据页上的变动可以根据WAL日志重做,包管数据的完备性。
流复制实验过程



  • 发生DML(INSERT/UPDATE/DELETE)、DDL(表结果变动)等变动操纵提交时,数据库进程将WAL记载先写入内存的WAL Buffer中。
  • WAL Buffer中的WAL记载被革新到硬盘的WAL日志文件中。
  • 关照walsender进程。
  • walsender进程读取刚刚革新到硬盘的WAL记载。
  • walsender进程负责WAL记载发送给备库的walreceiver进程。
  • 备库walreceiver吸收到WAL记载后会关照walwriter进程,walwriter负责把吸收到的WAL记载写入硬盘的WAL日志文件。
  • 关照数据库startup进程。
  • 备库startup进程读取刚刚革新到硬盘的WAL记载。
  • 备库startup进程重播WAL日志,并把数据写入硬盘的数据文件。
颠末以上步调,实现主库与备库的数据同等性。
流复制同步级别

2016年推出的9.6版本,PG的流式复制,通过复制WAL到达同步的目标,因此同步级别也和WAL有关。通过synchronous_commit参数,可以设置变乱的同步级别。
1、remote_apply,表现本地WAL fsync(fsync:内存长期化存储),同步standby WAL 已规复。这个带来的RT最高。
2、on,表现本地WAL fsync,同步standby WAL fsync。即两份长期化的WAL。
3、remote_write, 表现本地WAL fsync,同步standby WAL 异步write完成。一份长期化,备库的WAL大概还在OS CACHE中。
4、local,表现本地WAL fsync。
5、off,表现本地WAL写到WAL buffer中即返回客户端变乱提交乐成的ACK,为异步提交(数据库CRASH大概导致变乱丢失,但不会导致数据库不同等)。
RT影响,从低到高如下:off, local, remote_write, on, remote_apply。
同步品级设定值分析包管范围(流复制过程步调包管)同步remote_apply再备库上应用WAL(更新数据)后,它将返回COMMIT相应,而且可以在备库上举行引用。由于完全包管数据同步,因此它实用于必要备库始终保持最新数据的负载分配场景。1-9同步on(默认)在备库上写入WAL之后,返回COMMIT相应。性能和可靠性之间均衡。1-6准同步remote_writeWAL已传输到备库后,返回COMMIT相应。1-5异步local写入主库WAL之后,返回COMMIT相应。1-2异步offWAL写到WAL buffer中即返回COMMIT相应,无需期待主库WAL完成写入。该设置对现有业务服从无影响,相称于异步。1异步流复制和同步流复制的区别

流复制转达日志的两种方式

  • 异步流复制
  • 同步流复制
两者的告急区别

  • 在异步流复制的环境下,变乱被提交到master之后数据才会被复制。
slave就写操纵而言,通常滞后于master一些,此耽误(delay)被称为滞后性。

  • 同步复制较高的数据同等性规则
在同步流复制的环境下,体系必须确保通过变乱写入的数据至少变乱同时在两台服务器上提交。
这意味着:slave不滞后于master,而且终端用户在两台服务器上看到的数据是同等的。
思量数据丢失

假设我们正在以异步复制方式同步数据:

  • 变乱发送到master
  • 变乱提交到master
  • 在变乱发送到slave之前,master宕机
  • slave永世都不会收到这个变乱
在异步复制的环境下,有一个窗口(滞后),在滞后窗口期间数据会存在丢失
滞后窗口的巨细因设置范例的差别而差别,它的巨细非常短(几毫秒)或非常长(几分钟、几小时、几天)。
一个告急的究竟是:数据大概丢失,一个小的滞后指挥是数据丢失的大概性较小,但使命大于零的滞后都大概导致数据丢失。
思量性能题目

通过网络发送不须要的消息的开销是相对昂贵和耗时的。
假如一个变乱接纳同步的方式复制,PostgreSQL必须确保数据到达第二个节点,如许就会导致额外的耽误题目,业务的感知会有耽误。
在很多方面,同步复制比异步复制昂贵很多,因此假如这种斲丧确实必要,应该三思而后行。(只在有特殊必要的时间使用同步复制)
流式备份压缩

2017年推出的10版本,pg_basebackup, pg_receivewal下令支持流式压缩备份WAL。
quorum based 同步流复制

2017年推出的10版本,支持quorum based的同步流复制,比方有3个备节点,你可以告诉主库,这个变乱必要3份WAL副本,那么主库必要期待至少2个备节点已将WAL同步已往的反馈,才会将变乱提交乐成的ACK返回给客户端。
quorum based同步流复制,团结raft协议,可以实现零数据丢失的高可用、高可靠架构。
内置逻辑订阅、复制

2017年推出的10版本,内置了逻辑订阅的功能。
多master

2017年推出的10版本,通过逻辑订阅的功能,可以实现多Master架构。
物理流复制

主库实验操纵


  • 备份postgresql.conf
  1. cp /data/xxx/pgsql/data/postgresql.conf /data/xxx/pgsql/data/postgresql.conf.backup
  2. chown postgresql:postgresql postgresql.conf.backup
复制代码

  • 设置postgresql.conf
  1. # - iuser数据库主备配置 -
  2. wal_level = replica
  3. fsync = on
  4. synchronous_commit = remote_write
  5. synchronous_standby_names = 'ANY 1 (*)'
  6. max_wal_senders = 10
  7. wal_keep_segments = 1024
  8. hot_standby = on
  9. # - iuser数据库主备配置 -
复制代码
设置分析
  1. max_wal_senders 设置为一个大于0的数,表示主库最多可以有多少个并发的standby
  2. wal_keep_segments 设置为一个尽量大的值,以防止主库生成WAL日志太快,日志还没有来得及传送到standby就被覆盖,但是需要考虑磁盘空间允许,一个WAL日志文件的大小通常是16M
复制代码
postgresql.conf、pg_hba.conf设置调优
  1. https://github.com/digoal/blog/blob/master/201707/20170711_01.md
复制代码

  • 备份pg_hba.conf
  1. cp /data/xxx/pgsql/data/pg_hba.conf /data/xxx/pgsql/data/pg_hba.conf.backup
  2. chown postgresql:postgresql pg_hba.conf.backup
复制代码

  • 设置pg_hba.conf
  1. # - iuser数据库主备配置 -
  2. local   replication     all                                     md5  
  3. host    replication     all             127.0.0.1/32            md5  
  4. host    replication     all             ::1/128                 md5  
  5. host    replication     all             0.0.0.0/0               md5
  6. # - iuser数据库主备配置 -
复制代码

  • 重启主库
  1. service restart postgresql
复制代码

  • 创建流复制脚色
    创建replication脚色的用户来专门负责standby毗连去获取WAL日志
  1. psql -h 127.0.0.1 -p 5432 -U postgres
  2. PGPASSWORD=xxx psql -h 127.0.0.1 -p 5432 -U postgres
  3. postgres=# set synchronous_commit = off;
  4. postgres=# create role rep login replication encrypted password '123456';
复制代码
备库实验操纵


  • 备份备库目次
    做底子备份之前从库的数据目次必要手动清空
  1. cd /data/xxx/pgsql
  2. tar -cvf pg_data_backup.tar.gz /data/xxx/pgsql/data
  3. rm -rf /data/xxx/pgsql/data/*
复制代码

  • 克制备库
  1. service stop postgresql
复制代码

  • 规复备库(备份主库数据)
  1. # 获取整库备份文件(支持自定义表空间)
  2. # 注意:密码也会被覆盖成主机密码、即主备机密码需一致
  3. ./bin/pg_basebackup -D /data/xxx/pgsql/data -Ft -Pv -U rep -h 192.168.121.23
  4. -D 表示指定数据备份的位置
  5. -F 表示备份文件格式,这里t表示是tar压缩文件格式。
  6. -Pv 表示显示备份过程。
  7. -U、-h、-p 表示数据库连接相关设置
  8. ------
  9. # 生成基础备份(如果自定义表空间没有和默认表空间data目录一起存储可使用该命令)
  10. ./bin/pg_basebackup -h 192.168.121.23 -U rep -F p -P -R -D /data/xxx/pgsql/data -l repbackup20240304
  11. -X fetch:
  12. 当使用 -X fetch 选项时,pg_basebackup 将通过获取和复制 WAL 日志文件的方式来进行备份。它会在备份完成后将 WAL 日志文件复制到备份目录中,以确保备份的完整性。
  13. 优点是备份的完整性更高,因为它会将 WAL 日志文件复制到备份目录中,以便在恢复时能够恢复到特定的时间点。
  14. 缺点是备份过程可能会稍慢,特别是在网络连接较慢或延迟较高的情况下。
  15. -X stream:
  16. 当使用 -X stream 选项时,pg_basebackup 将通过流复制的方式来进行备份。它会在备份过程中直接从主服务器获取 WAL 日志文件,并将它们应用到备份数据中。
  17. 优点是备份过程可能会更快,因为它直接从主服务器获取 WAL 日志文件,并且不需要等待 WAL 日志文件复制完成。
  18. 缺点是由于备份数据中包含 WAL 日志的一部分,因此在恢复时可能无法恢复到特定的时间点,而是恢复到备份结束时的状态。
  19. 综上所述,-X fetch 和 -X stream 的区别在于备份时获取 WAL 日志文件的方式不同,前者将 WAL 日志文件复制到备份目录中以确保备份的完整性,而后者则直接从主服务器获取 WAL 日志文件以提高备份速度。您可以根据实际需求选择适合的方式进行备份。
  20. ./bin/pg_basebackup -D /data/xxx/pgsql/data -F p -X stream -h 192.168.121.23 -p 5432 -U rep
  21. 密码:123456
  22. ./bin/pg_basebackup -D /data/xxx/pgsql/data -F p -X fetch -h 192.168.121.23 -p 5432 -U rep
复制代码
自界说表空间规复留意事项
  1. 由于使用了自定义表空间恢复备份过程失败参考:
  2. https://cloud.tencent.com/developer/ask/sof/111519647
  3. https://zhuanlan.zhihu.com/p/677427319
  4. https://baijiahao.baidu.com/s?id=1708319850223764755&wfr=spider&for=pc
  5. http://www.manongjc.com/detail/40-xpencvjhrnhytdn.html
复制代码

  • 规复备库(备库实验规复)
    a.目次解压
    数据目次/data/xxx/pgsql/data下存在以下三个备份文件
  1. # 第一个基础信息包base.tar解压(直接数据目录下执行)
  2. tar -xvf base.tar
  3. # 第二个数据目录包16385.tar解压(解压到data目录下的pg_iuser目录下)
  4. tar -xvf 16385.tar -C pg_iuser/
  5. # 第三个WAL日志包pg_wal.tar解压(解压到data目录下的pg_iuser目录下)
  6. tar -xvf pg_wal.tar -C pg_wal/
复制代码
b.设置备库规复设置文件recovery.conf
  1. cp /data/xxx/postgresql/share/recovery.conf.sample recovery.conf
  2. chown postgresql:postgresql recovery.conf
  3. # 设置recovery.conf文件内容
  4. recovery_target_timeline = 'latest'  
  5. standby_mode = on  
  6. primary_conninfo = 'host=192.168.121.23 port=5432 user=rep password=123456'
复制代码
留意:recovery_target_timeline当设置为 ‘latest’ 时,PostgreSQL 将使用最新的时间线来举行规复。这意味着在规复数据库时,将使用 WAL 日志中最新的时间线。这对于在流复制环境中举行故障切换时非常有效,由于您渴望备库可以大概尽快地切换到主库的最新时间线,以确保数据的同等性和完备性。这在举行 PITR(Point-In-Time Recovery)时特殊有效,由于您可以确保将数据库规复到最新的状态,而不是规复到之前的某个时间点。‘immediate’ 该选择只能规复到备份的时间点,无法使用备份后天生的wal。
若recovery.conf文件存在,则举行PITR操纵,根据recovery_target应用日志。
c.数据目次赋权
  1. # 备份过程中可能由于root用户操作导致目录权限被覆盖
  2. sudo chown -R postgresql:postgresql /data/xxx/pgsql/data
复制代码

  • 备份完成启动备库
  1. service start postgresql
复制代码
主从节点摆设完成。
节点状态监控监控

主库查询
  1. # 扩展展示查询
  2. \x
  3. Expanded display is on.  
  4. # 查询状态
  5. select pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn)) as sent_delay,   
  6.   pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), write_lsn)) as write_delay,   
  7.   pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn)) as flush_delay,   
  8.   pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) as replay_delay,   
  9.   *  
  10. from pg_stat_replication;
  11. # 结果查询
  12. -[ RECORD 1 ]----+------------------------------
  13. sent_delay       | 0 bytes
  14. write_delay      | 0 bytes
  15. flush_delay      | 0 bytes
  16. replay_delay     | 0 bytes
  17. pid              | 56584
  18. usesysid         | 24576
  19. usename          | rep
  20. application_name | walreceiver
  21. client_addr      | 192.168.121.24
  22. client_hostname  |
  23. client_port      | 45564
  24. backend_start    | 2024-03-05 00:29:50.486627+08
  25. backend_xmin     |
  26. state            | streaming
  27. sent_lsn         | 0/F152118
  28. write_lsn        | 0/F152118
  29. flush_lsn        | 0/F152118
  30. replay_lsn       | 0/F152118
  31. write_lag        |
  32. flush_lag        |
  33. replay_lag       |
  34. sync_priority    | 1
  35. sync_state       | quorum
复制代码
备库查询
  1. -- 查看当前WAL应用是否暂停了 (navicat可执行)
  2. iuser=# select pg_is_wal_replay_paused();
  3. pg_is_wal_replay_paused   
  4. -------------------------  
  5. f  
  6. -- 查看WAL接收到的位点  
  7. iuser=# select pg_last_wal_receive_lsn();
  8. pg_last_wal_receive_lsn   
  9. -------------------------  
  10. 0/F152A88
  11. -- 查看WAL的应用位点  
  12. iuser=# select pg_last_wal_replay_lsn();
  13. pg_last_wal_replay_lsn   
  14. ------------------------  
  15. 0/F152B30
  16. -- 查看wal receiver的统计信息  
  17. iuser=# \x  
  18. Expanded display is on.  
  19. iuser=# select * from pg_stat_get_wal_receiver();
  20. -[ RECORD 1 ]---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------  
  21. pid                   | 65235  
  22. status                | streaming  
  23. receive_start_lsn     | 0/F000000
  24. receive_start_tli     | 1  
  25. received_lsn          | 0/F152B68
  26. received_tli          | 1  
  27. last_msg_send_time    | 2024-03-05 11:41:32.810624+08  
  28. last_msg_receipt_time | 2024-03-05 11:41:33.591844+08  
  29. latest_end_lsn        | 0/F152B68
  30. latest_end_time       | 2024-03-05 11:41:02.770438+08  
  31. slot_name             |   
  32. conninfo              | user=rep password=******** dbname=replication host=192.168.121.23 port=5432 fallback_application_name=walreceiver sslmode=prefer sslcompression=1 krbsrvname=postgres target_session_attrs=any
  33. -- 注意!!!执行暂停WAL的应用(例如要做一些排错时)
  34. iuser=# select pg_wal_replay_pause();  
  35. -[ RECORD 1 ]-------+-  
  36. pg_wal_replay_pause |   
  37.   
  38. -- 查询是否暂停WAL - 结果t
  39. postgres=# select pg_is_wal_replay_paused();
  40. -[ RECORD 1 ]-----------+--  
  41. pg_is_wal_replay_paused | t  
  42. -- 注意!!!执行继续
  43. postgres=# select pg_wal_replay_resume();
  44. -[ RECORD 1 ]--------+-  
  45. pg_wal_replay_resume |   
  46.   
  47. -- 查询是否暂停WAL - 结果f
  48. postgres=# select pg_is_wal_replay_paused();
  49. -[ RECORD 1 ]-----------+--  
  50. pg_is_wal_replay_paused | f  
复制代码
注:
– 删除全部发布
SELECT pg_drop_replication_slot(slot_name) FROM pg_replication_slots;
– 删除全部订阅
SELECT pg_drop_subscription(subname) FROM pg_subscription;
留意事项

1、假如要防止日志主库删除,备库还没有吸收的WAL文件。
使用slot,大概设置富足大的wal keep。
但是这两种方法都有肯定的风险或题目,比方当备库挂了,大概备库不再使用了,而用户忘记删除对应的SLOT时,大概导致主库WAL无穷膨胀。
而wal keep则会导致主库的WAL预留富足的个数,默认一个wal文件巨细16M,占用肯定空间,比方设置wal_keep_segments=1024,那么磁盘最大存储是16G。
相干参数
  1. 主 postgresql.conf  
  2. # max_replication_slots = 10  
  3. # wal_keep_segments = 1024  #保持至少 1024 个 WAL 文件可用,以确保数据库的持续运行
  4.   
  5. 备 recovery.conf  
  6. # primary_slot_name = ''  
复制代码
2、假如不想通过以上方法防备备库必要的WAL已被删除,那么可以设置主库的归档,同时备库必要能获取到已归档的WAL文件。
相干参数
  1. 主 postgresql.conf  
  2. #archive_mode = off             # enables archiving; off, on, or always  
  3.                                 # (change requires restart)  
  4. #archive_command = ''           # command to use to archive a logfile segment  
  5.                                 # placeholders: %p = path of file to archive  
  6.                                 #               %f = file name only  
  7.                                 # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'  
  8.   
  9. 备 recovery.conf  
  10. # restore_command = ''           # e.g. 'cp /mnt/server/archivedir/%f %p'  
复制代码
3、掩护好recovery.conf文件中的暗码,由于设置的是明文。–源码中是否可以设置密文?
  1. 在 recovery.conf 配置文件中配置的密码通常是以明文形式存储的,而不是加密存储的。这是因为 recovery.conf 文件通常只能由数据库管理员或具有足够权限的用户访问,因此存储密码为明文通常被视为足够安全。
  2. 然而,对于安全性要求较高的环境,您可能希望采取额外的措施来保护密码的安全性。这可能包括:
  3. 1.使用操作系统权限限制访问:确保只有具有足够权限的用户才能访问 recovery.conf 文件。
  4. 2.定期更改密码:定期更改密码是一种通用的安全实践,可以帮助减少密码泄露的风险。
  5. 3.使用密码管理工具:某些密码管理工具允许您安全地存储和管理密码,并提供额外的安全功能,如加密存储、访问控制和审计日志等。
  6. 4.加密密码:虽然 recovery.conf 文件本身不支持加密存储密码,但您可以使用加密技术来保护密码。例如,您可以将密码存储在加密的配置文件中,并在数据库启动时使用脚本来解密密码。
复制代码
4、主备之间的带宽请富足大,否则大概导致主备耽误。
5、大数据量下磁盘空间占满题目,预估一下一个大数据量项目标数据库巨细占存储空间多少。查察数据库的巨细 :
  1. postgres=# select round(sum(pg_database_size(oid))/1024/1024.0,2)||'MB' from pg_database;
  2. ?column?
  3. ----------
  4. 288.21MB
  5. (1 row)
复制代码
查察表空间和使用的数据库
  1. CREATE ROLE
  2. iuser=# SHOW data_directory;
  3.       data_directory      
  4. ---------------------------
  5. /data/xxx/pgsql/data
  6. (1 row)
  7. iuser=# SELECT * FROM pg_tablespace;
  8.   spcname   | spcowner | spcacl | spcoptions
  9. ------------+----------+--------+------------
  10. pg_default |       10 |        |
  11. pg_global  |       10 |        |
  12. iuser        |       10 |        |
  13. (3 rows)
  14. iuser=# \db+
  15.                                                List of tablespaces
  16.     Name    |   Owner    |             Location             | Access privileges | Options |  Size  | Description
  17. ------------+------------+----------------------------------+-------------------+---------+--------+-------------
  18. iuser        | postgresql | /data/xxx/pgsql/data/pg_iuser |                   |         | 11 MB  |
  19. pg_default | postgresql |                                  |                   |         | 23 MB  |
  20. pg_global  | postgresql |                                  |                   |         | 574 kB |
复制代码
同步压测

毗连主库举行TPC-B的压测
TPC-B 测试的结果通常以每秒完成的变乱数(Transaction-per-Second, TPS)来衡量,即体系在单位时间内可以大概完成的变乱数量。这个指标越高,表现数据库体系在处置处罚变乱型工作负载时的性能越好。
可通过正常摆设的呆板对比主从摆设的呆板性能测试。

  • 创建测试数据库
  1. iuser=# create database test_db;
复制代码

  • 初始化数据库
  1. pgbench -i -U <user> -d <dbname> -h <host>
复制代码
主库实验
  1. ./bin/pgbench -i -s 10 -d test_db -h 127.0.0.1 -p 5432 -U iuser
  2. 密码:xxx
  3. -i:表示初始化数据库。执行此命令后,pgbench 将创建必要的表和索引,并向数据库中插入初始数据。
  4. -s:指定了插入的规模因子(Scale Factor)。Scale Factor 是一个用于控制测试数据规模的参数,它决定了插入的数据量。在这个例子中,规模因子为 10,表示将会插入约为预设规模的 10 倍的数据。这意味着将会插入较大规模的测试数据,以便进行性能测试。比例因子,将生成的行数乘以给定的数,例如,在默认情况下,比例因子为1,pgbench_accounts表会创建100,000行,当-s 10 即会创建1,000,000行。
复制代码
  1. ./bin/pgbench -n -r -P 1 -d test_db -h 127.0.0.1 -p 5432 -U iuser -c 32 -j 32 -T 120
  2. 这个命令使用 pgbench 工具对 PostgreSQL 数据库执行性能测试,并输出了一些关于测试结果的统计信息。具体的参数含义如下:
  3. -n:表示不执行事务初始化阶段。如果数据库已经初始化过,可以通过这个选项跳过初始化步骤,直接执行测试。
  4. -r:表示按照事务顺序执行,而不是随机顺序。在这个例子中,使用的是 TPC-B 测试,它涉及到一系列按顺序执行的事务。
  5. -P 1:指定测试过程中的预热时间。在执行正式的测试之前,通常需要一段时间来预热数据库缓存。这个选项表示预热时间为 1 秒。
  6. -c 32:指定测试过程中的并发客户端数量为 32。即同时有 32 个客户端连接到数据库执行测试。
  7. -j 32:指定测试过程中的线程数量为 32。即同时有 32 个线程执行测试。
  8. -T 120:指定测试的持续时间为 120 秒。
复制代码
测试结果
  1. transaction type: <builtin: TPC-B (sort of)>
  2. scaling factor: 10
  3. query mode: simple
  4. number of clients: 32
  5. number of threads: 32
  6. duration: 120 s
  7. number of transactions actually processed: 109736
  8. latency average = 34.958 ms
  9. latency stddev = 172.667 ms
  10. tps = 913.754775 (including connections establishing)
  11. tps = 914.944815 (excluding connections establishing)
  12. script statistics:
  13. - statement latencies in milliseconds:
  14.          0.027  \set aid random(1, 100000 * :scale)
  15.          0.013  \set bid random(1, 1 * :scale)
  16.          0.011  \set tid random(1, 10 * :scale)
  17.          0.008  \set delta random(-5000, 5000)
  18.          1.122  BEGIN;
  19.          0.741  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
  20.          0.916  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
  21.          6.643  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
  22.         17.218  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
  23.          0.837  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
  24.          7.421  END;
复制代码
结果分析
  1. 根据提供的测试结果,我们可以进行性能分析:
  2. 平均延迟(Latency Average): 平均延迟约为 34.958 毫秒,这表示每个事务的平均执行时间。较低的延迟通常表示更好的性能。
  3. 延迟标准偏差(Latency Stddev): 延迟标准偏差为 172.667 毫秒,表示延迟值的离散程度。较小的标准偏差通常表示延迟值分布较为集中。
  4. 每秒事务数(TPS):在连接建立的情况下,TPS约为 913.75;不包括连接建立时,TPS约为 914.94。TPS 表示系统每秒钟可以处理的事务数量。较高的 TPS 值通常表示更好的性能。
  5. 各种语句的执行时间:在脚本统计中,每个语句的执行时间分别列出。可以看到,UPDATE 语句的执行时间较长,特别是 pgbench_branches 表的更新操作和 pgbench_tellers 表的更新操作。
  6. 基于以上数据,性能评估如下:
  7. 平均延迟较高:平均延迟较高,可能表示数据库服务器的负载较重或者系统资源不足。需要进一步分析系统资源使用情况,优化数据库配置或增加硬件资源以提高性能。
  8. TPS 较低:每秒处理的事务数量较低,可能会影响系统的并发处理能力。可以尝试优化 SQL 查询、调整连接池配置或者进行硬件升级等方式来提高 TPS。
  9. 部分语句执行时间较长:特别是 UPDATE 语句的执行时间较长,可能会影响整体性能。可以通过优化表结构、添加索引或调整查询计划等方式来减少执行时间。
  10. 综上所述,需要进一步分析系统的资源使用情况,并针对性地进行优化,以提高系统的性能和稳定性。
复制代码
观察主备的耽误
  1. iuser=# \x
  2. iuser=# select pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn)) as sent_delay,pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), write_lsn)) as write_delay,pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), flush_lsn)) as flush_delay,pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) as replay_delay, * from pg_stat_replication;
  3. iuser=# \watch 1
复制代码
运行过程中测试结果
  1. -[ RECORD 1 ]----+------------------------------
  2. sent_delay       | 0 bytes
  3. write_delay      | 0 bytes
  4. flush_delay      | 0 bytes
  5. replay_delay     | 1592 bytes
  6. pid              | 56584
  7. usesysid         | 24576
  8. usename          | rep
  9. application_name | walreceiver
  10. client_addr      | 192.168.121.24
  11. client_hostname  |
  12. client_port      | 45564
  13. backend_start    | 2024-03-05 00:29:50.486627+08
  14. backend_xmin     |
  15. state            | streaming
  16. sent_lsn         | 0/2B1D7998
  17. write_lsn        | 0/2B1D7998
  18. flush_lsn        | 0/2B1D7998
  19. replay_lsn       | 0/2B1D7360
  20. write_lag        | 00:00:00.005352
  21. flush_lag        | 00:00:00.005363
  22. replay_lag       | 00:00:00.007701
  23. sync_priority    | 1
  24. sync_state       | quorum
复制代码
运行过程中测试结果分析
  1. 根据提供的 pg_stat_replication 查询结果,我们可以分析主从数据库同步延迟情况如下:
  2. streaming 状态:从结果中可以看到,状态为 "streaming",这表示该从节点正在通过流复制(streaming replication)的方式与主节点同步数据。
  3. 延迟信息:从结果中的 sent_delay、write_delay、flush_delay 和 replay_delay 等字段可以看出不同阶段的延迟情况。这些字段表示从接收 WAL 日志到将其写入磁盘、刷新到持久存储、以及重放到从节点数据库的延迟情况。
  4. 延迟时间:从 write_lag、flush_lag 和 replay_lag 等字段可以看到相应的延迟时间。这些字段显示了在不同阶段的延迟时间,例如从接收到 WAL 日志到写入磁盘的延迟、刷新到持久存储的延迟以及重放到从节点数据库的延迟。
  5. 同步状态:sync_state 字段显示同步状态,这里是 "quorum",表示同步状态良好。
  6. 综合分析这些信息,可以得出以下结论:
  7. 延迟情况分析:从结果中可以看出,从节点的 replay 延迟较大,为 7.701 毫秒。这表示从节点接收到 WAL 日志后,需要经过约 7.7 毫秒的时间才能将其重放到从节点数据库中。其他阶段的延迟时间较小,都在毫秒级别。
  8. 同步状态正常:从结果中的 sync_state 字段可以看出,同步状态为 "quorum",表示同步状态良好,从节点与主节点之间的数据同步工作正常。
  9. 综上所述,根据 pg_stat_replication 查询结果分析,从节点的重放延迟较大,可能是由于从节点的资源负载较重或者网络延迟等原因导致。建议进一步分析系统资源使用情况,并针对性地进行优化,以减少同步延迟,提高主从数据库之间的同步性能。
复制代码
空载运行时结果对比
  1. -[ RECORD 1 ]----+------------------------------
  2. sent_delay       | 0 bytes
  3. write_delay      | 0 bytes
  4. flush_delay      | 0 bytes
  5. replay_delay     | 0 bytes
  6. pid              | 56584
  7. usesysid         | 24576
  8. usename          | rep
  9. application_name | walreceiver
  10. client_addr      | 192.168.121.24
  11. client_hostname  |
  12. client_port      | 45564
  13. backend_start    | 2024-03-05 00:29:50.486627+08
  14. backend_xmin     |
  15. state            | streaming
  16. sent_lsn         | 0/2F103930
  17. write_lsn        | 0/2F103930
  18. flush_lsn        | 0/2F103930
  19. replay_lsn       | 0/2F103930
  20. write_lag        |
  21. flush_lag        |
  22. replay_lag       |
  23. sync_priority    | 1
  24. sync_state       | quorum
复制代码
总结

物理流复制是 PostgreSQL 10 构建高可用架构的告急方案之一,实用于读写分离、数据容灾、快速故障切换等场景。与逻辑复制相比,物理复制能包管主备库的数据严格同等,但机动性较低。通过公道设置同步复制或异步复制,可以在性能与同等性之间找到最佳均衡,确保业务的稳固运行。🚀 想让你的 PostgreSQL 更高可用?物理流复制是必不可少的技能!💡
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表