首页 > 数据库 >posgresql数据库高可用方案-patroni

posgresql数据库高可用方案-patroni

时间:2024-11-07 16:35:50浏览次数:1  
标签:http -- 数据库 192.168 2380 patroni etcd posgresql

一、简介
pg常用高可用方案有repmgr,patroni等,本文介绍patroni方案。

Patroni,是专门为PostgreSQL数据库设计的一款以Python语言实现的高可用软件。其使用外部共享存储软件(kubernetes、etcd、etcd3、zookeeper、aws等)来存储patroni监控到的pg集群状态信息,实现 PostgreSQL 集群的自动故障恢复、自动故障转移等能力。

etcd是一个分布式键值对存储,设计用来可靠而快速的保存关键数据并提供访问,Etcd按照Raft算法和协议开发的,是一个强一致性的、分布式的key-value数据库。它为分布式系统提供了可靠的数据存储访问机制,patroni配合etcd一起使用来保障pg高可用。

本文通过patroni+etcd方式实现postgresql的高可用方案,以下是个软件版本。

python patroni etcd
3.7.4 2.0.2 3.3.11
二、部署etcd集群
1、yum方式部署etcd集群
#安装依赖包
yum install -y gcc python-devel epel-release libyaml
#安装etcd
yum install -y etcd libyaml

安装完成后etcd目录:
[root@xl001 ~]# ll /usr/bin/etcd*
-rwxr-xr-x 1 root root 25581944 Feb 14  2019 /usr/bin/etcd
-rwxr-xr-x 1 root root 21223848 Feb 14  2019 /usr/bin/etcdctl


2、二进制包安装
wget https://github.com/etcd-io/etcd/releases/download/v3.2.32/etcd-v3.2.32-linux-amd64.tar.gz

解压即可
tar -zxvf etcd-v3.2.32-linux-amd64.tar.gz
然后将 etcd  etcdctl  拷贝到 /usr/local/bin  下

etcd --version                    #etcd 为服务端执行文件
etcdctl --version                 #etcdctl 为客户端执行文件

以上两种安装方式任选一种即可,pg集群三个节点上都要安装。

3、创建目录并授权
mkdir -p /opt/etcd
chown -R postgres:postgres /opt/etcd


4、编辑etcd配置文件
chown -R postgres:postgres /etc/etcd/etcd.conf
vim /etc/etcd/etcd.conf

ETCD_NAME="etcd-1"       #节点名称,随便起个名字,三个节点不同即可,我这里三个节点叫做etcd-1,etcd-2,etcd-3
ETCD_DATA_DIR="/opt/etcd"  #数据目录

#监听客户端请求的地址列表url,可以监听多个,多个用逗号分割,或者写成0.0.0.0,监听所有请求地址。
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"  
 
#建议使用的客户端通信 url,该值用于 etcd 代理或 etcd 成员与 etcd 节点通信,192.168.167.11是本节点ip。   
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.167.11:2379"

监听的用于节点之间通信的url,可监听多个,集群内部将通过这些url进行数据交互(如选举,数据同步等)
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

#建议用于节点之间通信的url,节点间将以该值进行通信,192.168.167.11是本节点ip。
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.167.11:2380"

#也就是集群中所有的 initial-advertise-peer-urls 的合集。etcd启动的时候,通过这个配置找到其他etcd节点的列表。
ETCD_INITIAL_CLUSTER="etcd-1=http://192.168.167.11:2380,etcd-2=http://192.168.167.12:2380,etcd-3=http://192.168.167.13:2380"

#节点的 token 值,设置该值后集群将生成唯一 id,并为每个节点也生成唯一 id,当使用相同配置文件再启动一个集群时,只要该 token 值不一样,etcd 集群就不会相互影响。
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-token-1"

#初始化的时候,集群的状态:new 和 existing 两种状态。new代表新建的集群,existing 代表加入已经存在的集群
ETCD_INITIAL_CLUSTER_STATE="new"

# 这里只写了一个节点的配置文件作为示例,pg三个节点都要配置

5、启动etcd,在postgres账号下启动
启动之前检查一下时间是否同步,当各节点时间差大于1s时,etcd集群会报错,所以要配置时间同步服务器
这里的原则是谁先启动,谁就是etcd数据库主节点
su - postgres
etcd --config-file=/etc/etcd/etcd.conf 

注意,有的版本配置文件只能yaml格式(不知道为什么),如果是这种情况,直接在启动命令的命令行上指定参数,例如下面这样:
su - postgres
nohup etcd --name etcd-1 --initial-advertise-peer-urls http://192.168.167.11:2380 --listen-peer-urls http://0.0.0.0:2380 -data-dir /opt/etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://192.168.167.11:2379 --initial-cluster-state new --initial-cluster-token etcd-cluster-token-1 --initial-cluster etcd-1=http://192.168.167.11:2380,etcd-2=http://192.168.167.12:2380,etcd-3=http://192.168.167.13:2380 &
nohup etcd --name etcd-2 --initial-advertise-peer-urls http://192.168.167.12:2380 --listen-peer-urls http://0.0.0.0:2380 -data-dir /opt/etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://192.168.167.12:2379 --initial-cluster-state new --initial-cluster-token etcd-cluster-token-1 --initial-cluster etcd-1=http://192.168.167.11:2380,etcd-2=http://192.168.167.12:2380,etcd-3=http://192.168.167.13:2380 &
nohup etcd --name etcd-3 --initial-advertise-peer-urls http://192.168.167.13:2380 --listen-peer-urls http://0.0.0.0:2380 -data-dir /opt/etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://192.168.167.13:2379 --initial-cluster-state new --initial-cluster-token etcd-cluster-token-1 --initial-cluster etcd-1=http://192.168.167.11:2380,etcd-2=http://192.168.167.12:2380,etcd-3=http://192.168.167.13:2380 &

6、etcd常用运维命令
#查看集群状态
etcdctl cluster-health

eg:
[root@xl001 etcd]# etcdctl cluster-health
member 802aec41d9fb61a6 is healthy: got healthy result from http://192.168.167.11:2379
member b79cb086020dff09 is healthy: got healthy result from http://192.168.167.12:2379
member fec7c7f897b1265c is healthy: got healthy result from http://192.168.167.13:2379
cluster is healthy


#查看集群成员
etcdctl member list

eg:
[root@xl001 etcd]# etcdctl member list
802aec41d9fb61a6: name=etcd-1 peerURLs=http://192.168.167.11:2380 clientURLs=http://192.168.167.11:2379 isLeader=true
b79cb086020dff09: name=etcd-2 peerURLs=http://192.168.167.12:2380 clientURLs=http://192.168.167.12:2379 isLeader=false
fec7c7f897b1265c: name=etcd-3 peerURLs=http://192.168.167.13:2380 clientURLs=http://192.168.167.13:2379 isLeader=false


# 停止etcd 服务
ps -ef |grep etcd
kill -9 

etcdctl mkdir v   #创建目录v
etcdctl mkdir v/sub_v  #在目录v下创建目录sub_v
etcdctl rmdir v/sub_v    #删除目录
etcdctl mk v/sub_v/key1 value1  #在目录v/sub_v下创建键key1以及对应的值value1
etcdctl ls -r  #查看所有的目录及子目录以及所有目录和子目录下的键值对
etcdctl ls v/sub_v/  #查看 该目录下的所有键值对
etcdctl get v/sub_v/key1   #v/sub_v 目录下 key1键的值
etcdctl delete v/sub_v/key1  #删除键值对


7、如果中途出现了什么问题,想重新初始化etcd集群,可以这样做 
三个节点都做
1、停止etcd 服务
ps -ef |grep etcd
kill -9

2、删除etcd数据目录
rm -rf /opt/etcd/*

3、启动节点重新初始化集群
etcd --config-file=/etc/etcd/etcd.conf

三、安装patroni
3.1、安装python
patroni是用python写的一个组件,需要先安装python,然后再用python安装patroni这个包,三个节点都要安装python

python安装见我另一篇博客:
https://www.cnblogs.com/sunjiwei/articles/18066608

3.2、下面开始安装patroni
python3 -m pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple
python3 -m pip install --upgrade setuptools -i https://mirrors.aliyun.com/pypi/simple
python3 -m pip install psycopg2_binary==2.8.6 -i https://mirrors.aliyun.com/pypi/simple
python3 -m pip install patroni[etcd]==2.0.2 -i https://mirrors.aliyun.com/pypi/simple

# 查看patroni安装版本
patroni --version   #查看patroni 是否安装成功
如果报错:ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'OpenSSL 1.0.2k-fips  26 Jan 2017'. See: https://github.com/urllib3/urllib3/issues/2168
则执行   pip install urllib3==1.26.15 -i https://mirrors.aliyun.com/pypi/simple


# 查看patronictl是否可用
patronictl --help

如果报错:Traceback (most recent call last):
  File "./patronictl", line 5, in <module>
    from patroni.ctl import ctl
  File "/usr/local/python3.7.4/lib/python3.7/site-packages/patroni/ctl.py", line 33, in <module>
    from cdiff import markup_to_pager, PatchStream
ModuleNotFoundError: No module named 'cdiff'

则执行 pip install cdiff -i https://mirrors.aliyun.com/pypi/simple

3.3、编辑patroni配置文件
# patroni需要个rewind的账号,这个用户主要是用来主备切换时,timeline不一致的情况会用到
create user rewind_user encrypted password '111111';
这个账号要给相应的权限,或者直接使用postgres这个账号

mkdir /opt/patroni
chown -R postgres:postgres /opt/patroni

vim /etc/patroni.yml
scope: pg_cluster1             # 给集群起个名字
namespace: /service/           # 这个是etcd里会创建的目录,不配置的话默认就存储在/service,就用这个就行,
name: xl001                    # 节点名称,可以用主机名

restapi:
  listen: 0.0.0.0:8008
  connect_address: 192.168.167.11:8008   # 本节点ip:8008

etcd:
  #Provide host to do the initial discovery of the cluster topology:
  hosts: 192.168.167.11:2379,192.168.167.12:2379,192.168.167.13:2379

bootstrap:
  # this section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
  # and all other cluster members will use it as a `global configuration`
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 60000
    maximum_lag_on_failover: 1048576
    master_start_timeout: 300
    synchronous_mode: true
    postgresql:
      use_pg_rewind: true
      use_slots: false
      parameters:
        max_connections: 8000
        max_worker_processes: 16
        synchronous_commit: "on"
        wal_level: "logical"
        hot_standby: "on"
        wal_keep_segments: 5120
        max_wal_senders: 10
        max_replication_slots: 10
        wal_log_hints: "on"
        archive_mode: "on"
        archive_timeout: 1800s
  # 初始化数据库用,也可以手动初始化好数据库,不用patroni来初始化
  # initdb:
  # - encoding: UTF8
  # - locale: C
  # - lc-ctype: zh_CN.UTF-8
  # - data-checksums

	
postgresql:   
  listen: 0.0.0.0:5432
  connect_address: 192.168.167.11:5432
  data_dir: /opt/pgdata/data
  bin_dir: /usr/local/pgsql-12.6/bin
  config_dir: /opt/pgdata/data
  authentication:
    replication:
      username: repuser
      password: 111111
    superuser:
      username: postgres
      password: 111111
    #rewind:
      #username: rewind
      #password: 111111
   callbacks:
     on_start: /bin/bash /opt/patroni/pg_cluster1.vip
     on_restart: /bin/bash /opt/patroni/pg_cluster1.vip
     on_role_change: /bin/bash /opt/patroni/pg_cluster.vip


#watchdog:
#    mode: automatic # Allowed values: off, automatic, required
#    device: /dev/watchdog
#    safety_margin: 5



tags:
    nofailover: false
    noloadbalance: false
    clonefrom: false
    nosync: false


# 修改所属用户
chown postgres:postgres /etc/patroni.yml

三个节点都要配置,注意三个节点不同的参数是:
name: xl001
restapi里的 connect_address: 192.168.167.11:8008
postgresql 里的 connect_address: 192.168.167.11:5432



# 启动patroni
#要在 postgres 账号下 启动 
su - postgres
patroni /etc/patroni.yml > /opt/patroni/patroni.log 2>&1 &

#查看pg集群状态
patronictl -c /etc/patroni.yml list pg_cluster1


# 查看某个节点状态等信息
yum install jq -y   # jq,格式化输出json格式
curl -s http://192.168.167.161:8008 | jq

{
  "state": "running",
  "postmaster_start_time": "2023-09-27 10:44:33.542765+08:00",
  "role": "master",
  "server_version": 120015,
  "xlog": {
    "location": 167772160
  },
  "timeline": 1,
  "replication": [
    {
      "usename": "replica",
      "application_name": "ob11",
      "client_addr": "192.168.167.162",
      "state": "streaming",
      "sync_state": "async",
      "sync_priority": 0
    },
    {
      "usename": "replica",
      "application_name": "ob10",
      "client_addr": "192.168.167.161",
      "state": "streaming",
      "sync_state": "sync",
      "sync_priority": 1
    }
  ],
  "dcs_last_seen": 1695797837,
  "database_system_identifier": "7283070492616413950",
  "patroni": {
    "version": "3.0.4",
    "scope": "pg_cluster1"
  }
}

附上vip切换脚本,callbacks 那里要用到

vim /opt/patroni/cluster1.vip
#!/bin/bash
VIP=192.168.167.10
GATEWAY=192.168.167.254
DEV=bond0   # 网卡名称
action=$1
role=$2
cluster=$3
log()
{
  echo "recon: $*"|logger
}

load_vip()
{
ip a|grep -w ${DEV}|grep -w ${VIP} >/dev/null
if [ $? -eq 0 ] ;then
  log "vip exists, skip load vip"
else
  sudo ip addr add ${VIP}/24 dev ${DEV} label ${DEV}:2 >/dev/null
  rc=$?
  if [ $rc -ne 0 ] ;then
    log "fail to add vip ${VIP} at dev ${DEV} rc=$rc"
    exit 1
  fi

  log "added vip ${VIP} at dev ${DEV}"

  arping -U -I ${DEV} -s ${VIP} ${GATEWAY} -c 5 >/dev/null
  rc=$?
  if [ $rc -ne 0 ] ;then
    log "fail to call arping to gateway ${GATEWAY} rc=$rc"
    exit 1
  fi
  
  log "called arping to gateway ${GATEWAY}"
fi
}

unload_vip()
{
ip a|grep -w ${DEV}|grep -w ${VIP} >/dev/null
if [ $? -eq 0 ] ;then
  sudo ip addr del ${VIP}/24 dev ${DEV} label ${DEV}:2 >/dev/null
  rc=$?
  if [ $rc -ne 0 ] ;then
    log "fail to delete vip ${VIP} at dev ${DEV} rc=$rc"
    exit 1
  fi

  log "deleted vip ${VIP} at dev ${DEV}"
else
  log "vip not exists, skip delete vip"
fi
}

log "recon start args:'$*'"

case $action in
  on_start|on_restart|on_role_change)
    case $role in
      master)
        load_vip
        ;;
      replica)
        unload_vip
        ;;
      *)
        log "wrong role '$role'"
        exit 1
        ;;
    esac
    ;;
  *)
    log "wrong action '$action'"
    exit 1
    ;;
esac

注意:patroni 和 psycopg有可能出现版本不兼容的情况,导致patroni部署不成功,我自己测试是patroni2.0.2和psycopg2.9.9不兼容。
我测试可以的是 patroni2.0.2 和 psycopg2.8.6,patroni3.0.4 和 psycopg2.9.6这两个组合,python用的都是3.7.4版本。

四、一些说明
1、patroni 对数据库的侵入比较大,它会修改pg原有的配置文件(pg_hba.conf,postgresql.conf),把它们变成base.conf,然后根据patroni配置文件中的数据库参数自己生成一份新的配置文件,和老的配置文件一起组成数据库配置,新的配置文件优先级比老配置文件高。
2、patroni可以自己初始化数据库和部署流复制集群(不建议这样做),也可以自己部署好数据库和流复制集群,然后在此基础上部署patroni,这样的话patroni会重启备库(不会重启主库)

标签:http,--,数据库,192.168,2380,patroni,etcd,posgresql
From: https://www.cnblogs.com/sunjiwei/p/18527553

相关文章

  • Springboot游戏网站322mj(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,游戏信息,游戏分类,拍卖行,卖家,装备购买,游戏周边,周边购买,点卡充值,充值信息,处罚公示,处罚申诉,商品分类开题报告内容一、研究背景与意义随着信息技术......
  • 乐维CMDB:基于图数据库破除配置项关系管理难题
    在当今数字化飞速发展的时代,企业的IT架构日益复杂,如同一个庞大而精密的机器。其中,配置管理数据库(CMDB)作为IT运维管理的核心部分,承载着企业IT资源配置信息的管理重任。而在CMDB的范畴内,配置项管理和配置项关系管理则是重中之重,它们直接影响着企业IT系统的稳定运行、故障......
  • SpringBoot外卖服务系统k83px 本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:用户,商家,店铺信息,菜品分类,菜品信息,店铺公告开题报告内容一、研究背景与意义随着互联网技术的飞速发展,人们的生活方式正在发生深刻变革。在餐饮......
  • Springboot应急物资采购系统2548l(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,物资分类,物资商品,普通管理员开题报告内容一、研究背景与意义在当今社会,自然灾害、突发事件及公共卫生危机等不可预见事件频发,对社会的稳定与发展构成了......
  • 【含文档】基于ssm+jsp的茶产品销售平台(含源码+数据库+lw)
    1.开发环境开发系统:Windows10/11架构模式:MVC/前后端分离JDK版本:JavaJDK1.8开发工具:IDEA数据库版本:mysql5.7或8.0数据库可视化工具:navicat服务器:apachetomcat主要技术:Java,Spring,SpringMvc,mybatis,mysql,vue2.视频演示地址3.功能系统定义了两个......
  • 【含文档】基于ssm+jsp的NBA球队管理系统(含源码+数据库+lw)
    1.开发环境开发系统:Windows10/11架构模式:MVC/前后端分离JDK版本:JavaJDK1.8开发工具:IDEA数据库版本:mysql5.7或8.0数据库可视化工具:navicat服务器:apachetomcat主要技术:Java,Spring,SpringMvc,mybatis,mysql,vue2.视频演示地址3.功能系统定义了两个......
  • SpringBoot图书馆借阅管理系统49zr9 本系统(程序+源码+数据库+调试部署+开发环境)带论文
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:读者,图书分类,图书信息,图书借阅,图书归还,图书主题,出版时间,出版社分布,图书统计开题报告内容一、研究背景与意义随着信息技术的快速发展,图书馆作......
  • SpringBoot突发性疾病管理系统8bsf3 (程序+源码+数据库+调试部署+开发环境)带论文文档1
    题目:SpringBoot突发性疾病管理系统8bsf3进度安排:(1)2024年11月1日-2024年11月15日 确定选题,下达任务书,撰写开题报告;(2)2024年11月15日-2024年12月20日提交开题报告定稿;(3)2024年12月21日-2025年3月14日 完成选题的设计、论文大纲的撰写;(4)2025年3月15日-2025年3月21日  ......
  • SpringBoot头条资讯的设计与实现ja10r 本系统(程序+源码+数据库+调试部署+开发环境)
    开题报告内容一、项目背景随着信息化社会的快速发展,人们对新闻资讯的需求日益多样化和即时化。传统的新闻媒体已难以满足用户个性化、快速获取信息的需求,因此,头条资讯类应用应运而生。本项目旨在设计和实现一个高效、智能的头条资讯系统,以满足用户对高质量、个性化资讯的迫切......
  • 数据库原理 第五章 事务与并发控制
    目录1.事务的基本概念1.1为什么需要事务?什么是事务?1.2数据库事务的四大特性(ACID)1.3事务涉及的基本概念1.3.1 Transaction(事务)1.3.2. Rollback(回滚)1.33. Commit(提交)1.3.4. Savepoint(保存点)1.3.5关系总结1.4MySQL事务管理的完整示例示例:转账操作2.故障2.1故障的种类2.1.1. 数......