PostgreSQL码农集散地

领导找我谈心,为什么我总是慢ta半拍?

今天怀着沉重的心情发表这一篇信息,PostgreSQL同步流复制、时间点恢复、分区表、Hot standby等核心功能的作者Simon永远的离开了我们,他来中国支持第二届PostgreSQL用户大会2012年在人民大学:

Image
​
Image
​

作为一位开源爱好者,缅怀大师Simon,开源有你更精彩,PG有你更精彩。

文章开始前推荐2个学习环境: 

1、懒人Docker镜像, 已打包200+插件:《最好的PostgreSQL学习镜像》

2、免费的云起实验室: 《免费体验PolarDB开源数据库》
3、PolarDB开源数据库内核、最佳实践等学习图谱:  https://www.aliyun.com/database/openpolardb/activity 
欢迎关注我的公众号, 持续发布PostgreSQL、PolarDB、DuckDB等开源相关技术文章. 

为什么只读实例延迟高?

https://www.bilibili.com/video/BV1br4y1h7jY/

什么原因会导致只读实例延迟?

  • 这里说的都是物理流复制, 不包括逻辑复制. (逻辑复制的延迟更高)

  • 分两种延迟情况进行分析: send delay, apply delay

社区版本:

  • 在只读实例上执行SQL, 某些SQL可能读到冲突, 发生冲突就需要暂停wal apply, 导致WAL apply延迟

  • 设置了 recovery_min_apply_delay 参数恢复延迟

Image

排除以上等待问题, 还有常规问题导致的延迟:

  • 网络带宽低, freeze风暴, vacuum风暴, full page过多等, 导致send 延迟

  • 只读实例IO设备性能问题, 导致apply 慢, 而且startup恢复进程为单进程恢复时采用同步IO, 对于IO延迟高的设备只读实例延迟尤为明显. 例如网盘、分布式网络存储.

  • apply架构的天然缺陷,

    • 1、startup为单进程,

    • 2、内存有限导致多次IO, 数据块恢复后可能驱逐出shared buffer, 所以同一个数据块在被多次恢复时, 可能产生多次物理IO.

社区版本优化手段, 降低wal send和replay延迟的方法 (没有从根源上解决, 而是从使用角度尽量来规避):

  • 减少或避免快照冲突,

    • 但是有弊端, 参考 《PostgreSQL物理"备库"的哪些操作或配置,可能影响"主库"的性能、垃圾回收、IO波动》

    • 避免只读库上的 long query | xact

    • 修改ro节点参数 hot_standby_feedback=on, 只要ro库有查询, 就会返回snapshot xid给主库, 主库的垃圾回收进程不会回收这个垃圾.

    • 开启 vacuum_defer_cleanup_age 保留一定的dead tuples数据.

  • 减少冲突的时长

    • 在RO节点设置statement timeout , 低于主动cancel query的delay时长.

    • 在RO节点设置max_standby_archive_delay、max_standby_streaming_delay, 尽早cancel query.

  • 如果是standby本身资源问题导致delay, 那么建议查看standby节点的网络带宽、cpu、io能力是否存在瓶颈. 该加资源就加资源.

    • 《PostgreSQL 流复制冲突分类讲解以及对应解决方案 - DEALING WITH STREAMING REPLICATION CONFLICTS IN POSTGRESQL - 特别是lock confict(vacuum truncate suffix free page引起的)
      》

    • 《PostgreSQL standby conflict replay分析和解决方案》

  • 无法避免的冲突

    • HOT chain 清理导致的 buffer page pin 冲突

    • DDL

    • drop tablespace|database

PolarDB:
https://github.com/ApsaraDB/PolarDB-for-PostgreSQL/tree/POLARDB_11_DEV/docs/zh/architecture
从根源解决只读实例延迟高的问题:

  • 采用 log index 支持异步并行恢复

  • 共享存储, 不需要传输wal payload data, 只需要传输wal metadata(解析出来的pageid, lsn list)

  • 共享存储, 通过shared buffer脏页刷新推进, 不需要100%应用日志

  • 使用异步DDL回放, 不堵塞wal replay回放进程, (理论上异步wal回放也可以避免DDL, drop tablespace|database的冲突导致堵塞整个wal replay进程).

传统复制和恢复流程:
Image

PolarDB log index
Image

PolarDB 只复制meta
Image

PolarDB 异步并行恢复
Image

PolarDB 异步DDL回放
Image

PolarDB VS 社区版本 复制对比:
wal传输量对比
Image

延迟对比
Image

DDL堵塞数据对比
Image

本期问题1:
哪些是导致只读实例延迟的原因?

  • a. 复制网络带宽低

  • b. 只读实例上的LONG SQL查询与WAL replay发生了各种冲突(例如ddl, snapshot, drop tbs|db, buffer pin 等conflict), 导致堵塞了wal replay

  • c. 设置了主动延迟恢复

  • d. 只读实例硬件性能差

  • e. replay进程为单进程同步回放架构

  • f. 内存有限, 回放过程中单个page的多次修改可能发生多次物理IO

  • g. 只读实例需要接收所有WAL, 遇到突发性的大量写WAL事件, 例如大量数据同时发生vacuum freeze, 大表vacuum等.

  • h. 只读实例有任何SQL查询存在时, 都会堵塞wal的恢复

答案:

  • abcdefg

解释:

  • 参考本文内容

本期问题2:
社区版本如何优化只读实例延迟问题?

  • a. 避免只读库上的 long query | xact

  • b. 关闭 hot_standby_feedback

  • c. 设置 vacuum_defer_cleanup_age, 保留一定的dead tuples数据

  • d. 设置非常大的 statement timeout

  • e. 提高复制网络带宽, 提高cpu、io能力

答案:

  • ace

解释:

  • 参考本文内容

本期问题3:
PolarDB做了什么使得只读实例几乎没有延迟?

  • a. 采用 log index 异步并行恢复

  • b. 采用共享存储架构, 不需要传输wal payload data, 只需要传输wal metadata, 大幅度减少WAL传输量

  • c. 采用共享存储架构, 通过shared buffer脏页刷新推进, 并不需要100%应用日志

  • d. 使用异步DDL回放, 不堵塞wal replay回放进程

  • e. 采用了多个WAL replay process, 并行恢复, 加快了恢复速度

答案:

  • abcd

解释:

  • 参考本文内容

欢迎关注我的github (https://github.com/digoal/blog) , 学习数据库不迷路.  

近期正在写公开课材料, 未来将通过视频号推出, 欢迎关注视频号:

Image

文章中的参考文档请点击阅读原文获得.