金鑫工程师 2019-04-10 07:12:47 浏览 101 评论 0
云栖社区
编程语言
Linux
大数据
Java 核心技术
算法
java
docker
服务器
MySQL
Ubuntu
日志
高可用
数据库
集群
摘要: 有了 docker 虚拟机, 就需要利用平台部署数据库的集群, 在实际操作之前介绍下数据库集群的方案和各自的特点.
有了 docker 虚拟机, 就需要利用平台部署数据库的集群, 在实际操作之前介绍下数据库集群的方案和各自的特点. 源码:
集群的方案
单节点的弊病
大型互联网程序用户群体庞大, 所以架构必须要特殊设计
单节点的数据库无法满足性能的要求
案例 15 年前, 高考成绩可以在网上查(河南几十万考生), 那时候基本家里都没电脑, 都是去网吧白天去网吧也查不了, 太慢了, 后来半夜通宵有时候可以查到, 也就是说白天基本查不了人太多了. 晚上看运气. 一个数据库的实例 1 万多人就无法反应了.
单节点的数据库没有冗余设计, 无法满足高可用
常用的 MySQL 集群设计方案
Replication
速度快
弱一致性
低价值
场景: 日志, 新闻, 帖子
PXC
速度慢
强一致性
高价值
场景: 订单, 账户, 财务
Percona Xtradb Cluster, 简称 PXC. 是基于 Galera 插件的 MySQL 集群. 相比那些比较传统的基于主从复制模式的集群架构 MHA 和 MM+keepalived,galera cluster 最突出特点就是解决了诟病已久的数据复制延迟问题, 基本上可以达到实时同步. 而且节点与节点之间, 他们相互的关系是对等的. 大数据学习扣 qun74 零零加[41 三八 yi] 本身 galera cluster 也是一种多主架构. galera cluster 最关注的是数据的一致性, 对待事物的行为时, 要么在所有节点上执行, 要么都不执行, 它的实现机制决定了它对待一致性的行为非常严格, 这也能非常完美的保证 MySQL 集群的数据一致性. 在 PXC 里面任何一个节点都是可读可写的. 在其他的节点一定是可以读取到这个数据.
建议 PXC 使用 PerconaServer(MySQL 的改进版, 性能提升很大)
PXC 方案和 Replication 方案的对比
PXC 任意一个节点都可以存在读写的方案, 也就是任意一个节点都可以当读或者当写. 同步复制. 保证强一致性.
Replication 方案, 主从的方式, 他是采用异步的方式.
PXC 的数据强一致性
同步复制, 事务在所有节点要提交都提交. 要么都不提交
Replication 弱一致性, 主要 master 成功就成功了. 返回给调用者. 如果 slave 失败, 也没办法. 因为已经告诉调用者成功了, 调用者获取查询的时候查询不到信息. 例如: 在淘宝买个东西, 付款也成功了, 查询订单没信息是不是要骂娘.
环境搭建
应用 IP 地址 服务 配置 安装应用 安装方式
docker-MySQL 192.168.66.100 docker-MySQL 双核 8g 内存 docker-MySQL docker
(1). 虚拟机 Vagrant 讲述安装的步骤
Vagrant up
(2). 机器 Windows/Mac 开通远程登录 root 用户下
su -
密码
Vagrant
设置 PasswordAuthentication yes
- vi /etc/SSH/sshd_config
- sudo systemctl restart sshd
PXC 集群安装介绍
PXC 既可以在 Linux 系统安装, 也可以在 docker 上面安装.
安装镜像 PXC 镜像
docker pull percona/percona-xtradb-cluster
本地安装
docker load /soft/pxc.tar.gz
创建内部网络的
处于安全, 需要给 PXC 集群实例创建 Docker 内部网络, 都出可虚拟机自带的网段是 172.17.0., 这是内置的一个网段, 当你创建了网络后, 网段就更改为 172.18.0.,
- docker network create net1
- docker network inspect net1
- docker network rm net1
设置网段
docker network create --subnet=172.18.0.0/24 net1
创建 Docker 卷
一旦生成 docker 容器, 不要在容器内保存业务的数据, 要把数据放到宿主机上, 可以把宿主机的一个目录映射到容器内, 如果容器出现问题, 只需要吧容器删除, 重新建立一个新的容器把目录映射给新的容器.
之前一直有个疑问, 如果直接映射目录的吧, 存在失败的问题, 现在终于知道解决方案了, 直接映射 docker 卷就可以可以忽略这个问题了.
容器中的 PXC 节点映射数据目录的解决方法
docker volume create name --v1
MySQL pxc 搭建
脚本开发
- !/bin/bash
- echo "创建网络"
- docker network create --subnet=172.18.0.0/24 net1
- echo "创建 5 个 docker 卷"
- docker volume create v1
- docker volume create v2
- docker volume create v3
- docker volume create v4
- docker volume create v5
- echo "创建节点 node1"
- docker run -d -p 3306:3306 --net=net1 --name=node1 \
- -e CLUSTER_NAME=PXC \
- -e MYSQL_ROOT_PASSWORD=a123456 \
- -e XTRABACKUP_PASSWORD=a123456 \
- -v v1:/var/lib/MySQL \
- --privileged \
- --ip 172.18.0.2 \
- percona/percona-xtradb-cluster
- sleep 1m
- echo "创建节点 node2"
- docker run -d -p 3307:3306 --net=net1 --name=node2 \
- -e CLUSTER_NAME=PXC \
- -e MYSQL_ROOT_PASSWORD=a123456 \
- -e XTRABACKUP_PASSWORD=a123456 \
- -e CLUSTER_JOIN=node1 \
- -v v2:/var/lib/MySQL \
- --privileged \
- --ip 172.18.0.3 \
- percona/percona-xtradb-cluster
- sleep 1m
- echo "创建节点 node3"
- docker run -d -p 3308:3306 --net=net1 --name=node3 \
- -e CLUSTER_NAME=PXC \
- -e MYSQL_ROOT_PASSWORD=a123456 \
- -e XTRABACKUP_PASSWORD=a123456 \
- -e CLUSTER_JOIN=node1 \
- -v v3:/var/lib/MySQL \
- --privileged \
- --ip 172.18.0.4 \
- percona/percona-xtradb-cluster
- sleep 1m
- echo "创建节点 node4"
- docker run -d -p 3309:3306 --net=net1 --name=node4 \
- -e CLUSTER_NAME=PXC \
- -e MYSQL_ROOT_PASSWORD=a123456 \
- -e XTRABACKUP_PASSWORD=a123456 \
- -e CLUSTER_JOIN=node1 \
- -v v4:/var/lib/MySQL \
- --privileged \
- --ip 172.18.0.5 \
- percona/percona-xtradb-cluster
- sleep 1m
- echo "创建节点 node5"
- docker run -d -p 3310:3306 --net=net1 --name=node5 \
- -e CLUSTER_NAME=PXC \
- -e MYSQL_ROOT_PASSWORD=a123456 \
- -e XTRABACKUP_PASSWORD=a123456 \
- -e CLUSTER_JOIN=node1 \
- -v v5:/var/lib/MySQL \
- --privileged \
- --ip 172.18.0.6 \
- percona/percona-xtradb-cluster
新建立一个 aaa 数据库 结果都可以用
哇塞就这么简单, 成功的搭建了 MySQL 的集群
增加负载均衡方案
目前数据库都是独立的 ip, 在开发的时候总不能随机连接一个数据库吧. 如果想请求, 统一的口径, 这就需要搭建负载均衡了. 虽然上边已经搭建了集群, 但是不使用数据库负载均衡, 单节点处理所有请求, 负载高, 性能差. 下图就是一个节点很忙, 其他节点很闲.
调整后的方案, 使用 Haproxy 做负载均衡, 请求被均匀分发到每个节点, 单节点的负载低, 性能好. haproxy 不是数据库, 只是一个转发器.
负载均衡中间件对比
LVS 是不知道在虚拟机环境下安装的.
安装 haproxy
docker-haproxy 的介绍: https://hub.docker.com/_/haproxy/
配置文件
- mkdir haproxy/h1
- pwd
- vi haproxy.cfg
haproxy.cfg 配置
登录: admin
密码: abc123456
- global
- # 工作目录
- chroot /usr/local/etc/haproxy
- # 日志文件, 使用 rsyslog 服务中 local5 日志设备(/var/log/local5), 等级 info
- log 127.0.0.1 local5 info
- # 守护进程运行
- daemon
- defaults
- log global
- mode http
- # 日志格式
- option httplog
- # 日志中不记录负载均衡的心跳检测记录
- option dontlognull
- # 连接超时(毫秒)
- timeout connect 5000
- # 客户端超时(毫秒)
- timeout client 50000
- # 服务器超时(毫秒)
- timeout server 50000
监控界面
- listen admin_stats
- # 监控界面的访问的 IP 和端口
- bind 0.0.0.0:8888
- # 访问协议
- mode http
- #URI 相对地址
- stats uri /dbs
- # 统计报告格式
- stats realm Global\ statistics
- # 登陆帐户信息
- stats auth admin:abc123456
数据库负载均衡
- listen proxy-MySQL
- # 访问的 IP 和端口
- bind 0.0.0.0:3306
- # 网络协议
- mode tcp
- # 负载均衡算法(轮询算法)
- # 轮询算法: roundrobin
- # 权重算法: static-rr
- # 最少连接算法: leastconn
- # 请求源 IP 算法: source
- balance roundrobin
- # 日志格式
- option tcplog
- # 在 MySQL 中创建一个没有权限的 haproxy 用户, 密码为空. Haproxy 使用这个账户对 MySQL 数据库心跳检测
- option MySQL-check user haproxy
- server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000
- server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000
- server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000
- server MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
- server MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
- # 使用 keepalive 检测死链
- option tcpka
创建 docker 下的 haproxy 容器
- docker run -it -d -p 4001:8888 \
- -p 4002:3306 \
- -v /root/haproxy/h1:/usr/local/etc/haproxy \
- --name h1 --privileged --net=net1 \
- --ip 172.18.0.7 haproxy
进入容器后, 加载配置文件
- docker exec -it h1 /bin/bash
- haproxy -f /usr/local/etc/haproxy/haproxy.cfg
在数据库中创建一个 haproxy 的用户, 不需要设置密码
登录 haproxy 网页端
http://192.168.66.100:4001/dbs
客户端连接 haproxy-MySQL 数据库
正常的连接 haproxy, 传递增删盖查, 其实是通过轮询的方式. 选择 MySQL 的节点. 均匀的分发给 MySQL 的实例. 不会吧数据库的请求都集中在一个节点上. 把请求分散出去, 每个数据库实例获取到的请求就小很多了. 这就是数据库的负载.
虚拟机重启后, 发现 pxc 起不起来了
查看日志发现, node1 无法启动, 输入命令查看 docker logs node1
It may not be safe to Bootstrap the cluster from this node. It was not the last one to leave the cluster and may not contain all the updates. To force cluster Bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .
解决方案
查看 node1 挂载点的文件地址
docker volume inspect v1
进入目录下
cd /var/lib/docker/volumes/v1/_data
编辑文件 grastate.dat
vi grastate.dat
高可用负载均衡方案
目前 haproxy 只有一个, 单 haproxy 不具备高可用, 必须冗余设计. haproxy 不能形成瓶颈.
虚拟 IP 技术
haproxy 双机互备离不开一个关键的技术, 这个技术是虚拟 IP,Linux 可以在一个网卡内定义多个虚拟 IP, 得把这些 IP 地址定义到一个虚拟 IP.
利用 keepalived 实现双机热备
定义出来一个虚拟 IP, 这个方案叫双机热备, 准备 2 个 keepalived,keepalived 就是为了抢占虚拟 IP 的, 谁手快谁能抢到, 没抢到的处于等待的状态. 抢到的叫做主服务器, 未抢到的叫做备服务器. 两个 keepalived 之前有心跳检测的, 当备用的检测到主服务挂了, 就立马抢占虚拟 IP.
Haproxy 双机热备方案
安装 keepalived
keepalived 必须在 haproxy 所在的容器之内, 也可以在 docker 仓库里面下载一个 haproxy-keepalived 的镜像. 这里直接在容器内安装 keepalived.
docker exec -it h1 /bin/bash
写入 dns, 防止 apt-get update 找不到服务器
- echo "nameserver 8.8.8.8" | tee /etc/resolv.conf> /dev/null
- apt-get clean
- apt-get update
- apt-get install VIM
- vi /etc/apt/sources.list
sources.list 添加下面的内容
- deb http://mirrors.163.com/ubuntu/ precise main universe restricted multiverse
- deb-src http://mirrors.163.com/ubuntu/ precise main universe restricted multiverse
- deb http://mirrors.163.com/ubuntu/ precise-security universe main multiverse restricted
- deb-src http://mirrors.163.com/ubuntu/ precise-security universe main multiverse restricted
- deb http://mirrors.163.com/ubuntu/ precise-updates universe main multiverse restricted
- deb http://mirrors.163.com/ubuntu/ precise-proposed universe main multiverse restricted
- deb-src http://mirrors.163.com/ubuntu/ precise-proposed universe main multiverse restricted
- deb http://mirrors.163.com/ubuntu/ precise-backports universe main multiverse restricted
- deb-src http://mirrors.163.com/ubuntu/ precise-backports universe main multiverse restricted
- deb-src http://mirrors.163.com/ubuntu/ precise-updates universe main multiverse restricted
更新 apt 源
- apt-get clean
- apt-get update
- apt-get install keepalived
- apt-get install VIM
keepalived 配置文件
容器内的路径:/etc/keepalived/keepalived.conf
vi /etc/keepalived/keepalived.conf
VI_1 名称可以自定义
state MASTER | keepalived 的身份(MASTER 主服务器, BACKUP 备份服务器, 不会抢占虚拟机 ip). 如果都是主 MASTER 的话, 就会进行互相争抢 IP, 如果抢到了就是 MASTER, 另一个就是 SLAVE.
interface 网卡, 定义一个虚拟 IP 定义到那个网卡上边. 网卡设备的名称. eth0 是 docker 的虚拟网卡, 宿主机是可以访问的.
virtual_router_id 51 | 虚拟路由标识, MASTER 和 BACKUP 的虚拟路由标识必须一致. 标识可以是 0-255.
priority 100 | 权重. MASTER 权重要高于 BACKUP 数字越大优选级越高. 可以根据硬件的配置来完成, 权重最大的获取抢到的级别越高.
advert_int 1 | 心跳检测. MASTER 与 BACKUP 节点间同步检查的时间间隔, 单位为秒. 主备之间必须一致.
authentication | 主从服务器验证方式. 主备必须使用相同的密码才能正常通信. 进行心跳检测需要登录到某个主机上边所有有账号密码.
virtual_ipaddress | 虚拟 ip 地址, 可以设置多个虚拟 ip 地址, 每行一个. 根据上边配置的 eth0 上配置的 ip.
启动 keeplived
容器内启动
service keepalived start
宿主机 ping 这个 ip
ping 172.18.0.201
创建 haproxy2 容器, 并配置与 haproxy1 相同的环境
因为要保证有 2 个 haproxy 和 keepalived, 这次就不那么麻烦了. 直接对一个镜像里面包括 keeplived 和 haproxy.
宿主机创建文件
- mkdir haproxy/h2
- cd haproxy/h2
- vi haproxy.cfg
- vi keepalived.cfg
- haproxy.cfg
- global
- # 工作目录
- chroot /usr/local/etc/haproxy
- # 日志文件, 使用 rsyslog 服务中 local5 日志设备(/var/log/local5), 等级 info
- log 127.0.0.1 local5 info
- # 守护进程运行
- daemon
- defaults
- log global
- mode http
- # 日志格式
- option httplog
- # 日志中不记录负载均衡的心跳检测记录
- option dontlognull
- # 连接超时(毫秒)
- timeout connect 5000
- # 客户端超时(毫秒)
- timeout client 50000
- # 服务器超时(毫秒)
- timeout server 50000
监控界面
- listen admin_stats
- # 监控界面的访问的 IP 和端口
- bind 0.0.0.0:8888
- # 访问协议
- mode http
- #URI 相对地址
- stats uri /dbs
- # 统计报告格式
- stats realm Global\ statistics
- # 登陆帐户信息
- stats auth admin:abc123456
数据库负载均衡
- listen proxy-MySQL
- # 访问的 IP 和端口
- bind 0.0.0.0:3306
- # 网络协议
- mode tcp
- # 负载均衡算法(轮询算法)
- # 轮询算法: roundrobin
- # 权重算法: static-rr
- # 最少连接算法: leastconn
- # 请求源 IP 算法: source
- balance roundrobin
- # 日志格式
- option tcplog
- # 在 MySQL 中创建一个没有权限的 haproxy 用户, 密码为空. Haproxy 使用这个账户对 MySQL 数据库心跳检测
- option MySQL-check user haproxy
- server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000
- server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000
- server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000
- server MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
- server MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
- # 使用 keepalive 检测死链
- option tcpka
- keepalived.cfg
- vrrp_instance VI_1 {
- state MASTER
- interface eth0
- virtual_router_id 51
- priority 100
- advert_int 1
- authentication {
- auth_type PASS
- auth_pass 123456
- }
- virtual_ipaddress {
- 172.18.0.201
- }
- }
docker 的方式一下安装好 haproxy 和 keepalived
https://hub.docker.com/r/pelin/haproxy-keepalived/
映射端口更改为 4003 4004 name 修改 h2
- docker run -it -d --privileged -p 4003:8888\
- -p 4004:3306 \
- -v /root/haproxy/h2/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg \
- -v /root/haproxy/h2/keepalived.conf:/etc/keepalived/keepalived.conf \
- --name haproxy-keepalived \
- --net=net1 \
- --name h2 \
- --ip 172.18.0.8 \
- pelin/haproxy-keepalived
宿主机安装 keepalived
- yum -y install keepalived
- vi /etc/keepalived/keepalived.conf
删除这个表里之前存在的内容
- keepalived.cof
- vrrp_instance VI_1 {
- state MASTER
- interface eth0
- virtual_router_id 51
- priority 100
- advert_int 1
- authentication {
- auth_type PASS
- auth_pass 1111
- }
- virtual_ipaddress {
- 192.168.66.200
- }
- }
- virtual_server 192.168.66.200 8888 {
- delay_loop 3
- lb_algo rr
- lb_kind NAT
- persistence_timeout 50
- protocol TCP
- real_server 172.18.0.201 8888 {
- weight 1
- }
- }
- virtual_server 192.168.66.200 3306 {
- delay_loop 3
- lb_algo rr
- lb_kind NAT
- persistence_timeout 50
- protocol TCP
- real_server 172.18.0.201 3306 {
- weight 1
- }
- }
启动宿主机
service keepalived start
虚拟机端口转发 外部无法访问
WARNING: IPv4 forwarding is disabled. Networking will not work.
解决方案
宿主机修改
vi /etc/sysctl.conf
添加 net.ipv4.ip_forward=1
systemctl restart network
PS: 如果通过 docker 的方式直接拉取 haproxy 和 keepalived 镜像, 比直接在镜像里面安装应用方便很多, 建议各位老铁尽量避免在容器内安装应用, 这样真心麻烦不爽, 别人封装的镜像根据 pull 的量好好看看 API 就可以使用了. 像 h1 如果容器 stop 后, 重新 start, 还需要进入容器把 keeplived 给起起来. 而 h2 直接 start 里面的 haproxy 和 keeplived, 同时都起起来了. 两个容器的采用的热备的方案, 让用户毫无感知, 切换 ip 的形式真是美滋滋. MySQL 集群的高性能, 高负载, 高可用基本完成了, 可用按照这个思路搭建不同的主机下.
来源: https://yq.aliyun.com/articles/697448