在生产环境,Redis如果是单节点会存在单点故障,所以一般都是集群环境,所以我们一会先搭建集群,再在Redis集群环境中实现Redis缓存高级操作。
1. 集群搭建
1.1 Redis集群原理
在做Redis集群前,我们先了解一下Redis集群原理:
1:无论对Redis执行增加、删除、查询操作,都会操作一个key
2:无论什么key,经过CRC16算法取模,结果都在0-16383之间,这16384个值被称为哈希槽
3:如果我们现在有一个Redis集群,集群有3个节点,会为每个节点分配一定哈希槽
RedisNode1:0-5460
RedisNode2:5461-10922
RedisNode3:10923-16383
4:每次做增加、删除、查询时,先对key进行CRC16算法取模,计算哈希槽的值
5:根据哈希槽的值重定向当前链接到指定节点上,并执行操作
Redis集群虽然能降低每个节点的载荷,但也存在宕机的风险,此时我们应该给每个节点安装一个从节点,当主节点宕机的时候,可以切换至从节点,添加从节点后,架构图如下:
1.2 Docker安装Redis集群
我们使用Docker容器安装Redis集群,准备6台机器(我们在1台机器上模拟):
| 节点 | IP | 端口 |
|---|---|---|
| RedisNode1 | 192.168.100.130 | 7001 |
| RedisNode2 | 192.168.100.130 | 7002 |
| RedisNode3 | 192.168.100.130 | 7003 |
| RedisNode4 | 192.168.100.130 | 7004 |
| RedisNode5 | 192.168.100.130 | 7005 |
| RedisNode6 | 192.168.100.130 | 7006 |
1)创建网络
创建网络(各个Redis集群节点都在同一网段下数据交换,安全性更高,传输效率也会更高):
docker network create redis-net
2)创建Redis配置
我们可以基于shell脚本批量创建每个Redis的配置文件,再采用shell脚本为脚本批量填充数据,再创建docker容器,我们可以先写一个Redis配置的模板文件redis-config.tmpl。注意修改本地IP,否则集群会连接不上的。同时注意如果是云服务器,记得放行相关端口(7001/7006;17001/17006)
#端口
port ${PORT}
#非保护模式
protected-mode no
#启用集群模式
cluster-enabled yes
cluster-config-file nodes.conf
#超时时间
cluster-node-timeout 5000
cluster-announce-ip 192.168.100.130
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
#开启aof持久化策略
appendonly yes
#后台运行
#daemonize yes
pidfile /var/run/redis_${PORT}.pid
3)Shell创建docker容器
我们创建一个shell脚本,从7001循环到7006,以上面的redis-config.tmpl模板为基础,批量创建每个redis节点的配置文件,并创建对应容器,文件名字叫install.sh,将改文件设置为可执行文件:
注意自己创建相关文件夹,将这些文件放在同一目录下。
#!/bin/bash
#在/opt/redis-cluster下生成conf和data目标,并生成配置信息
for port in `seq 7001 7006`;
do
mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-config.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data;
done
#创建6个redis容器
for port in `seq 7001 7006`;
do
docker run -d -it -p ${port}:${port} -p 1${port}:1${port} -v /opt/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /opt/redis-cluster/${port}/data:/data --privileged=true --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
done
#查找ip
for port in `seq 7001 7006`;
do
echo -n "$(docker inspect --format '{{ (index .NetworkSettings.Networks "redis-net").IPAddress }}' "redis-${port}")":${port}" ";
done
#换行
echo -e "\n"
#输入信息
read -p "输入要进入的Docker容器名字,默认redis-7001:" DOCKER_NAME
#判断是否为空
if [ ! $DOCKER_NAME ];
then DOCKER_NAME='redis-7001';
fi
#进入容器
docker exec -it redis-7001 /bin/bash
创建文件后执行授权:
chmod +x install.sh
此时执行./install.sh就能安装7001-7006的容器。
执行这一步之后,也只是容器安装好了,开启了集群,但哪些节点创建一个集群组还并未操作,我们需要用到redis-cli客户端工具来创建集群组:(IP地址对应上图最后输出的IP)
首先进入容器内部:
docker exec -it redis-7001 /bin/bash
cd /usr/local/bin/
注意IP地址和端口号。
./redis-cli --cluster create 172.18.0.2:7001 172.18.0.3:7002 172.18.0.4:7003 172.18.0.5:7004 172.18.0.6:7005 172.18.0.7:7006 --cluster-replicas 1
效果如下:
此时集群管理如下:
7001(Master) 7005(Slave)
7002(Master) 7006(Slave)
7003(Master) 7004(Slave)
关于创建集群中的相关参数我们做如下说明:
Cluster Manager Commands:
create host1:port1 ... hostN:portN #创建集群
--cluster-replicas <arg> #从节点个数
check host:port #检查集群
--cluster-search-multiple-owners #检查是否有槽同时被分配给了多个节点
info host:port #查看集群状态
fix host:port #修复集群
--cluster-search-multiple-owners #修复槽的重复分配问题
reshard host:port #指定集群的任意一节点进行迁移slot,重新分slots
--cluster-from <arg> #需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递--from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入
--cluster-to <arg> #slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入
--cluster-slots <arg> #需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。
--cluster-yes #指定迁移时的确认输入
--cluster-timeout <arg> #设置migrate命令的超时时间
--cluster-pipeline <arg> #定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10
--cluster-replace #是否直接replace到目标节点
rebalance host:port #指定集群的任意一节点进行平衡集群节点slot数量
--cluster-weight <node1=w1...nodeN=wN> #指定集群节点的权重
--cluster-use-empty-masters #设置可以让没有分配slot的主节点参与,默认不允许
--cluster-timeout <arg> #设置migrate命令的超时时间
--cluster-simulate #模拟rebalance操作,不会真正执行迁移操作
--cluster-pipeline <arg> #定义cluster getkeysinslot命令一次取出的key数量,默认值为10
--cluster-threshold <arg> #迁移的slot阈值超过threshold,执行rebalance操作
--cluster-replace #是否直接replace到目标节点
add-node new_host:new_port existing_host:existing_port #添加节点,把新节点加入到指定的集群,默认添加主节点
--cluster-slave #新节点作为从节点,默认随机一个主节点
--cluster-master-id <arg> #给新节点指定主节点
del-node host:port node_id #删除给定的一个节点,成功后关闭该节点服务
call host:port command arg arg .. arg #在集群的所有节点执行相关命令
set-timeout host:port milliseconds #设置cluster-node-timeout
import host:port #将外部redis数据导入集群
--cluster-from <arg> #将指定实例的数据导入到集群
--cluster-copy #migrate时指定copy
--cluster-replace #migrate时指定replace
4)集群测试
集群安装好了后,我们可以使用redis-cli进行测试:
#登录redis集群
root@6f42ad53f7bb:/usr/local/bin# ./redis-cli -p 7001 -c
#添加数据
127.0.0.1:7001> set zhangsan SDFDSFDSF.DSFSDFSDFS.FHBSDFDSFSDFF
#自动重定向到7003节点
-> Redirected to slot [12767] located at 192.168.100.130:7003
OK
192.168.100.130:7003>
5)卸载Docker容器
如果我们想卸载安装的docker容器,可以创建一个文件uninstall.sh:
#!/bin/bash
docker stop redis-7001 redis-7002 redis-7003 redis-7004 redis-7005 redis-7006
docker rm redis-7001 redis-7002 redis-7003 redis-7004 redis-7005 redis-7006
rm -rf 7001 7002 7003 7004 7005 7006
再给uninstall.sh添加可执行权限:
chmod +x uninstall.sh
执行该文件即可卸载7001-7006所有docker容器了
2. Java连接Redis集群
在java客户端连接Redis集群,只需要修改配置文件bootstrap.yml中redis链接即可:
redis:
cluster:
nodes: 192.168.100.130:7001,192.168.100.130:7002,192.168.100.130:7003,192.168.100.130:7004,192.168.100.130:7005,192.168.100.130:7006
3. 扩容与迁移
在生产环境,如果缓存数据量过大,就有扩容需求,针对Redis进行扩容,其实只用使用它的指令即可,但无论怎么使用,都和Redis集群的原理有关,也就是key经过CRC16算法取模最终的值在0至16383范围之间。
3.1 新节点创建
我们需要做扩容操作,所以需要先创建一个节点,创建单个节点我们可以把之前的脚本修改一下,创建单个节点的文件oneinstall.sh:
#!/bin/bash
#在/opt/redis-cluster下生成conf和data目标,并生成配置信息
#换行
echo -e "\n"
#输入信息
read -p "请输入容器端口:" DOCKER_PORT
#输入端口赋值
port=$DOCKER_PORT;
echo -e "$port"
#创建配置文件
mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-config.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data;
#创建redis容器
docker run -d -it -p ${port}:${port} -p 1${port}:1${port} -v /opt/redis-cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /opt/redis-cluster/${port}/data:/data --privileged=true --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
#查找ip
echo -n "启动$(docker inspect --format '{{ (index .NetworkSettings.Networks "redis-net").IPAddress }}' "redis-${port}")":${port}" 成功!";
echo -e "\n"
给oneinstall.sh添加可执行权限,并执行该脚本:
#添加可执行权限
chmod +x oneinstall.sh
#创建新的节点
./oneinstall.sh
#输入7007端口
7007
此时7007节点创建完成:
3.2 扩容
我们要进行扩容,可以先查看当前集群状态:
#查看集群状态
cluster nodes
流程如下:
我们现在开始执行节点增加,也就是扩容操作:
./redis-cli --cluster add-node 192.168.100.130:7007 192.168.100.130:7001
执行后,我们可以再去看下集群状态,会发现有所变化,可以发现新增一个节点。
此时节点已经增加进来,但目前没有分配任何哈希槽,所以无论做数据增加还是删除以及查询,都和它没有一毛钱关系,因此我们还要把部分哈希槽迁移到该节点上,同时被迁移的节点上对应数据也会跟着一起迁移过来,迁移命令如下:
./redis-cli --cluster reshard 192.168.100.130:7003 --cluster-from 5d93f5ca5e7289c04b00ccc468e0ce4ef8afaea9 --cluster-to 889a13a1e1761f1e83c25e41287d1c463175d467 --cluster-slots 100
参数说明:
5d93f5ca5e7289c04b00ccc468e0ce4ef8afaea9 指的是7003节点
889a13a1e1761f1e83c25e41287d1c463175d467 指定是7007节点
表示将7003节点中100个哈希槽迁移到7007上来
我们再查看状态就可以发现7007拥有100个哈希槽了。
3.3 收容
收容其实也很简单,也是使用命令即可,要做2个操作:
-
哈希槽迁移
说先将哈希槽迁移否则会造成数据丢失。
-
删除节点
第一个地址代表集群环境,最后的字符代表删除哪一个节点。
./redis-cli --cluster del-node 192.168.100.130:7001 889a13a1e1761f1e83c25e41287d1c463175d467














还没有评论,来说两句吧...