注意!!:Redis 并不能保证数据的强一致性.
这意味这在实际中集群在特定的条件下可能会丢失写操作:原因是因为集群是用了异步复制.
1、客户端向主节点写入一条命令.
2、主节点向客户端回复命令状态.
3、主节点将写操作复制给它的从节点
docker pull redis镜像缺少某些配置,而镜像本身是可读的,所以该镜像不适合做集群
所以需要自己构建一个redis镜像
自定义的redis镜像所需的材料:镜像底层操作系统(centos7)+(下载的redis源码包并配置)
1、拉取redis镜像
docker pull redis
2、下载redis源码包
进入Xshell,docker文件夹下创建redis文件夹
mkdir redis
wget http://download.redis.io/releases/redis-4.0.1.tar.gz
3、源码包解压缩
tar -xzf redis-4.0.1.tar.gz
4、将源代码编译成可执行的文件
在 redis-4.0.1文件夹中执行以下命令
make
make命令的使用前提是安装了gcc命令
vim redis.conf
#修改的内容
bind 0.0.0.0
requirepass 123
masterauth 123
logfile "/usr/local/redis/logs/redis-server.log"
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
解释一下代码
bind 设置ip绑定 0.0.0.0为不绑定ip
requirepass 设置密码 redis单个节点的密码
masterauth 主从复制的验证密码 redis集群的密码
logfile 设置日志文件的存储位置
cluster-enabled 开启集群配置
cluster-config-file 设置集群的配置文件
cluster-node-timeout 设置集群的超时时间 即当超过这个时间,redis节点无法连接,从节点会接替主节点的工作
6、通过Dockerfile创建redis基础镜像
redis目录下创建Dockerfile文件
touch Dockerfile
vim Dockerfile
#Dockerfile文件内容如下
#指定基础镜像
FROM centos:7
#说明镜像作者
MAINTAINER dean "[email protected]"
#定义路径的环境变量
ENV REDIS_HOME /usr/local
#将Dockerfile同级目录下的redis-4.0.1.tar.gz复制到镜像的根目录
ADD redis-4.0.1.tar.gz /
#创建安装目录,根据环境变量信息,实际的创建目录为:/usr/local/redis
RUN mkdir -p $REDIS_HOME/redis
#将Dockerfile同级目录下redis-4.0.1中的redis配置文件拷贝到容器的/usr/local/redis目录中
ADD redis-4.0.1/redis.conf $REDIS_HOME/redis/
#更新镜像的yum
RUN yum -y update
#安装gcc相关编译工具
RUN yum install -y gcc make
#指定工作目录
WORKDIR /redis-4.0.1
#执行编译
RUN make
#移动编译后的redis-server到容器相关的目录
RUN mv /redis-4.0.1/src/redis-server $REDIS_HOME/redis/
#移动到上一级
WORKDIR /
#删除解压文件
RUN rm -rf /redis-4.0.1
#删除gcc的工具
RUN yum remove -y gcc make
#添加数据卷
#/usr/local/redis/logs/redis-server.log
#此目录需要和redis.conf中logfile一致
VOLUME ["/usr/local/redis/logs"]
#暴露6379的端口
EXPOSE 6379
7、构建镜像
docker build . -t dean/redis:1.0
以上述自定义的redis镜像作为基础镜像,构建redis节点镜像
1、创建文件
在redis目录中创建redis-node目录
在redis-node目录中创建Dockerfile文件
2、编辑redis-node的Dockerfile
vim Dockerfile
# Dockerfile 文件内容
FROM dean/redis:1.0
MAINTAINER dean "[email protected]"
ENTRYPOINT ["/usr/local/redis/redis-server","/usr/local/redis/redis.conf"]
构建镜像
docker build . -t xx/redis-node:1.0
1、启动多个redis-node容器
docker run -d --name r1 -p 7001:6379 xx/redis-node:1.0
docker run -d --name r2 -p 7002:6379 xx/redis-node:1.0
docker run -d --name r3 -p 7003:6379 xx/redis-node:1.0
docker run -d --name r4 -p 7004:6379 xx/redis-node:1.0
docker run -d --name r5 -p 7005:6379 xx/redis-node:1.0
docker run -d --name r6 -p 7006:6379 xx/redis-node:1.0
docker inspect $(docker ps -a -q) |grep IPAddress
宿主机与redis容器的映射关系
r1: 192.168.10.101:7001 --> 172.17.0.2:6379
r2: 192.168.10.101:7002 --> 172.17.0.3:6379
r3: 192.168.10.101:7003 --> 172.17.0.4:6379
r4: 192.168.10.101:7004 --> 172.17.0.5:6379
r5: 192.168.10.101:7005 --> 172.17.0.6:6379
r6: 192.168.10.101:7006 --> 172.17.0.7:6379
3、节点配置
因为redis-cli的路径为/redis/redis-4.0.1/src中,登录是使用不便
所以我们将该路径告知给环境变量
export PATH=$PATH:/root/docker/redis/redis-4.0.1/src
在虚拟机中登录redis服务
redis-cli -p 7001 -a 123
-a 是之前设置的节点密码
4、添加节点
将所有的redis节点都添加到redis集群中
cluster meet 节点IP 端口号
cluster nodes
当前默认所有节点都是master(主节点)
5、配置槽点
即设置每个节点的哈希槽段位
写一个shell脚本(addSlot.sh)来指定主节点的哈希槽范围
在redis文件夹下创建一个addSlot.sh文件
touch addSlot.sh
vim addSlot.sh
# addSlot.sh中的内容如下
#!/bin/bash
#将0-5461的槽点配置在r1节点172.17.0.2:6379(宿主机127.0.0.1:7001)的redis上
n=0
for ((i=n;i<=5461;i++))
do
redis-cli -h 127.0.0.1 -p 7001 -a 123 CLUSTER ADDSLOTS $i
done
#将5462-10922的槽点配置在r2节点172.17.0.3:6379(宿主机127.0.0.1:7002)的redis上
n=5462
for ((i=n;i<=10922;i++))
do
redis-cli -h 127.0.0.1 -p 7002 -a 123 CLUSTER ADDSLOTS $i
done
#将10923-16383的槽点配置在r3 172.17.0.4:6379(宿主机127.0.0.1:7003)的redis上
n=10923
for ((i=n;i<=16383;i++))
do
redis-cli -h 127.0.0.1 -p 7003 -a 123 CLUSTER ADDSLOTS $i
done
为addSlot.sh加权限,使之成为可执行文件
chomd +x addSlot.sh
./addSlot.sh
登录redis 服务
查看所有节点信息
redis-cli -p 7001 -a 123
cluster info
6、配置主从关系
将r4、r5、r6配置为slave(从节点)
#CLUSTER REPLICATE后面跟的是主节点的节点ID 127.0.0.2:6379
redis-cli -h 127.0.0.1 -p 7004 -a 123 CLUSTER REPLICATE ec8b8c6c75b47ae422ee6995ad223480d441b3d0
#CLUSTER REPLICATE后面跟的是127.17.0.3:6379的集群ID
redis-cli -h 127.0.0.1 -p 7005 -a 123 CLUSTER REPLICATE 3d62ee388099611469869cecb1d4e0de8b11f4ee
#CLUSTER REPLICATE后面跟的是172.17.0.4:6379的集群ID
redis-cli -h 127.0.0.1 -p 7006 -a 123 CLUSTER REPLICATE 156c3e764882a24cbdf6489d2591028315855266
可以发现已有主从之分
当停掉一个主节点后,该主节点的从节点就会变成主节点
7、测试数据的获取
我们存入一个变量
set ff 111
获取变量
get f
#打印集群的信息
CLUSTER INFO
#列出集群当前已知的所有节点(node),以及这些节点的相关信息
CLUSTER NODES
#节点(node)
#所指定的节点添加到集群中
CLUSTER MEET <ip> <port> 将 ip 和 port
#从集群中移除 node_id 指定的节点
CLUSTER FORGET <node_id>
#将当前节点设置为 node_id 指定的节点的从节点
CLUSTER REPLICATE <node_id>
#将节点的配置文件保存到硬盘里面
CLUSTER SAVECONFIG
#槽(slot)
#将一个或多个槽(slot)指派(assign)给当前节点。
CLUSTER ADDSLOTS <slot> [slot ...]
#移除一个或多个槽对当前节点的指派
CLUSTER DELSLOTS <slot> [slot ...]
#移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
CLUSTER FLUSHSLOTS
#将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
CLUSTER SETSLOT <slot> NODE <node_id>
#将本节点的槽 slot 迁移到 node_id 指定的节点中。
CLUSTER SETSLOT <slot> MIGRATING <node_id>
#从 node_id 指定的节点中导入槽 slot 到本节点
CLUSTER SETSLOT <slot> IMPORTING <node_id>
#取消对槽 slot 的导入(import)或者迁移(migrate)
CLUSTER SETSLOT <slot> STABLE
#键 (key)
#计算键 key 应该被放置在哪个槽上
CLUSTER KEYSLOT <key>
#返回槽 slot 目前包含的键值对数量。
CLUSTER COUNTKEYSINSLOT <slot>
#返回 count 个 slot 槽中的键
CLUSTER GETKEYSINSLOT <slot> <count>
Replication
PXC
MySQlL本身不支持集群,Percona Server为MySQL数据库服务器进行了改进,提升了性能,使之可以支持集群
拉取PXC镜像
去docker Hub镜像仓库搜索percona,查找镜像名
回到Xshell进行拉取镜像
docker pull percona/percona-xtradb-cluster
可以为镜像改下名方便记忆
docker tag percona/percona-xtradb-cluster pxc
改名后会出现两个pxc镜像,使用docker rmi删除原来的镜像
创建新的docker网段
在redis集群中,我们使用的网段是172.17.0.0(docker的默认网段,无需手动创建),为了不使PXC与redis冲突,创建新的网段
查看虚拟机中docker的虚拟网卡
docker network ls
docker network create --subnet=172.18.0.0/24 pxc_net
查看新建网段的信息
docker nework inspect pxc_net
docker network rm pxc_net
创建volume卷
使用volume卷将容器的数据挂载在容器的外面,方便修改
docker volume create pxc_v1
docker volume create pxc_v2
docker volume create pxc_v3
docker volume create pxc_v4
docker volume create pxc_v4
启动5个pxc容器
docker run -d
-p 8001:3306 #指定映射端口
-e MYSQL_ROOT_PASSWORD=root #指定登录MySQL的密码
-e CLUSTER_NAME=PXC #指定集群的名字
-e XTRABACKUP_PASSWORD=root #集群中一个节点给另一个节点备份时,需要知道该节点的密码
-v pxc_v1:/var/lib/mysql #v1挂载卷,挂载容器中的/var/lib/mysql文件夹
--privileged #容器拥有最高权限
--name=pxc1 #容器名
--net=pxc_net #指定网段,若不指定,默认是在172.17.0.0网段中
--ip=172.18.0.11 #指定IP地址 ,若不指定,会默认分配
pxc #镜像名
5个容器中的映射端口、挂载卷名、容器名、IP地址是不同的,其余相同
当我们创建了第一个pxc容器pxc1时,集群会默认这个是主节点,后面所有容器都要加入这个节点
实现方法是,给pxc2、pxc3、pxc4、pxc5增加参数 -e CLUSTER_JOIN=pxc1实现
pxc1容器的启动会去启动mysql,所以耗时较长,大概1min左右,一定要等待pxc1完全启动后再启动其余容器
可以使用navicat查看pxc1是否成功,连接成功后再启动其余的pxc容器
启动成功
此时,集群已经搭建完成,在任意一个节点中插入数据,都会同步到所有的节点内
增加代理节点做负载均衡,客户端不会连接某一个具体的节点,而是连接代理节点,由代理节点将客户端请求分发给某个pxc节点
代理节点又称中间件,常用的中间件有haproxy、nginx、apache、lvs
目录结构
拉取haproxy镜像
在docker Hub搜索haproxy
在Xshell中进行拉取
docker pull haproxy
配置文件的配置
docker文件夹中创建haproxy文件夹
haproxy镜像里配置文件路径在/usr/local/etc/haproxy.cfg
再次声明:镜像是静态的,只读不能改,启动为容器后才能修改里面的文件,但容器里没有vim编辑工具,所以采用文件挂载方式挂载到宿主机,在宿主机内进行修改
在haproxy中创建配置文件
touch 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和端口(0.0.0.0表示任何ip地址都可以访问该监控界面)
bind 0.0.0.0:8888 #(8888监控界面端口)
#访问协议
mode http
#URI相对地址
stats uri /dbs
#统计报告格式
stats realm Global\ statistics
#登陆帐户信息
stats auth admin:admin
#数据库负载均衡
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 pxc1 172.18.0.11:3306 check weight 1 maxconn 2000
server pxc2 172.18.0.12:3306 check weight 1 maxconn 2000
server pxc3 172.18.0.13:3306 check weight 1 maxconn 2000
server pxc4 172.18.0.14:3306 check weight 1 maxconn 2000
server pxc5 172.18.0.15:3306 check weight 1 maxconn 2000
#使用keepalive检测死链
option tcpka
启动haproxy容器
docker run -d -p 4001:8888 #设置8888监控界面端口映射
-p 4002:3306 #登录到haproxy数据库
-v /root/docker/haproxy/:/usr/local/etc/haproxy #挂载配置文件
--name h1
--privileged
--net=pxc_net
haproxy
进入haproxy容器
docker exec -it h1 bash
docker -f haproxy.cfg
该命令会使在启动haproxy服务时读取配置文件并进行相关配置
在浏览器访问后台监控界面
用户名和密码是在配置文件中设定的
登录成功后会显示以下界面
前提是要在navicat里创建haproxy用户
当我们停止一个pxc节点时
docker pause pxc1
pxc1节点状态将会变为黄色
等待一会将会变为红色,即判定该节点死亡
使用以下命令取消暂停
docker unpause pxc1