postgres12 读写分离

文章概览


在这里插入图片描述


docker实现 pgpool+postgres 高可用、读写分离,代码已放到我的github上:
https://github.com/guozizi/pg_cluster.

可以拉下来对照文章自己试试


介绍

pgpool-II

pgpool-II是位于 PostgreSQL 服务器和 PostgreSQL 数据库客户端之间的中间件,也是现在比较成熟的读写分离的中间件

在这里插入图片描述

高可用

pgpool可以管理多台postgres实例,一个主节点带多个从节点进行实时备份,当主节点下线,从节点提供服务,服务不会被中断

读写分离

在主从模式下,写请求只发给主节点,读请求可以发给任何一个节点。在高并发的场景下,由于从服务分担了一部分读请求,可以使系统整体的吞吐量提升

连接池

pgpool连接池自动管理连接对象的创建和释放,可以减少内存开销,提高运行速度。当超过最大连接数,会将连接放入队列,而不是立即返回错误

postgres流复制

实现原理

1、主库启动walsender进程将WAL数据发送到备库
2、备节点启动一个walreceiver和一个startup进程接受和重放数据

在这里插入图片描述

搭建流程

思路:先搭建postgres主从复制,再加入pgpool进行管理

环境准备

系统:ubuntu 18.04
软件:docker、docker-compose安装

# 容器ip
postgres:172.80.0.2
postgres_standby:172.80.0.3
pgpool:172.80.0.4

postgres主从搭建

主节点(postgres :172.80.0.2)

Dockerfile 配置

1、更换国内镜像源
2、修改postgres源镜像的docker-entrypoint.sh
3、修改配置postgresql.conf配置文件
4、 加入主节点配置脚本primary.sh


FROM postgres:12.2

# 更换国内镜像源
COPY sources.list /etc/apt/sources.list
RUN apt-get update \
    && apt-get install -y vim

# https://github.com/docker-library/postgres/tree/17c71aef1940ef0d2cc8bdc8bf7fb0a2856c8326/12
# 基于原镜像 docker-entrypoint.sh 做出来需更改权限
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \
    && chmod 777 /docker-entrypoint.sh

# postgres 配置文件
COPY postgresql.conf /etc/postgresql/postgresql.conf
RUN chown -R postgres:postgres /etc/postgresql/postgresql.conf

# postgres 主节点配置脚本
COPY primary_deploy.sh /primary_deploy.sh
RUN chmod 777 /primary_deploy.sh

ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 5432
CMD ["postgres"]

第2步的原因:postgres12.2的源镜像包含docker-entrypoint.sh脚本,导致无法加一些外部命令,dockerfile中ENTRYPOINTCMD同时存在时CMDENTRYPOINT的可选参数,因此修改docker-entrypoint.sh扩展自定义功能


docker-entrypoint.sh

postgres源镜像使用docker-entrypoint.sh脚本初始化数据库
自定义功能:在docker-entrypoint.sh加入一条执行主从相关配置脚本的命令,在postgres服务起来之后在后台运行

在这里插入图片描述
primary_deploy.sh

1、创建同步数据的用户
2、允许从数据库连接到主节点
3、重新加载配置

#!/bin/bash
sleep 10s  # 等服务起来

STANDBY_IP="172.80.0.3"
PGDATA="/var/lib/postgresql/data"

# 判断是否已经为主从复制的状态
OUTPUT="$(psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='replicator'")"
if  [ "${OUTPUT}" != "1" ]; then
  # 创建用户
  psql -U postgres -c "CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'secret';"
  # 允许从数据库连接到主节点
  echo "host replication replicator $STANDBY_IP/16 md5" >> $PGDATA/pg_hba.conf
  # 重新加载配置
  psql -U postgres -c "select pg_reload_conf()"
fi

从节点(postgres_standby :172.80.0.3)

Dockerfile 配置

1、更换国内镜像源
2、配置root用户ssh免密(与pgpool容器免密)
3、修改postgres源镜像的docker-entrypoint.sh
4、修改配置postgresql.conf配置文件
5、加入主节点配置脚本primary.sh

FROM postgres:12.2
# 更换国内镜像源
COPY sources.list /etc/apt/sources.list

RUN apt-get update \
    && apt-get install -y vim \
    && apt-get install -y openssh-server
    
# ssh 免密
RUN mkdir /root/.ssh/ \
    &&touch /root/.ssh/authorized_keys
COPY id_rsa  /root/.ssh/id_rsa
COPY id_rsa.pub /root/.ssh/id_rsa.pub
COPY sshd_config /etc/ssh/sshd_config

COPY id_rsa.pub.pgpool  /root/.ssh/authorized_keys
RUN chmod 400 /root/.ssh/authorized_keys

# https://github.com/docker-library/postgres/tree/17c71aef1940ef0d2cc8bdc8bf7fb0a2856c8326/12
# 基于原镜像 docker-entrypoint.sh 做出来需更改权限
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod 777 /usr/local/bin/docker-entrypoint.sh \
    && chmod 777 /docker-entrypoint.sh
    
# postgres 配置文件
COPY postgresql.conf /etc/postgresql/postgresql.conf
RUN chown -R postgres:postgres /etc/postgresql/postgresql.conf

# postgres 从节点配置脚本
COPY standby_deploy.sh /standby_deploy.sh
RUN chmod 777 /standby_deploy.sh

# 设置root密码为"root"
RUN echo "root:root" | chpasswd

EXPOSE 5432

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]


docker-entrypoint.sh

postgres源镜像使用docker-entrypoint.sh脚本初始化数据库
自定义功能:在docker-entrypoint.sh加入一条执行主从相关配置脚本的命令

在这里插入图片描述
standby_deploy.sh 脚本

1、开启ssh服务
2、连接主库做基础备份

#!/bin/bash
# 使用root用户执行命令
echo "root" | su - root /etc/init.d/ssh start

# 等主服务配置好
sleep 20s

PRIMARY_IP="172.80.0.2"
PGDATA="/var/lib/postgresql/data"

if [ ! "$(ls -A $PGDATA)" ];then
      export PGPASSWORD=secret && pg_basebackup -h $PRIMARY_IP -U replicator -p 5432 -D $PGDATA -Fp -Xs -P -R
fi

pgpool-II搭建

Dockerfile 配置

1、更换国内镜像源
2、配置ssh免密 (与postgres_standby容器免密)
3、修改pgpool源镜像文件pgpool_setup.sh
4、加入failover高可用脚本failover.sh

FROM postdock/pgpool:latest

COPY sources.list /etc/apt/sources.list
RUN apt-get update \
    && apt-get install -y vim \
    && apt-get install -y openssh-server

# postgres用户ssh免密
RUN mkdir -p /home/postgres/.ssh/
COPY id_rsa  /home/postgres/.ssh/id_rsa
COPY id_rsa.pub /home/postgres/.ssh/id_rsa.pub
COPY sshd_config /etc/ssh/sshd_config

RUN chown -R postgres:postgres /home/postgres/.ssh
RUN chmod 600 /home/postgres/.ssh/id_rsa

# 将failover_command设置为evn变量
COPY pgpool_setup.sh /usr/local/bin/pgpool/pgpool_setup.sh

# 配置failover脚本(主节点下线从节点升为主节点)
COPY failover.sh /usr/local/etc/failover.sh
RUN chmod 777 /usr/local/etc/failover.sh

RUN mkdir /run/sshd
CMD /etc/init.d/ssh start && bash /usr/local/bin/pgpool/entrypoint.sh

第3步的原因: pgpool_setup.sh脚本可设置evn参数,并将配置写入到pgpool.conf,传参只需要docker-compose.yml的environment设置就可以

pgpool_setup.sh

自定义加入FAILOVER_COMMAND EVN,并写入pgpool.conf

在这里插入图片描述
docker-compose.yml 的配置

environment :配置环境变量作用到pgpool.conf
同时也可以看到在pgpool_setup.sh加入的FAILOVER_COMMAND,可以直接在environment配置

在这里插入图片描述
failover.sh

主节点下线,从节点升为主节点继续提供服务

# node 0 is primary, and 1 is standby
new_primary=$1
falling_node=$2
if [ $falling_node = 1 ]; then
        exit
fi
ssh -tt -o StrictHostKeyChecking=no root@$new_primary "psql -U postgres -c \"select pg_promote(true,60)\""

测试

postgrs流复制

docker exec -it postgres /bin/sh -c "psql -U postgres -x -c \"select * from pg_stat_replication\""

可以看到主从流复制搭建成功
在这里插入图片描述

pgpool-II
docker exec -it pgpool bash
export PGPASSWORD=pg_pwd && psql -h localhost -p 5432 -U postgres postgres -c "show pool_nodes"

可以看到pgpool管理的主从服务都已提供服务

在这里插入图片描述

注:环境搭建好之后,客户端连接pgpool发出请求,由pgpool分发到各个节点

pgpool读写分离

连接pgpool 写入和读取一些数据

docker exec -it pgpool bash
export PGPASSWORD=pg_pwd && echo "create table test01(id int primary key, name varchar(20))" | psql -h localhost -p 5432 -U postgres && echo "INSERT INTO test01 (id, name) VALUES (1, 'gzj01')" | psql -h localhost -p 5432 -U postgres && echo "INSERT INTO test01 (id, name) VALUES (2, 'gzj02')" | psql -h localhost -p 5432 -U postgres && echo "SELECT * FROM test01" | psql -h localhost -p 5432 -U postgres && echo "SELECT name FROM test01" | psql -h localhost -p 5432 -U postgres && echo "SELECT * FROM test01 WHERE name='gzj01'" | psql -h localhost -p 5432 -U postgres

在这里插入图片描述
查看主库postgres的日志
可以看到写请求都往主库上发,同时也可以接收查询请求

在这里插入图片描述
查看从库postgres_standby日志
可以看到从库也接收查询请求

在这里插入图片描述

pgpool高可用

试试把主节点postgres下线
可以看到主节点下线,从节点自动升为主机节点提供服务

在这里插入图片描述

总结

在定制镜像时我们会在Dockefile FROM 指定一个基础镜像,可以先去dockerhub看看基础镜像的Dockerfile实现,可以避免后期出现一些奇怪的问题,也可以更灵活的定制自己的镜像。总之,多看官方镜像还是有很多益处


欢迎关注公众号,一起学习交流

在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值