本文主要从以下几个方面介绍PostgreSQL高可用集群在360的落地实战

为什么选择Patroni + Etcd + PostgreSQL高可用集群方案

PostgreSQL高可用集群在360的落地实战 Patroni + Etcd 高可用集群架构解析

Patroni + Etcd + PostgreSQL 部署实战

Patroni 日常运维管理

PostgreSQL 监控实现

PostgreSQL 应用连接方式

PostgreSQL 备份恢复方式选择

背  景

最近线上重要业务容器云的镜像仓库需要部署一套postgresql 高可用集群,涉及到数据库选型,最终选择了postgresql,为什么不选择mysql呢,postgresql是功能最强大的开源数据库,主要考虑postgresql支持使用函数索引和条件索引,text 没有限制,可以索引,还可以全文检索,不用再接一套es,并且postgresql 开源协议好,开源软件原生支持好,特别对开发来说比较友好,最重要的是kube-bench 只支持postgresql。

为什么选择Patroni + Etcd 方案

PostgreSQL 比较流行的高可用解决方案有很多,常用的主要包含repmgr和patroni等,也是github star前几的高可用组件,并且文档更新比较及时,都可最高支持postgresql 13,repmgr 相对来说功能没有patroni全面以及不能检测备机是否被错误配置为未知或不存在的节点、不能检测远程节点的状态(不具备分布式解决方案)和不能处理单个节点的恢复,本文主要基于patroni 实现。

此方案使用Patroni管理本地库,并结合Etcd作为数据存储和主节点选举,具有以下优势:

  • 健壮性使用分布式key-value数据库作为数据存储,主节点故障时进行主节点重新选举,具有很强的健壮性

  • 支持多种复制方式基于内置流复制,支持同步流复制、异步流复制、级联复制

  • 支持主备延迟设置: 可以设置备库延迟主库WAL的字节数,当备库延迟大于指定值时不做故障切换

  • 自动化程度高:

  1. 支持自动化初始PostgreSQL实例并部署流复制

  2. 当备库实例关闭后,支持自动拉起

  3. 当主库实例关闭后,首先会尝试自动拉起

  4. 支持switchover命令,能自动将老的主库进行角色转换

  • 避免脑裂: 数据库信息记录到ETCD 中,通过优化部署策略(多机房部署、增加实例数)可以避免脑裂

Patroni + Etcd 高可用架构

Patroni 是一个开源工具套件,它是用 Python编写的,可确保 PostgreSQL HA 集群的端到端设置,包括流复制。它的功能通过REST API显示,也通过一个名为 Patronictl 的命令行实用程序显示。它通过使用其运行状况检查API来处理负载平衡来支持与 HAProxy 的集成。在此 HA 解决方案中,etcd 用于分布式配置存储 (DCS),以实现最大的可访问性,下面是官方高可用集群方案的架构图展示,我们基于此完成postgresql 高可用架构集群方案设计,不过并没有使用HAproxy 进行负载均衡,而是使用公司内部的LVS 来实现的,一主两副本,副本部署在不同的idc 实现异地灾备,etcd 也是三节点集群分别部署在三台机器, 如果资源有限,也可以和postgresql/patroni部署在相同机器。

Etcd、Patroni 和PostgreSQL是如何一起工作的

etcd/patroni/postgresql 都是部署的3节点集群

Etcd: 分布式的Key-Value数据库

etcd1、etcd2、 etcd3作为分布式的Key-Value数据库,被partroni1、 patroni2、 patroni3读/写,用于共享/传递信息。每一个 Patroni都能读/写etcd中的数据。

Paroni: 控制/监控本地的PostgreSQL, 把本地PostgreSQL信息/状态写入etcd

每一个 Patroni实例监控/控制本地的PostgreSQL,把本地本地PostgreSQL信息/状态写入etcd , 一个Patroni实例能够通过读取etcd获取外地PostgreSQL的信息/状态。

PostreSQL主节点的选举

Patroni判断本地PostgreSQL是否可以作为Primary库。如果可以,Paroni试图选举本地PostgreSQL作为Primary(Leader) , 选举方式是:把etcd中的某个key更新成为本地PostgreSQL的名字, 如果多个Paroni同时更改同一个key,只有一个能改成功,然后成为Primary(Leader)。

部署篇

系统/软件/版本

· CentOS 7.4

· PostgreSQL 12.6

· etcd: 3.2.18

· python: Python 3.6.5

· Patroni: 2.1.0

主机信息

10.16.75.17  pg12/patroni

10.16.75.15  pg12/patroni

10.16.78.53   pg12/patroni

10.24.13.9   etcd

10.24.13.10  etcd

10.24.13.11  etcd

这里用了6台机器,也可以用3台机器组件全部安装在一起

Python3 安装

# 安装依赖

yum install wget gcc make zlib-devel openssl openssl-devel

wget "https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tar.xz"

tar -xvJf Python-3.6.5.tar.xz

# 编译

cd Python-3.6.5 && ./configure prefix=/usr/local/python3

make && make install

ln -fs /usr/local/python3/bin/python3 /usr/bin/python3

ln -fs /usr/local/python3/bin/pip3 /usr/bin/pip3

# virtualenv

pip3 install virtualenv -i https://mirrors.ustc.edu.cn/pypi/web/simple/

ln -fs /usr/local/python3/bin/virtualenv /usr/bin/virtualenv

# 编译安装python的使用

cd /data04 && virtualenv venv4archery --python=python3

# 切换python运行环境到虚拟环境

source venv4archery/bin/activate

创建PG目录和用户

useradd postgres #编译安装的,yum 安装不用创建

mkdir -p /data04/pg15432

mkdir -p /data04/pg15432/data

mkdir -p /data04/pg15432/scripts

chown -R postgres:postgres /data04/pg15432/

创建归档目录

mkdir -p /data04/pg15432/arch

源码安装postgresql12

yum -y install -y readline-devel

mkdir -p /usr/local/pgsql/

./configure --prefix=/usr/local/pgsql

make && make install

cp /usr/local/pgsql/bin/* /sbin/

Etcd 部署

yum install etcd -y

编辑/etc/etcd/etcd.conf 配置文件

Etcd node1配置

ETCD_DATA_DIR="/var/lib/etcd/codis.etcd"

ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_NAME="node1"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.24.13.9:2380"

ETCD_ADVERTISE_CLIENT_URLS="http://10.24.13.9:2379"

ETCD_INITIAL_CLUSTER="node1=http://10.24.13.9:2380,node2=http://10.24.13.10:2380,node3=http://10.24.13.11:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

Etcd node2 配置

ETCD_DATA_DIR="/var/lib/etcd/codis.etcd"

ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_NAME="node2"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.24.13.10:2380"

ETCD_ADVERTISE_CLIENT_URLS="http://10.24.13.10:2379"

ETCD_INITIAL_CLUSTER="node1=http://10.24.13.9:2380,node2=http://10.24.13.10:2380,node3=http://10.24.13.11:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

Etcd node3 配置

ETCD_DATA_DIR="/var/lib/etcd/codis.etcd"

ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"

ETCD_NAME="node3"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.24.13.11:2380"

ETCD_ADVERTISE_CLIENT_URLS="http://10.24.13.11:2379"

ETCD_INITIAL_CLUSTER="node1=http://10.24.13.9:2380,node2=http://10.24.13.10:2380,node3=http://10.24.13.11:2380"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_INITIAL_CLUSTER_STATE="new"

#注意etcdnode1 每个节点都不一样,etcd-cluster-1 是集群名字统一

systemctl daemon-reload

systemctl enable etcd

systemctl start etcd

Etcd 成员列表显示

etcdctl member list

Etcd集群健康检查

etcdctl --endpoints http://10.24.13.9:2379 cluster-health

Patronic 部署

cd /data04 && virtualenv venv4archery --python=python3

source venv4archery/bin/activate

pip3 install psycopg2-binary -i https://mirrors.aliyun.com/pypi/simple/

或者pip3 install psycopg2>=2.5.4 -i https://mirrors.aliyun.com/pypi/simple/

pip3 install  patroni[etcd,consul,zookeeper,kubernetes] -i https://mirrors.aliyun.com/pypi/simple/

#启动patroni集群需非root用户

集群进行初始化所有节点执行

patroni /etc/patroni.yml  > patroni_member_1.log 2>&1 &

可以使用centos7的service启动:

[Unit]

Description=Runners to orchestrate a high-availability PostgreSQL

After=syslog.target network.target

[Service]

Type=simple

User=postgres

Group=postgres

#StandardOutput=syslog

ExecStart=/sbin/patroni /etc/patroni.yml

ExecReload=/bin/kill -s HUP $MAINPID

KillMode=process

TimeoutSec=30

Restart=no

[Install]

WantedBy=multi-user.target

/etc/patroni.yml (可根据自己需求定制化

scope: postgresql

namespace: /service/

name: postgresql1

restapi:

listen: 10.16.75.17:8008

connect_address: 10.16.75.17:8008

etcd:

host: 10.24.13.9:2379

host: 10.24.13.10:2379

host: 10.24.13.11:2379

bootstrap:

dcs:

ttl: 30

loop_wait: 10

retry_timeout: 10

maximum_lag_on_failover: 1048576

postgresql:

use_pg_rewind: true

use_slots: true

parameters:

listen_addresses: "0.0.0.0"

                wal_level: logical   

 archive_mode: "on"    

                max_connections: 6000

                Shared_buffers: 32GB

archive_command: 'DATE=`date +%Y%m%d`;DIR="/data04/pg15432/arch/$DATE";(test -d $DIR || mkdir -p $DIR)&& cp %p $DIR/%f'

hot_standby: "on"

wal_keep_segments: 100

max_wal_senders: 10

max_replication_slots: 10

wal_log_hints: "on"

initdb:

- encoding: UTF8

- data-checksums

pg_hba:

- host replication repl 127.0.0.1/32 md5

- host replication repl 10.16.75.17/0 md5

- host replication repl 10.16.75.15/0 md5

- host replication repl 10.206.87.218/0 md5

- host replication repl 0.0.0.0/0 md5

- host all all 0.0.0.0/0 md5

users:

admin:

password: admin

options:

- createrole

- createdb

postgresql:

listen: 10.16.75.17:15432

connect_address: 10.16.75.17:15432

bin_dir: /usr/local/pgsql/bin

data_dir: /data04/pg15432/data

pgpass: /tmp/pgpass1

authentication:

replication:

username: repl

password: "1a23s6c54f"

superuser:

username: postgres

password: "59687411134be622"

parameters:

unix_socket_directories: '.'

synchronous_commit: "on"

synchronous_standby_names: "*"

tags:

nofailover: false

noloadbalance: false

clonefrom: false

nosync: false

重点关注上面标红的参数设置,如果初始化未设置也没关系,部署完成一定验证下重要参数设置,未设置的可以通过patronictl 进行设置。

PG集群信息查看

数据库账户创建

CREATE USER docker WITH PASSWORD 'xxxx';

CREATE DATABASE docker OWNER docker;

GRANT ALL PRIVILEGES ON DATABASE docker to docker;

远程连接数据库

psql -U docker -d docker -p xxxx-h xxxx

尝试对主节点进行读写

以上完成对整个集群的部署并确保数据库可以正常进行读写

Patronictl 日常运维

参数设置查看


shared_buffers

类似mysql innodb_buffer_pool_size,该参数主要设置数据库服务器将使用的共享内存缓冲区量,建议是设置系统内存的25%,过高也会造成一些工作负载,还是需要跟业务沟通获取预估的数据量以及估算热数据量来针对性制定参数值。


修改shared_buffers

patronictl -c /etc/patroni.yml edit-config -p "shared_buffers='32GB'"

patronictl -c /etc/patroni.yml restart postgresql (重启生效)

max_connections

决定数据库的最大并发连接数。默认值通常是 100 个连接,但是如果内核设置不支持(initdb时决定),可能会比这个 数少。这个参数只能在服务器启动时设置。

当运行一个后备服务器时,你必须设置这个参数等于或大于主服务器上的参数。否则,后备服务器上可能无法允许查询。

修改max_connections

patronictl -c /etc/patroni.yml edit-config -p 'max_connections=6000'

patronictl -c /etc/patroni.yml restart postgresql (重启生效)

查看当前归档日志

select pg_walfile_name(pg_current_wal_lsn());

手动切换归档

select pg_walfile_name(pg_current_wal_lsn());

可以看到归档已经由...0000B 切换到...0000C

设置开启慢日志

阈值为200ms

patronictl -c /etc/patroni.yml edit-config -p 'log_min_duration_statement=200'

查看慢日志设置阈值

 

高可用故障转移测试

Kill 主节点进程

会发现patroni 会自动拉起postgresql进程,并且还是主节点,并未进行切主

手工切主

假设切主到postgresql2 155节点

patronictl -d etcd://10.16.75.17:2379 switchover postgresql

切主期间会出现中间状态unknown,瞬间会恢复正常如下,切主成功到155。

重启集群

可看到主节点也是没切主,拓扑和以前是一样的。

主/从节点机器重启

机器宕机是常有的事情,当postgresql 某个节点所在机器宕机恢复后,需要手动拉起节点 patroni /etc/patroni.yml  > patroni_member_1.log 2>&1 &

禁用开启故障转移

当pause 后,这时候集群是不会进行自动故障转移的,可以在某些特定场景使用,然后用resume 恢复就可以了。

还有其它一些功能可以参考patronictl --help

PostgreSQL监控

监控是眼睛,对于运维来说非常重要,这边主要采用的是Grafana + Prometheus 监控PostgreSQL,自带PG监控指标模版,也可自己定制详尽指标,结合内部告警平台编写api 实现告警短信发送以及推推内部沟通软件推送,具体部署这里就不详细阐述了,监控界面如下:

监控参考:

https://www.bbsmax.com/A/pRdBKG0Pzn/

dashboard json 下载模版

https://grafana.com/grafana/dashboards?search=postgresql&orderBy=reviewsCount&direction=desc

下载好json 文件直接在dashboard倒入模版即可

监控指标rules 可自己定制,可选择常用的,比较重要的指标即可

应用连接方式

这边采用的是公司内部的lvs机制,通过挂载vip的方式来实现读写分离,也可以通过haproxy 等组件来实现负载均衡,多一层组件就会多一层故障点,同样需要保证高可用,可根据业务重要程度进行抉择。

PostgreSQL 备份

PostgreSQL流复制备份可选择物理备份或者逻辑备份,逻辑备份可选择pg_dump 进行单表备份或者pg_dumpall进行全库备份,物理备份可选择pg_basebackup 或者pg_rman 备份,在此我选择pg_rman 进行备份,下面重点介绍下强大的pg_rman 备份工具。

pg_rman是一个开源的PostgreSQL备份管理软件,类似Oracle的RMAN,使用的是pg_start_backup(), copy, pg_stop_backup()的备份模式,pg_rman跑的不是流复制协议,而是文件拷贝,所以pg_rman必须和数据库节点跑在一起,如果在standby节点运行pg_rman,pg_rman则需要通过网络连接到主节点执行pg_start_backup/pg_stop_backup。

pg_rman可支持的主要功能如下:

  • 全量备份

  • 增量备份

  • 检验备份集

  • 列出备份集

  • 按指定时间从catalog 删除备份集

  • 物理删除已从catalog删除的备份集

相信用过oracle的同学了解oracle rman 备份的强大就清楚pg_rman 的功能强大之处,具体可参考http://mysql.taobao.org/monthly/2016/09/05/

未来展望

PostgreSQL 在最新的数据库DB-Engines 9月榜单高居第四,是功能最强大的开源数据库,增势迅速,稳定性极强,特别是在GIS领域处于优势地位,有丰富统计函数和统计语法支持对开发特别友好,而且高可用复制架构越来越完善,相信在不久的将来在国内应用会越来越广泛。

PostgreSQL高可用集群在360的落地实战相关推荐

  1. PostgreSQL高可用集群

    一主两从+haproxy IP地址.端口.版本号根据自身的服务器和要求来改变 架构图 服务器配置 服务器四台 (192.168.0.78 192.168.0.79 192.168.0.80 192.1 ...

  2. linux集群管理平台,基于Linux平台的高可用集群管理系统的研究与实现

    摘要: 集群管理系统的高可用性是指其能够连续地对外提供服务,本文针对集群系统的高可用性,以开源的集群搭建和管理软件KUSU为基础,以集群管理节点的双机热备份技术理论为支撑,以实现集群系统的帮障检测与业 ...

  3. Kubernetes容器集群 - harbor仓库高可用集群部署说明

    之前介绍Harbor私有仓库的安装和使用,这里重点说下Harbor高可用集群方案的部署,目前主要有两种主流的Harbor高可用集群方案:1)双主复制:2)多harbor实例共享后端存储. 一.Harb ...

  4. 【参赛作品66】快速搭建一套openGauss主备高可用集群

    作者:Sally openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行.openGauss内核早期源自PostgreSQL,深度融合华为在数据库领域多年的经验,结合企业级场景需 ...

  5. Postgresql12+Pgpool-ii 4.1高可用集群

    Postgresql12+Pgpool-ii 4.1高可用集群 注意 原文链接 postgresql12主从复制链接 一.方案 1.1 方案效果 1.1 主机配置 二.安装 2.1 postgresq ...

  6. 安排,谷粒商城java分布式开发基础篇高级篇与高可用集群架构篇2020

    来源: 来自网络,如侵权请告知博主删除????. 仅学习使用,请勿用于其他- 最近有小伙伴管我要分布式这类的项目,还有一些要商城的,还有要springboot,springcloud,k8s等,几乎涵 ...

  7. 使用RKE部署Rancher v2.5.8 HA高可用集群

    文章目录 一 了解 Rancher 1 关于Helm 2 关于RKE 3 关于K3S 4 Rancher 名词解释 4.1 仪表盘 4.2 项目 4.3 多集群应用 4.4 应用商店 4.5 Ranc ...

  8. [转]HA高可用集群中“脑裂“问题解决

    什么是脑裂(split-brain) 在"双机热备"高可用(HA)系统中,当联系两个节点的"心跳线"断开时(即两个节点断开联系时),本来为一个整体.动作协调的H ...

  9. 数据库系列之SequoiaDB高可用集群部署(一)

    SequoiaDB作为存储引擎,支持高并发的HTAP场景.本位总结运维分析项目中使用SequoiaDB作为数据存储的高可用部署实战,并接入Kafka进行高并发的更新业务和Spark进行高并发的批量查询 ...

最新文章

  1. cannot reshape array of size 5011 into shape (2)
  2. Lync 2010迁移Lync 2013 PART8:部署新边缘
  3. 【Tika基础教程之一】Tika基础教程
  4. requireJS和seajs区别?
  5. 两点(51nod 深搜)
  6. Android之面试题总结加强版(一)
  7. java阴阳师抽卡概率_《阴阳师》公布抽卡概率!看到数字我哭了
  8. LeetCode MySQL 1747. 应该被禁止的Leetflex账户
  9. 勇于尝鲜,感受世界——对话阿里云 MVP黄坤
  10. ViewBag ViewData
  11. silverlight计时器
  12. $(document).ready
  13. 标准工时分析软件VIOOVI,适配现代化工业的人工智能软件
  14. 归并排序java(内附超详解图文讲解)
  15. 财务报表分析,Smartbi财务BI项目解决方案
  16. 360手机助手pc版 v2.4.0.1265 官方版
  17. visio2013如何画箭头
  18. android客户端同php服务端进行XML/JSON通信
  19. 修改win10 ntp服务器地址,修改win10 ntp服务器地址
  20. 编程中键盘KeyCode对照表

热门文章

  1. Python 分布式文件系统 Mongodb GridFS
  2. spark数据本地性级别划分
  3. java 备份 mysql 日志_MySQL 数据备份与还原
  4. mysql数据库连接配置路径_关于mysql安装后更改数据库路径方法-linux环境
  5. python下载包突然卡住_【python】python下载视频为什么会卡?
  6. 二叉搜索树的思想,以及增删查改的实现
  7. Docker制作镜像(四)
  8. zookeeper和Kafka的关系
  9. 超详细:Springboot连接centos7下redis6的必要配置和失败分析
  10. TIME_WAIT和CLOSE_WAIT