【PGCCC】Postgresql 物理流复制

postgresql 提供了主从复制功能,有基于文件的拷贝和基于 tcp 流的数据传输两种方式。两种方式都是传输 wal 数据,前者是等待生成一个完整的wal文件后,才会触发传输,后者是实时传输的。可以看出来基于文件方式的延迟会比较高,而且wal文件有可能没来得及传输就被损坏了,造成了这块的数据丢失。基于 tcp 流的方式,延迟非常低,是现在最常见的方式,本篇文章也主要讲述这种方式。

进程启动

当配置好了主从后,我们需要先启动主库,再启动从库。

  1. 从库启动后,会创建 walreceiver 进程,然后发送同步请求到主库。
  2. 主库收到请求后,会创建 walsender 进程。
  3. walsender 进程启动后会和 walreceiver 建立 tcp 连接
  4. 主库和从库就依靠这个 tcp 连接进行后续通信

walsender 进程只会运行在主库上,而 walreceiver 进程只会运行在从库上。

通信协议

这里继续讲解后续的通信过程,为了让读者理解起来更加容易,会分为简单和复杂两个场景。我们知道 wal 数据是有 timeline 区分的,简单场景就是不包含timeline的切换,复杂场景则会包含。

简单场景

下图展示了通信流程:
在这里插入图片描述
首先从库会发送IDENTIFY_SYSTEM请求,用来确认主库的身份。每个 postgresql 数据库在第一次初始化时,都会分配一个唯一的systemid。当配置主从复制时,从库需要将主库的数据备份过来,这时候也会拷贝systemid,所以从库和主库的systemid是一样的。主库处理IDENTIFY_SYSTEM请求时,会返回自身的systemid。从库通过匹配它,可以判断出来主库的有效性。比如当用户在配置时错写了主库的地址,就可以检查出来。

从库在确认主库的身份后,就会发送START_REPLICATION请求,其中包含了从库想要获取的 wal 数据位置。主库收到请求后,会去检查该 wal 数据是否存在。如果不存在,主库会返回错误信息。从库收到错误信息后,会直接退出。如果发生了这种情况,那么我们则需要重新备份了,重新配置主从复制了。

在确认 wal 数据存在后,主库会传输数据给从库。

复杂场景

上面的简单场景只是假设了从库和主库的 timeline 是一致的,如果不一致还有额外的请求过程。如下图所示,主库此时已经变为了 timeline3,而从库因为网络原因断开了,只同步到了 timeline2 的位置时。
在这里插入图片描述
现在从库重新启动了,它想追赶到主库的位置,就必须先获取缺失 timeline 的数据。所以从库会先去请求 timeline2 的数据,接着请求 timeline3 的数据,直到与主库保持一致。

整个通信流程如下图:
在这里插入图片描述
从库开始会发送IDENTIFY_SYSTEM请求,主库会返回响应,包含了systemid和此时的timeline。从库会检查自身的timeline是否等于主库,如果不等于说明从库缺少中间 timeline 的数据。因为 timeline 都是自增的,所以从库只需要依次遍历就行了。从库会发送TIMELINE_HISTORY请求,请求获取指定 timeline 的信息。主库会返回这个 timeline 的起始位置。

心跳

从库会定期向主库汇报自身的同步进度,比如已经刷新wal数据的位置,已经应用wal数据的位置等,这样主库就可以了解到每个从库的情况。

当主库超过指定时间间隔,没有收到来自从库的消息,会发送Keepalive消息,强制要求从库汇报自身进度。

Replication Slot

当从库长时间落后主库过多,导致主库的wal数据还没出去,就被回收了。这种情况下,需要重新备份主库和重新配置从库。

在现实环境中,主库的数据量会比较大,导致备份的时间长并且对主库造成很大的性能影响。postgresql 针对者这种情况提供了 replication slot,它保存了从库的同步位置。主库在每次回收wal数据时,都会检查 replication slot,确保不会删除从库还未同步的数据。

replication slot 需要手动在主库中创建,然后在从库中配置。我们在使用 replication slot,需要时刻监控从库的情况,确保从库不会落后太多。否则主库上的 wal 数据不能回收,造成磁盘空间占满,进而会导致主库不能处理写请求。

实现原理

上面讲述了主库和从库之间的通信协议,这里继续讲解他们各自内部的实现。

从库

进程
从库的同步涉及到 wal 数据的获取和执行,分别由 walreciever 和 recovery 两个进程负责。walreciever 进程负责从主库中获取wal数据,当接收到新的 数据后,会通过 recovery 进程。recovery 进程负责读取并且执行接收的wal 数据。recovery 进程一直会读取新的 wal 数据并且应用,如果没有新的数据,它会阻塞等待 walreceiver 的唤醒。

状态
walreceiver 进程的状态表示从库的同步状态。它在启动的时候,状态为WALRCV_STARTING。启动完后,状态变为WALRCV_STREAMING。

walreceiver 进程在接收完指定 timeline 的数据后,会变为WALRCV_WAITING状态。等待后续指令。

recovery 进程在执行完这个 timeline 的数据后,会将 walceiver 的状态设置为WALRCV_RESTARTING。

walreceiver 向主库发起请求,获取下一个 timeline 的数据,状态会变为WALRCV_STREAMING。

walreceiver 会一直请求到最近的 timeline,直到和主库保持一致。

walreceiver 的状态会一直保持为WALRCV_RESTARTING,直到数据库关闭,变为WALRCV_STOPPING。

汇报
从库在空闲时间,会每隔100ms,检查一次。如果超过 wal_receiver_timeout / 2的时间,没有收到主库的信息,那么它会强制发送自身的信息到主库,包含自身的wal数据写入位置,刷新位置,应用位置。

如果没有超过,则试图发送自身的信息到主库。这里还需要考虑从库汇报自身信息的最低时间间隔,由wal_receiver_status_interval表示,如果小于时间间隔,那么则不会发送。

主库

进程
主库在接收到了从库的请求后,会创建 walsender 进程负责处理,walsender 会将 wal 数据发送给从库。当从库已经追赶上了主库,那么 walsender 会等待新的 wal 数据产生。

如果主库处理了来自客户的写请求,产生了新的wal 数据,会唤醒 walsender 进程。

状态
walsender 的初始状态为 WALSNDSTATE_CATCHUP,表示从库正在追赶主库。

当从库在追上主库后,状态会变为WALSNDSTATE_STREAMING,然后会一直维持这个状态。

心跳
wal_sender_timeout表示从库的超时时间,如果从库超过这段时间,一直没有信息,那么主库就会认为它出现了问题,会断开该连接。

如果超过了wal_sender_timeout / 2的时间,从库都没反应,那么主库会发送keepalive消息给从库,从库必须立即回应。

监控指标

主库监控

在主库执行下列 sql,可以获得从库的相关信息。不过有些信息都是由从库汇报上来的,比如flush_lsn,replay_lsn,会有一些延迟。

postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 22219
usesysid         | 25411
usename          | repl
application_name | walreceiver
client_addr      | 192.168.1.2
client_hostname  | 
client_port      | 35442
backend_start    | 2020-05-06 14:40:58.271771+08
backend_xmin     | 
state            | streaming
sent_lsn         | 0/70209B0
write_lsn        | 0/70209B0
flush_lsn        | 0/70209B0
replay_lsn       | 0/70209B0
write_lag        | 
flush_lag        | 
replay_lag       | 
sync_priority    | 0
sync_state       | async
reply_time       | 2020-05-06 14:41:08.308271+08

从库监控

postgres=# select * from pg_stat_wal_receiver;
-[ RECORD 1 ]---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pid                   | 852
status                | streaming
receive_start_lsn     | 0/7000000
receive_start_tli     | 1
received_lsn          | 0/7000000
received_tli          | 1
last_msg_send_time    | 2020-05-06 14:53:59.640178+08
last_msg_receipt_time | 2020-05-06 14:53:59.640012+08
latest_end_lsn        | 0/70209B0
latest_end_time       | 2020-05-06 14:40:58.293124+08
slot_name             | 
sender_host           | 192.168.1.1
sender_port           | 15432
conninfo              | ...

关于上面主控监控中,从库的关于 wal 的恢复信息获取会存在延迟。不过我们可以直接在从库上实时获取,

postgres=# select pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();
 pg_last_wal_receive_lsn | pg_last_wal_replay_lsn | pg_last_xact_replay_timestamp 
-------------------------+------------------------+-------------------------------
 0/70209B0               | 0/70209B0              | 2020-04-30 17:15:24.425998+08
(1 row)

作者:zhmin
链接:https://zhmin.github.io/posts/postgresql-physical-replication/
#PG证书#PG考试#postgresql培训#postgresql考试#postgresql认证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/915074.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日小练:Day2

1.乒乓球筐 题目链接:乒乓球筐__牛客网 题目描述: 这道题主要考察B盒是不是A盒的子集,我们可以通过哈希表来做 单哈希表 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public stat…

esp32学习:如何解决OV5640摄像头发热问题

我们在使用esp开发板过程中,连接ov2640摄像头时,非常正常,但连接ov5640摄像头时,会发现摄像头发烫,非常热,我们网上找解决方案,基本都是加散热片,没有根本解决问题。 前段时间&#…

JQuery封装的ajax

1. 注意&#xff1a; 首先要导jq的包json对象可以用 . 来调用keyjava只能给前端传页面&#xff0c;或者打印的内容String jsonstr json.toJSONString(resultJSON); //将对象转为JSON对象 Json格式和参数解释&#xff1a; <script src"js/jquery-1.10.2.min.js&quo…

【计算机网络】章节 知识点总结

一、计算机网络概述 1. 计算机网络向用户提供的两个最重要的功能&#xff1a;连通性、共享 2. 因特网发展的三个阶段&#xff1a; 第一阶段&#xff1a;从单个网络 ARPANET 向互联网发展的过程。1983 年 TCP/IP 协议成为 ARPANET 上的标准协议。第二阶段&#xff1a;建成三级…

Python+robotframework接口自动化测试实操(超详细总结)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 目前我们需要考虑的是如何实现关键字驱动实现接口自动化输出&#xff0c;通过关键字的封装实现一定意义上的脚本与用例的脱离&#xff01; robot framework 的…

如何管理好自己的LabVIEW项目

在LabVIEW项目开发中&#xff0c;项目管理对于提高开发效率、确保项目质量、减少错误和维护成本至关重要。以下从项目规划、代码管理、测试与调试、版本控制、团队协作等方面&#xff0c;分享LabVIEW项目管理的体会。 ​ 1. 项目规划与需求分析 关键步骤&#xff1a; 需求分析…

【快速解决】kafka崩了,重启之后,想继续消费,怎么做?

目录 一、怎么寻找我们关心的主题在崩溃之前消费到了哪里&#xff1f; 1、一个问题&#xff1a; 2、查看消费者消费主题__consumer_offsets 3、一个重要前提&#xff1a;消费时要提交offset 二、指定 Offset 消费 假如遇到kafka崩了&#xff0c;你重启kafka之后&#xff0…

matlab建模入门指导

本文以水池中鸡蛋温度随时间的变化为切入点&#xff0c;对其进行数学建模并进行MATLAB求解&#xff0c;以更为通俗地进行数学建模问题入门指导。 一、问题简述 一个煮熟的鸡蛋有98摄氏度&#xff0c;将它放在18摄氏度的水池中&#xff0c;五分钟后鸡蛋的温度为38摄氏度&#x…

51单片机应用开发(进阶)---定时器应用(电子时钟)

实现目标 1、巩固定时器的配置流程&#xff1b; 2、掌握按键、数码管与定时器配合使用&#xff1b; 3、功能1&#xff1a;&#xff08;1&#xff09;简单显示时间。显示格式&#xff1a;88-88-88&#xff08;时-分-秒&#xff09; 4、功能2&#xff1a;&#xff08;1&#…

【外包】软件行业的原始形态,项目外包与独立开发者

【外包】互联网软件行业的原始形态&#xff0c;项目外包与独立开发者 本科期间写的一些东西&#xff0c;最近整理东西看到了&#xff0c;大致整理一下放出来&#xff0c;部分内容来自其他文章&#xff0c;均已引用。 文章目录 1、互联网软件行业的原始形态2、项目订单&#xff…

Python酷库之旅-第三方库Pandas(208)

目录 一、用法精讲 971、pandas.MultiIndex.set_levels方法 971-1、语法 971-2、参数 971-3、功能 971-4、返回值 971-5、说明 971-6、用法 971-6-1、数据准备 971-6-2、代码示例 971-6-3、结果输出 972、pandas.MultiIndex.from_arrays类方法 972-1、语法 972-2…

基于ConvNeXt的矿石种类识别

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

C++入门基础知识140—【关于C++ 类构造函数 析构函数】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C 类构造函数 & 析构函数的相关内容…

【Linux】-学习笔记03

第十一章-管理Linux软件包和进程 1.源码下载安装软件 1.1概念 源码文件&#xff1a;程序编写者使用C或C等语言编写的原始代码文本文件 源码文件使用.tar.gz或.tar.bz2打包成压缩文件 1.2特点 源码包可移植性好&#xff0c;与待安装软件的工作环境依赖性不大 由于有编译过程…

鸿蒙HarmonyOS(ArkUI基础篇大合集!)

文章目录 ArkUI&#xff08;方舟UI框架&#xff09;1.简介2.基本概念3.概述4.布局1.概述2.通用布局属性&#x1f388;1.盒子属性2.背景属性3.定位属性4.通用属性&#x1f388; 3.线性布局4.弹性布局(Flex)5.层叠布局(Stack) 5.组件1.使用文本1.文本显示(Text/Span)2.文本输入 (…

Prompt 工程

Prompt 工程 1. Prompt 工程简介 “预训练-提示预测”范式是近年来自然语言处理&#xff08;NLP&#xff09;领域的一个重要趋势&#xff0c;它与传统的“预训练-微调-预测”范式相比&#xff0c;提供了一种更为灵活和高效的模型应用方式。 Prompt工程是指在预训练的大型语言…

十天入门javaScript第四天(Promises对象异步 )(睡眠函数) (json)

Promise 是一个 JavaScript 的内置对象&#xff0c;它代表了一个异步操作的最终完成&#xff08;或失败&#xff09;及其结果值。Promise 对象是异步编程的一种解决方案&#xff0c;它可以使异步操作以更简洁、更易于管理的方式进行。 Promise 对象有三个状态&#xff1a; Pen…

【C#设计模式(8)——过滤器模式(Adapter Pattern)】

前言 滤液器模式可以很方便地实现对一个列表中的元素进行过滤的功能&#xff0c;能方便地修改滤器的现实&#xff0c;符合开闭原则。 代码 //过滤接口public interface IFilter{List<RefuseSorting> Filter(List<RefuseSorting> refuseList);}//垃圾分类public cla…

开源共建 | 长安链开发常见问题及规避

长安链开源社区鼓励社区成员参与社区共建&#xff0c;参与形式包括不限于代码贡献、文章撰写、社区答疑等。腾讯云区块链王燕飞在参与长安链测试工作过程中&#xff0c;深入细致地总结了长安链实际开发应用中的常见问题及其有效的规避方法&#xff0c;相关内容多次解答社区成员…

华为云创建ECS前台展示规格类型选项是怎么做到的?

前台展示很多规格可选&#xff0c;怎么做到的&#xff1f;先了解规格其实都是管理员在后台service_OM创建好规格 1.规格 1.1设置自定义标签打通规格和主机组还能体验调度功能 引申&#xff1a;AZ可用分区&#xff08;为了做容灾&#xff09; 为什么在界面可以让我√az0.dc0,…