基于Patroni+etcd+流复制搭建PostgreSQL高可用——筑梦之路

news2024/11/17 20:37:46

Patroni方案简介

Patroni是一个基于zk、etcd、consul等的pg ha模板,可以使用python来创建和定制高可用性解决方案。Patroni使用分布式key-value数据库作为数据存储,主节点故障时进行主节点重新选举。通过PG内置的流复制,支持同步和异步复制。

由于数据库信息记录在ETCD中,通过增加部署实例数可以避免脑裂,且该方案自动化程度较高,可以自动初始化PG实例;当STANDBY实例关闭后,支持自动尝试拉起;支持当主库宕机后自动选取新主库。

ETCD是一个基于RAFT协议的分布式Key-Value数据库,基于Go语言编写,Patroni监控本地的PG数据库状态,并将相关信息写入ETCD。每个Patroni都能读写ETCD的KEY,从而获取其他主机的PG数据库实例信息。

环境说明

  • 操作系统:CentOS Linux 7.9

  • 数据库版本:PostgreSQL 13.1

  • Python版本:Python3.8

  • ETCD版本:3.3

  • Patroni版本:2.0.1

 部署规划

主机名

IP

组件

备注

PG1

192.168.21.135

PostgreSQL、Patroni、ETCD

MASTER

PG2

192.168.21.136

PostgreSQL、Patroni、ETCD

STANDBY

PG3

192.168.21.137

PostgreSQL、Patroni、ETCD

STANDBY

 搭建部署

1. 安装PostgreSQL以及搭建流复制

2. 安装etcd集群

# PG1节点

sudo yum install -y etcd
vim etc/etcd/etcd.conf
ETCD_NAME="node1"
ETCD_DATA_DIR="/var/lib/etcd/node1.etcd"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://192.168.21.135:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://192.168.21.135:2379"
ETCD_LISTEN_PEER_URLS="http://192.168.21.135:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.21.135:2380"
ETCD_INITIAL_CLUSTER="node1=http://192.168.21.135:2380,node2=http://192.168.21.136:2380,node3=http://192.168.21.137:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

# PG2节点

sudo yum install -y etcd
vim /etc/etcd/etcd.conf
ETCD_NAME="node2"
ETCD_DATA_DIR="/var/lib/etcd/node2.etcd"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://192.168.21.136:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://192.168.21.136:2379"
ETCD_LISTEN_PEER_URLS="http://192.168.21.136:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.21.136:2380"
ETCD_INITIAL_CLUSTER="node1=http://192.168.21.135:2380,node2=http://192.168.21.136:2380,node3=http://192.168.21.137:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

# PG3节点

sudo yum install -y etcd
vim /etc/etcd/etcd.conf
ETCD_NAME="node3"
ETCD_DATA_DIR="/var/lib/etcd/node3.etcd"
ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://192.168.21.137:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://127.0.0.1:2379,http://192.168.21.137:2379"
ETCD_LISTEN_PEER_URLS="http://192.168.21.137:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.21.137:2380"
ETCD_INITIAL_CLUSTER="node1=http://192.168.21.135:2380,node2=http://192.168.21.136:2380,node3=http://192.168.21.137:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

3. 安装patroni

# 这里采用编译安装的方式

# 安装依赖包

yum install -y libffi-devel libuuid libuuid-devel

# 安装python

tar -xzvf python-3.8.7.tgz
cd python-3.8.7
./configure
make -j 7
make -j 7 install

rm -rf /usr/bin/python
ln -s /usr/local/bin/python3 /usr/bin/pyhon

# 处理yum的问题

vim /usr/bin/yum
修改#!/usr/bin/python 为#!/usr/bin/python2


# 安装patroni

pip3 install psycopg2-binary
pip3 install patroni[etcd]

4. 创建patroni配置文件

# PG1节点

mkdir /etc/patroni

vim /etc/patroni/patroni.conf

scope: etcd_patroni_pg
namespace: /data/
name: pg1
restapi:
listen: 192.168.21.135:8008
connect_address: 192.168.21.135:8008
etcd:
host: 192.168.21.135:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
master_start_timeout: 300
synchronous_mode: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
listen_address: "*"
port: 5432
max_connections: 2000
hot_standby: "on"
max_locks_per_transactions: 128
max_prepared_transactions: 2000
max_replication_slots: 10
max_wal_sender: 10
max_worker_precesses: 256
track_commit_timestamp: "on"
wal_keep_size: 0
wal_level: replica
wal_log_hints: "on"
log_directory: "log"
log_destination: "stderr"
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.21.135:5432
data_dir: /data/pgdata
bin_dir: /opt/pg13/bin
pgpass: /home/postgres/.pgpass
authentication:
replication:
username: replica
password: replica
superuser:
username: postgres
password: root
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
# PG2节点

mkdir /etc/patroni

vim /etc/patroni/partoni.conf

scope: etcd_patroni_pg
namespace: /data/
name: pg2
restapi:
listen: 192.168.21.136:8008
connect_address: 192.168.21.136:8008
etcd:
host: 192.168.21.136:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
master_start_timeout: 300
synchronous_mode: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
listen_address: "*"
port: 5432
max_connections: 2000
hot_standby: "on"
max_locks_per_transactions: 128
max_prepared_transactions: 2000
max_replication_slots: 10
max_wal_sender: 10
max_worker_precesses: 256
track_commit_timestamp: "on"
wal_keep_size: 0
wal_level: replica
wal_log_hints: "on"
log_directory: "log"
log_destination: "stderr"
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.21.136:5432
data_dir: /data/pgdata
bin_dir: /opt/pg13/bin
pgpass: /home/postgres/.pgpass
authentication:
replication:
username: replica
password: replica
superuser:
username: postgres
password: root
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
# PG3节点

mkdir /etc/patroni
vim /etc/patroni/patroni.conf
scope: etcd_patroni_pg
namespace: /data/
name: pg3
restapi:
listen: 192.168.21.137:8008
connect_address: 192.168.21.137:8008
etcd:
host: 192.168.21.137:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
master_start_timeout: 300
synchronous_mode: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
listen_address: "*"
port: 5432
max_connections: 2000
hot_standby: "on"
max_locks_per_transactions: 128
max_prepared_transactions: 2000
max_replication_slots: 10
max_wal_sender: 10
max_worker_precesses: 256
track_commit_timestamp: "on"
wal_keep_size: 0
wal_level: replica
wal_log_hints: "on"
log_directory: "log"
log_destination: "stderr"
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.21.137:5432
data_dir: /data/pgdata
bin_dir: /opt/pg13/bin
pgpass: /home/postgres/.pgpass
authentication:
replication:
username: replica
password: replica
superuser:
username: postgres
password: root
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false

5. 将patroni加入服务开机启动

vim /etc/systemd/system/patroni.service

[Unit]
Description=patroni - a high-availability PostgreSQL
Documentation=https://patroni.readthedocs.io/en/latest/index.html
After=syslog.target network.target etcd.target
Wants=network-online.target
[Service]
Type=simple
User=postgres
Group=postgres
PermissionsStartOnly=true
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml
ExecReload=/bin/kill -HUP $MAINPID
LimitNOFILE=65536
KillMode=process
KillSignal=SIGINT
Restart=on-abnormal
RestartSec=30s
TimeoutSec=0
[Install]
WantedBy=multi-user.target

6. 启动集群

启动数据库:
Pg_ctl start $PGDATA

启动etcd:
Sudo systemctl start etcd

启动patroni:
Sudo systemctl start patroni

检查验证

1. 查看集群节点状态

patronictl -c /etc/patroni/patroni.yml list
  • Role:显示当前节点所属状态;

  • TL:显示当前集群的时间线;

  • Lag in MB:显示当前集群主备延迟大小

2.  手工触发主备切换

选择某一可用的从节点,使其成为主节点角色
patronictl -c /etc/patroni/patroni.yml switchover
查看集群状态
patronictl -c /etc/patroni/patroni.yml list

 原始旧主库,自动切换为新主的备库,TL时间线变化。切换后,旧主库会自动跟随新主库。

3. 手工停止主节点Patroni

再次发生主备切换,重新启动patroni组件后,集群状态 

pg2自动跟随新主库pg3。

当某一节点与主库不同步,或者节点异常运行时,
可以使用此方法初始化节点信息以重新加入集群。
patronictl -c /etc/patroni/patroni.yml reinit pgsql
1.选择以下需要添加的节点名称:pg2
2.你确定要重新初始化成员 pg2?[y/N]:y
3.成功:为成员pgsql_node3执行初始化

4. 手动停止PG主节点实例

 从上面的过程可以看出,停止主库的后,patroni组件很快就检测到主库宕机,然后尝试将主库重新启动。如果启动不成功,则触发主备切换。

绑定VIP

Patroni集群,在应用连接时,可以连接多个IP,在使用时,先判断当前实例是否为MASTER,如果是,则业务继续进行,否则需要尝试其他IP。PATRONI可以将VIP绑定在MASTER节点,当主备切换时,VIP漂移到新主节点。

1. 修改patroni配置文件,每个节点都需要

scope: etcd_patroni_pg1
namespace: /data/
name: pg1
restapi:
listen: 192.168.21.135:8008
connect_address: 192.168.21.135:8008
etcd:
host: 192.168.21.135:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
master_start_timeout: 300
synchronous_mode: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
listen_address: "*"
port: 5432
max_connections: 2000
hot_standby: "on"
max_locks_per_transaction: 128
max_prepared_transactions: 2000
max_replication_slots: 10
max_wal_sender: 10
max_worker_precesses: 256
track_commit_timestamp: "on"
wal_keep_size: 0
wal_level: replica
wal_log_hints: "on"
log_directory: "log"
log_destination: "stderr"
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.21.135:5432
data_dir: /data/pgdata
bin_dir: /opt/pg13/bin
authentication:
replication:
username: replica
password: replica
superuser:
username: postgres
password: root
pgpass: /home/postgresql/.pgpass
callbacks:
on_start: /etc/patroni/patroni_callback.sh
on_stop: /etc/patroni/patroni_callback.sh
on_role_change: /etc/patroni/patroni_callback.sh
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false

注意:

callbacks:
on_start: /etc/patroni/patroni_callback.sh
on_stop: /etc/patroni/patroni_callback.sh
on_role_change: /etc/patroni/patroni_callback.sh

此段为绑定VIP需要的shell脚本。

2. shell脚本

#!/bin/bash

readonly cb_name=$1
readonly role=$2
readonly scope=$3

function usage() {
echo "Usage: $0 <on_start|on_stop|on_role_change> <role> <scope>";
exit 1;
}

echo "this is patroni callback $cb_name $role $scope"

case $cb_name in
on_stop)
sudo ip addr del 192.168.21.250/24 dev ens33 label ens33:1
sudo arping -q -A -c 1 -I ens33 192.168.21.250
#sudo iptables -F
;;
on_start)
;;
on_role_change)
if [[ $role == 'master' ]]; then
sudo ip addr add 192.168.21.250/24 brd 192.168.21.255 dev ens33 label ens33:1
sudo arping -q -A -c 1 -I ens33 192.168.21.250
#sudo iptables -F
elif [[ $role == 'slave' ]]||[[ $role == 'replica' ]]||[[ $role == 'logical' ]]; then
sudo ip addr del 192.168.21.250/24 dev ens33 label ens33:1
sudo arping -q -A -c 1 -I enp0s8 192.168.21.250
#sudo iptables -F
fi
;;
*)
usage
;;
esac

总结

 Patroni用于构建高可用 PostgreSQL 集群的工具,它通过自动化的方式来管理主备切换、数据复制和集群健康检查。

参考资料:

乖乖,PG高可用咱不用主从流复制了,咱试试patroni

基于Patroni+etcd+流复制搭建PostgreSQL高可用 - 墨天轮

使用Patroni和HAProxy创建高度可用的PostgreSQL集群-腾讯云开发者社区-腾讯云

https://www.linode.com/docs/guides/create-a-highly-available-postgresql-cluster-using-patroni-and-haproxy/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java中,怎样用最简单方法实现写word文档

在跨平台环境中实现写word时&#xff0c;如果用现成的库&#xff0c;就会涉及跨平台兼容性问题&#xff0c;比如在安卓与java中实现写word的功能。还有一个问题就是&#xff0c;完全用程序生成word文档&#xff0c;工作量较大。所以采用了模板替换的方法。 docx文档本质就是一…

BUUCTF [GUET-CTF2019]zips 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 得到一个attachment.zip文件 解题思路&#xff1a; 1、解压attachment.zip&#xff0c;得到222.zip文件。尝试解压需要密码&#xff0c;使用Ziperello爆破密码…

C语言学习笔记-- 3.4.2实型变量

1.实型数据在内存中的存放形式&#xff08;了解&#xff09; 实型数据一般占4个字节&#xff08;32位&#xff09;内存空间。按指数形式存储。 2.实型变量的分类&#xff08;掌握&#xff09; 实型变量分为&#xff1a;单精度&#xff08;float型&#xff09;、双精度&#…

在线思维导图编辑!3个AI思维导图生成软件推荐!

思维导图&#xff0c;一种以创新为驱动的视觉化思考工具&#xff0c;已经渗透到我们日常生活和工作的各个角落。当我们需要整理思绪、规划项目或者梳理信息时&#xff0c;思维导图总能提供极大的帮助。 近些年随着云服务等基础设施的完善&#xff0c;我们可以看到越来越多提供…

new CCDIKSolver( OOI.kira, iks ); // 创建逆运动学求解器

demo案例 new CCDIKSolver(OOI.kira, iks); 在使用某个特定的库或框架来创建一个逆运动学&#xff08;Inverse Kinematics, IK&#xff09;求解器实例。逆运动学在机器人学、动画和计算机图形学等领域中非常重要&#xff0c;它用于根据期望的末端执行器&#xff08;如机器人的…

【IOT】OrangePi+HomeAssistant+Yolov5智能家居融合

前言 本文将以OrangePi AIpro为基础&#xff0c;在此基础构建HomeAssistant、YOLO目标检测实现智能家居更加灵活智能的场景实现。 表头表头设备OrangePi AIpro(8T)系统版本Ubuntu 22.04.4 LTSCPU4核64位处理器 AI处理器AI算力AI算力 8TOPS算力接口HDMI2、GPIO接口、Type-C、M.2…

复购率下降是什么原因导致的?三个步骤直击复购率下降根源

在商业运营中&#xff0c;回购率的波动往往能够直观地反映出客户对品牌和产品的忠诚程度。一个健康的回购率可以为企业带来稳定的收入流&#xff0c;同时也是品牌口碑和市场影响力的有力证明。但是&#xff0c;当企业面临回购率下降的情况时&#xff0c;这通常是一个警示信号&a…

c++(六)

c&#xff08;六&#xff09; 多态概念在c中是如何实现多态静态多态&#xff08;绑定&#xff09;动态多态&#xff08;绑定&#xff09; 动态多态的实现原理动态内存分配中遇到的问题 重载、重定义、重写的区别抽象类接口类---抽象类空类对象的内存大小explicitfinal修饰类修饰…

串口调试助手中文乱码 解决方案

输出乱码 一般&#xff0c;当串口调试助手输出乱码时&#xff0c;可能有以下几个原因&#xff1a; 波特率设置错误&#xff1a;串口通信需要保证发送和接收的设备使用相同的波特率。请检查串口调试助手和目标设备的波特率设置是否一致。 数据位、停止位或校验位设置错误&…

java Web开发中采用Servlet登录验证,中文用户名始终提示“用户名密码错误”以及输出中文乱码问题

采用Servlet登录验证&#xff0c;中文乱码问题解决 在Java Web开发中&#xff0c;往往采用Servlet完成前后端直接的控制和处理&#xff0c;例如&#xff1a;用户登录验证功能。 在采用如下Servle源码t完成用户名登录验证时&#xff0c;只要用户名涉及中文&#xff0c;对于正确…

kafka-偏移量图解

生产者偏移量&#xff1a;生产者发送消息时写入到哪个位置&#xff08;主题的每个分区会存储一个 leo 即将写入消息的偏移量&#xff09;&#xff0c;每次写完消息 leo 会 1 消费者偏移量&#xff1a;消费者从哪个位置开始消费消息&#xff0c;小于等于 leo&#xff0c;每个组…

电脑怎么清理c盘垃圾文件 电脑运行内存不足怎么清理

和Windows系统电脑文件分区不同&#xff0c;苹果电脑并不分区&#xff0c;默认只有C盘&#xff0c;当C盘垃圾文件过多&#xff0c;电脑运行内存不足时&#xff0c;手动清理电脑垃圾文件毫无头绪&#xff0c;可以尝试使用苹果电脑清理软件——CleanMyMac来清理 。 一、电脑怎么…

Stable Diffusion WebUI详细使用指南

Stable Diffusion WebUI&#xff08;AUTOMATIC1111&#xff0c;简称A1111&#xff09;是一个为高级用户设计的图形用户界面&#xff08;GUI&#xff09;&#xff0c;它提供了丰富的功能和灵活性&#xff0c;以满足复杂和高级的图像生成需求。由于其强大的功能和社区的活跃参与&…

618局外人抖音:别人挤压商家“拼价格”,它默默联合商家“抢用户”?

文&#xff5c;新熔财经 作者&#xff5c;宏一 “618”来临之际&#xff0c;各电商平台和短视频平台早已打响了“促销大战”。不过&#xff0c;今年各大平台都更积极适应新的消费形式&#xff0c;调整了“大促动作”。 比如淘宝、京东带头取消了沿用十年之久的预售机制&…

【JS红宝书学习笔记】第4章 变量、作用域和内存

第4章 变量、作用域和内存 1. 原始值和引用值&#xff08;面试题&#xff09; ECMAScript 变量可以包含两种不同类型的数据&#xff1a;原始值和引用值。原始值&#xff08;primitive value&#xff09;就是最简单的数据&#xff08;Undefined、Null、Boolean、Number、Strin…

windows上安装miniforge和jupyterlab

1&#xff0c;下载miniforge3 GitHub - conda-forge/miniforge: A conda-forge distribution. 下载下来后傻瓜式安装就可以了 配置环境变量&#xff0c;在系统环境变量的path添加下列就行了&#xff0c;根据自己的路径修改 2&#xff0c;创建虚拟环境 conda create -n test …

1比1万地形图符号库分享

我们在《1:2.5万、1:5万、1:10万军用地形图图式》一文中&#xff0c;为大家分享过军用地形图式。 还在《超实用三调符号库分享下载》一文中&#xff0c;为大家分享过三调符号库。 现在再为你分享一个&#xff11;比&#xff11;万的地形图符号库&#xff0c;请在文末查看符号…

四象限桌面怎么制作 结合桌面便签更高效

在繁忙的工作中&#xff0c;我们经常面临各种任务和项目的挑战&#xff0c;如何高效地管理这些任务成为提升工作效率的关键。这时候&#xff0c;四象限时间管理法就显得尤为重要。 四象限&#xff0c;即将工作按照紧急与重要程度分为四类&#xff1a;紧急且重要、紧急不重要、…

怎么从视频中提取音频?这里有三种提取妙招

怎么从视频中提取音频&#xff1f;在数字媒体日益丰富的今天&#xff0c;视频内容成为了信息传播的重要形式。但有时我们可能只需要视频中的音频部分&#xff0c;用于制作播客、音乐剪辑或语音分析等。幸运的是&#xff0c;技术的发展为我们提供了多种从视频中高效提取音频的方…

今日好料推荐(大数据湖体系规划)

今日好料推荐&#xff08;大数据湖体系规划&#xff09; 参考资料在文末获取&#xff0c;关注我&#xff0c;获取优质资源。 大数据湖体系规划 一、大数据湖简介 大数据湖&#xff08;Data Lake&#xff09;是一个集中式的存储库&#xff0c;用于存储来自各种来源的结构化和…