Docker安装Redis集群失败经历汇总

在程序员的开发过程中,Redis可以说基本上是必不可少的缓存中间件。不管是二进制包还是docker安装Redis的文章在网上都是数不胜数。我之前自己玩Redis的时候基本不是二进制包安装就是docker安装,也没有尝试过集群方式。每次需要的时候,网上百度一篇文章,安装一个单机版的,有的时候行,有的文章不行。

也正是因为这个原因,本篇文章就想着自己创建Redis,通过docker方式进行部署。算是记录一下,方便以后使用。最后,然后我们再安装一下Redis集群模式。结果没想到,刚开始成功了,但是没有做记录,后来搞的时候竟然搞成了这个鬼样子。最后各种解决问题,还是没有解决。

既然是容器,那么删除很方便,我们之后把这个集群删除,重新部署,等到部署成功后会把文章链接贴到本篇文章中。集群的部署一定要贴合实际,不搞demo那种玩法,搞就搞生产上的部署方案与可行性。

一、单机版

# 1.查询所有镜像
docker search redis

# 2.拉取redis镜像
docker pull redis

# 3.查看所有镜像
docker images

# 4.宿主机创建需要挂载的目录和文件
mkdir -p /usr/local/redis/{data,conf}
touch /usr/local/redis/conf/redis.conf

# 5.创建redis容器并进行端口映射、容器命名和目录文件挂载
docker run -p 6379:6379 --name redis \
-v /usr/local/redis/data:/data \
-v /usr/local/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf

# 6.查看正在运行的容器
docker ps

# 或者所有容器
docker ps -a

# 7.进入容器,此处的redis指的是容器名或容器id
docker exec -it redis bash

# 进入redis命令行界面
redis-cli

# 8.测试

# 测试方法一
set key1 v1

# 命令行返回:OK
set key1

# 命令行返回:“v1”

# 测试方法二
ping

# 客户端返回:PONG

# 此时代表一台redis安装成功

# 9.退出redis命令行
Ctrl + c

# 10.退出redis容器
Ctrl + pq

# 或者直接启动容器并进入
docker exec -it redis redis-cli

# 退出容器
Ctrl + pq
# 或者
exit

 

二、Redis集群部署

集群节点情况:

节点

Ip

端口

主从

Node01

192.168.222.100

6380

Master

6381

Slave

Node02

192.168.222.103

6380

Master

6381

Slave

Node03

192.168.222.104

6380

Master

6381

Slave

2.1 方案一

# 1.创建目录
mkdir -p /usr/local/redis-cluster/{master-6380,slave-6381,slave-6382}

# 2.拉取镜像
docker pull redis

# 3..创建master节点的redis容器
docker run -d --name redis-master-6380 --net host --privileged=true \
-v /usr/local/redis-cluster/master-6380/conf/redis.conf:/etc/redis/redis.conf \
-v /usr/local/redis-cluster/master-6380/data:/data \
redis redis-server /etc/redis/redis.conf

# 4..创建slave-6381的redis容器
docker run -d --name redis-slave-6381 -p 6381:6379 --privileged=true \
-v /usr/local/redis-cluster/slave-6381/conf/redis.conf:/etc/redis/redis.conf \
-v /usr/local/redis-cluster/slave-6381/data:/data \
redis redis-server /etc/redis/redis.conf

# 5.创建slave-6382的redis容器
docker run -d --name redis-slave-6382 -p 6382:6379 --privileged=true \
-v /usr/local/redis-cluster/slave-6382/conf/redis.conf:/etc/redis/redis.conf \
-v /usr/local/redis-cluster/slave-6382/data:/data \
redis redis-server /etc/redis/redis.conf


# 6.分别在三台机器上创建三台redis


# 7.进入随便一台redis容器(这里以第一台服务器的master节点为例)

docker exec -it redis-master-6380 bash


# 通过端口映射的方式安装的redis集群有一定的问题,就是使用redis的服务必须和redis在一台机器上,
# 不然无法访问。

2.2 方案二

# 1.创建三台redis,通过 --net 指定网络类型 host模式,这种情况不需要端口映射。

# 创建的容器是没有自己独立的网络命名空间的,是跟物理机共享一个网络空间,进而可以# 共享物理机的所# 有端口与IP,这样就可以让公共网络直接访问容器

# 此时需要对外共享容器端口服务,只需要指定对外暴露的端口即可,-p 6379/-p 6380等。

# 下文中使用的是 --port 6380

docker create --name redis-master-6380 --net host \
-v /usr/local/redis-cluster/master-6380/conf/redis.conf:/etc/redis/redis.conf \
-v /usr/local/redis-cluster/master-6380/data:/data \
redis:latest --cluster-enabled yes --cluster-config-file redis-master-6380.conf --port 6380


docker create --name redis-slave-6381 --net host \
-v /usr/local/redis-cluster/slave-6381/conf/redis.conf:/etc/redis/redis.conf \
-v /usr/local/redis-cluster/slave-6381/data:/data \
redis:latest --cluster-enabled yes --cluster-config-file redis-slave-6381.conf --port 6381



docker create --name redis-slave-6382 --net host \
-v /usr/local/redis-cluster/slave-6382/conf/redis.conf:/etc/redis/redis.conf \
-v /usr/local/redis-cluster/slave-6382/data:/data \
redis:latest --cluster-enabled yes --cluster-config-file redis-slave-6382.conf --port 6382



# 参数解释

--cluster-enabled:是否启动集群,选值:yes 、no

--cluster-config-file 配置文件.conf :指定节点信息,自动生成

--cluster-node-timeout 毫秒值: 配置节点连接超时时间

--appendonly:是否开启持久化,选值:yes、no



# 主节点最少3个,3个才能保证集群的健壮性。


# 2.启动三台redis

docker start redis-master-6380 redis-slave-6381 redis-slave-6382

# 或者,如果只有这三个容器的话

docker start $(docker ps -aq)


# 3.查看日志

docker logs redis-master-6380

 主要是这句话:

WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /et

c/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

翻译过来就是:

警告过度提交内存设置为0!在内存不足的情况下,后台保存可能会失败。要解决此问题,请添加“vm”。过量提交内存=1'到/etc/sysctl.conf,然后重新启动或运行命令'sysctl-vm。overcommit_memory=1'以使其生效。

解决方案在警告中已经给出:修改 /etc/sysctl.conf 配置文件,增加 vm.overcommit_memory = 1 

关于 /etc/sysctl.conf 配置

/etc/sysctl.conf是一个允许改变正在运行中的Linux系统的接口,它包含一些TCP/IP堆栈和虚拟内存系统的高级选项,修改内核参数永久生效。

/proc/sys目录下存放着大多数内核参数,并且可以在系统运行时进行更改,不过重新启动机器就会失效。

即,/proc/sys下内核文件与配置文件 sysctl.conf 中变量存在着对应关系。

Linux对大部分申请内存的请求都回复"yes",以便能跑更多更大的程序。因为申请内存后,并不会马上使用内存。这种技术叫做 Overcommit(过量使用)。

当linux发现内存不足时,会发生OOM killer(OOM=out-of-memory)。它会选择杀死一些进程(用户态进程,不是内核线程),以便释放内存。

内核参数 overcommit_memory

它是 内存分配策略。可选值:0、1、2。

0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。

1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。

2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

修改内核参数,要有root权限:

方法 1:编辑 /etc/sysctl.conf ,新增一行vm.overcommit_memory=1,然后sysctl -p使配置文件生效。

方法 2:临时设置:sysctl vm.overcommit_memory=1

不修改也不要紧。

# 4.进入其中一个容器

docker exec -it redis-master-6380 /bin/bash


# 5.创建集群

redis-cli --cluster create 192.168.222.100:6380  192.168.222.100:6381 192.168.222.100:6382 --cluster-replicas 0

# 这里是采用 redis-cli 命令方式创建集群,一共有三台机器。
# --cluster-replicas 0 指定集群副本数为0,也就是说上面三台全部是主节点,没有从节点。

 

 

# 如果报错:

[ERR] Node 192.168.222.100:6380 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0. 

删除所有redis容器和对应的映射文件,重新生成容器并创建即可。

# 5.进入其中一台redis节点

redis-cli

# 或者

redis-cli -c

# 很可能报错:

Could not connect to Redis at 127.0.0.1:6379: Connection refused

# 原因是:

# redis.conf 配置文件不存在,或者未绑定127.0.0.1。

# 解决方案:

# 找到 bind开头的配置行
# 表示redis服务程序会监听这台电脑上的本地环回地址
# 如果配置文件中,只bind了这一个ip,那么就不能远程
# 访问这台服务器上的redis服务了。
# bind 127.0.0.1 ::1    

# 表示redis服务程序会监听我们指定的ip地址,当然这个ip地址必须
# 是这台电脑的一个合法ip地址才行。
# bind x.x.x.x ::1       

#表示redis服务程序会监听任意一个合法的ip
# bind 0.0.0.0 ::1      

# 假如在配置文件中 的内容是:bind x.x.x.x ::1

# 那么在使用redis-cli连接redis-server时,应该使用 :

或者 redis-cli -h x.x.x.x -p port(配置文件中指定的端口号)
# redis-cli -h x.x.x.x -p 6379   

# 所以此时,我们的命令应该是:

redis-cli -h 192.168.222.100 -p 6380

# 或者,-c是以集群模式启动
# 如果是集群而不加该参数,会导致set值的时候报错

redis-cli -c -h 192.168.222.100 -p 6380

# 6.查看集群信息

cluster nodes

# 或者查看集群状态

cluster info

# 集群帮助命令

cluster help



# 7.集群赋值与获取值

# 在一个节点赋值,可能会存放到其他节点上,然后可以到其他节点上获取该key的值

# 8.退出redis命令行

Ctrl + c


# 9.退出redis容器

Ctrl + pq


因为我们创建的时候设置的redis数量比较少,而且指定的--cluster-replicas 0,导致最终我们的集群全部是主节点的。至此,我们的三主的redis集群搭建成功。

下面的方案我们创建一个三主三从的redis集群。

2.3 方案三

# 1.分别在三台机器上创建三个redis容器

# 这里没有映射redis.conf文件夹

# --cluster-config-file redis.conf 指定redis的配置文件,每个节点的data目录下生成一个该文# 件,这里我们统一使用redis.conf来命名,然后还会生成一个dump.RDB持久化快照文件。

# docker创建的redis默认持久化策略是RDB,如果我们想修改持久化策略,可以使用如下命令:

docker run -d --name redis-master-6380 --net host --privileged=true \

-v /usr/local/redis-cluster/master-6380/data:/data \

redis:latest --cluster-enabled yes --appendonly yes --cluster-config-file redis.conf --port 6380

# 我们在这里不使用AOF持久化,不添加--appendonly yes参数

# 我们直接一次性copy下面方框中的三条命令,直接执行即可创建并运行三个redis容器

docker run -d --name redis-master-6380 --net host --privileged=true \

-v /usr/local/redis-cluster/master-6380/data:/data \

redis:latest --cluster-enabled yes --cluster-config-file redis.conf --port 6380

docker run -d --name redis-slave-6381 --net host --privileged=true \

-v /usr/local/redis-cluster/slave-6381/data:/data \

redis:latest --cluster-enabled yes --cluster-config-file redis.conf --port 6381

docker run -d --name redis-slave-6382 --net host --privileged=true \

-v /usr/local/redis-cluster/slave-6382/data:/data \

redis:latest --cluster-enabled yes --cluster-config-file redis.conf --port 6382

 

# 也可能是这样的

 

# 因为我们在文档中的不同的创建redis容器的命令之间有回车,所以上图都是自动切换的。

# 2.查看创建的容器

docker ps

 

# 3.进入容器

# 这里我们进入100这台服务器的6380端口对应的redis容器

docker exec -it redis-master-6380 /bin/bash

# 或者

docker exec -it redis-master-6380 bash

# 4.创建主从集群(三主六从)

redis-cli --cluster create 192.168.222.100:6380 192.168.222.103:6380 192.168.222.104:6380 192.168.222.100:6381 192.168.222.103:6381 192.168.222.104:6381 192.168.222.100:6382 192.168.222.103:6382 192.168.222.104:6382  --cluster-replicas 2

# 此时我们又遇到了这个错误:

[ERR] Node 192.168.222.100:6380 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

# 解决方案:

# (1)删除对应节点的appendonly.aof、dump.rdb、redis.conf文件

rm -rf master-6380/data/*

rm -rf slave-6381/data/*

rm -rf slave-6382/data/*

# (2)清除redis数据库,如果是主从模式,则进入主数据库执行清除操作

# 进入容器

docker exec -it redis-master-6380 bash

# 进入redis

redis-cli -h 192.168.222.100 -p 6380

# 清除数据库

flushdb

 

# 清除数据库后继续执行4

>>> Performing hash slots allocation on 9 nodes...

Master[0] -> Slots 0 - 5460

Master[1] -> Slots 5461 - 10922

Master[2] -> Slots 10923 - 16383

Adding replica 192.168.222.103:6381 to 192.168.222.100:6380

Adding replica 192.168.222.104:6381 to 192.168.222.100:6380

Adding replica 192.168.222.100:6382 to 192.168.222.103:6380

Adding replica 192.168.222.104:6382 to 192.168.222.103:6380

Adding replica 192.168.222.103:6382 to 192.168.222.104:6380

Adding replica 192.168.222.100:6381 to 192.168.222.104:6380

M: 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f 192.168.222.100:6380

   slots:[0-5460] (5461 slots) master

M: f42465b62e889facf2ab37f92a36566dec0aa419 192.168.222.103:6380

   slots:[5461-10922] (5462 slots) master

M: 665fa7b34846eebee7d18e9aa2f75576a97bdca4 192.168.222.104:6380

   slots:[10923-16383] (5461 slots) master

S: bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db 192.168.222.100:6381

   replicates 665fa7b34846eebee7d18e9aa2f75576a97bdca4

S: 245cfdac475fe50d6ef1a37c43e042d280fecca2 192.168.222.103:6381

   replicates 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

S: ca008f89db1d7ade8fa474a4545a310c881997da 192.168.222.104:6381

   replicates 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

S: d06230f7438a45927d7bba6aa56cec0b7337ed27 192.168.222.100:6382

   replicates f42465b62e889facf2ab37f92a36566dec0aa419

S: 2290e52c0933bcac9261b213553b738937d0e6e8 192.168.222.103:6382

   replicates 665fa7b34846eebee7d18e9aa2f75576a97bdca4

S: d712f9e3331d83412f83107be779f0e51a8d08b3 192.168.222.104:6382

   replicates f42465b62e889facf2ab37f92a36566dec0aa419

Can I set the above configuration? (type 'yes' to accept): yes

>>> Nodes configuration updated

>>> Assign a different config epoch to each node

>>> Sending CLUSTER MEET messages to join the cluster

Waiting for the cluster to join

......

>>> Performing Cluster Check (using node 192.168.222.100:6380)

M: 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f 192.168.222.100:6380

   slots:[449],[4576] (2 slots) master

   2 additional replica(s)

M: d06230f7438a45927d7bba6aa56cec0b7337ed27 192.168.222.100:6382

   slots:[12706] (1 slots) master

M: bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db 192.168.222.100:6381

   slots:[8455] (1 slots) master

M: f42465b62e889facf2ab37f92a36566dec0aa419 192.168.222.103:6380

   slots:[5461-8454],[8456-10922] (5461 slots) master

   1 additional replica(s)

S: ca008f89db1d7ade8fa474a4545a310c881997da 192.168.222.104:6381

   slots: (0 slots) slave

   replicates 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

M: 665fa7b34846eebee7d18e9aa2f75576a97bdca4 192.168.222.104:6380

   slots:[10923-12705],[12707-16383] (5460 slots) master

   1 additional replica(s)

S: 2290e52c0933bcac9261b213553b738937d0e6e8 192.168.222.103:6382

   slots: (0 slots) slave

   replicates 665fa7b34846eebee7d18e9aa2f75576a97bdca4

S: d712f9e3331d83412f83107be779f0e51a8d08b3 192.168.222.104:6382

   slots: (0 slots) slave

   replicates f42465b62e889facf2ab37f92a36566dec0aa419

S: 245cfdac475fe50d6ef1a37c43e042d280fecca2 192.168.222.103:6381

   slots: (0 slots) slave

   replicates 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[ERR] Not all 16384 slots are covered by nodes.

# 用图片显示如下:

 

 

我们看上图最后一行红色字体,再看上图中的slots中括弧里面的哈希槽索引,可以发现是有不少遗漏的。

[ERR] Not all 16384 slots are covered by nodes.

# 这个往往是由于主node移除了,但是并没有移除node上面的slot,从而导致了slot总数# 没有达到16384,其实也就是slots分布不正确。所以在删除节点的时候一定要注意

# 删除的是否是Master主节点。

# 实际上,我们并没有删除主节点,只是在创建的时候本来是三主六从,但是给我们创建成# 了五主四从。就是这个原因导致的。

# 下面我们通过命令来修复集群

redis-cli --cluster fix 192.168.222.100:6380

 

 

# 下面还有很多,将这些哈希槽覆盖到某一个节点上

# 如果我们使用 cluster nodes 命令查看集群节点情况,会发现,确实是随机给我们分配了哈希槽

 

# 下面会将9个节点全部列出来,我们这里不再一一展示

# 查看集群情况

cluster info

 

# 修复完成后再用check命令检查下是否正确

redis-cli --cluster check 192.168.222.100:6380

# 又很长,我们截取重要信息

# 如果分布不均匀那可以使用下面的方式重新分配slot

# 我们上面的未分配的插槽再分配时是随机的,这里重新分配(重新分片)

redis-cli --cluster reshard 192.168.222.100:6380

# 又很长

# 直到这样一句话:

How many slots do you want to move (from 1 to 16384)?

# 意思是你想移动多少个插槽

# 也就是说你想移动多少个槽位到某个主节点

# 如果我们输入一个数字5000的话,又让我们输入节点ID

# 我们输入100的6380这个节点的id后又有提示了,这次我们直接输入all

# 又很长

 

# 接着又很长,有个提示:

 

Do you want to proceed with the proposed reshard plan (yes/no)? yes

# 意思是,是否要继续执行既定的重新分片计划

# 我们选择是

# 下面的操作都是从某一个节点开始移动哈希槽到另一个节点上

# 查看哈希槽信息

redis-cli -h 192.168.222.100 -p 6380

cluster slots

 

# 太多我们就不看了

# 下面说一下槽位定位算法

Redis 集群总共的槽位数是 16384 个,每一个主节点负责维护一部分槽以及槽所映射的键值数据,Redis 集群默认会对要存储的 key 值使用 CRC16 算法进行 hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位,公式为

slot = CRC16(key) % 16383

# 负载均衡

在 Redis 集群负载不均衡的情况下,我们可以使用 rebalance 命令重新分配各个节点负责的槽数量,从而使得各个节点的负载压力趋于平衡,从而提高 Redis 集群的整体运行效率。

redis-cli --cluster rebalance 192.168.222.100:6380

 

# 我们看到确实执行了重新负载的命令

需要注意的是,即使输入 rebalance 命令,但它可能不会执行,当它认为没有必要进行分配时会直接退出,如下所示:

$ redis-cli --cluster rebalance 127.0.0.1:6381

>>> Performing Cluster Check (using node 127.0.0.1:6381)

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

*** No rebalancing needed! All nodes are within the 2.00% threshold.

# 输入命令验证

 

# 上面我们看到12706这个槽位已经被移动到100的6382节点,所以执行set k1 v1命令时直接报错。这是什么原因呢?因为我们上面进入redis命令行的时候使用的命令是

redis-cli -h 192.168.222.100 -p 6380

这个命令连接的redis是单机版的,而非以集群模式连接。根据哈希槽定位算法,k1这key的哈希槽被分配到100的6382节点,所以set值的时候无法成功。

要解决这个办法,我们只需要采用集群模式连接即可,命令如下:

redis-cli -c -h 192.168.222.103 -p 6380

同样道理,我们采用redis客户端工具连接的时候,也需要指定是否以集群模式连接,如图:

 

# 退出redis命令行和容器

Ctrl + c

Ctrl + pq

# 到redis集群安装的一个配置文件目录查看

cd /usr/local/redis-cluster/master-6380/data

cat redis.conf

# 这次就比较乱了

 

该文件的主要信息是:

节点id

节点ip:端口@端口+10000

master或者slave

主节点id(如果本身是主节点就以-代替)

0

然后这一串不知道了

多少个已连接的

# 下面讲一下redis的端口

在redis cluster架构下,每个redis要放开两个端口号,比如一个是6379,另外一个就是加10000的端口号,比如16379

16379端口号是用来进行节点间通信的,也就是cluster bus的东西,集群总线。cluster bus的通信,用来进行故障检测,配置更新,故障转移授权

cluster bus用了另外一种二进制的协议,主要用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。

# 上面我们创建并运行redis的时候没有设置自动重启功能

docker container update --restart=always redis-master-6380 redis-slave-6381 redis-slave-6382

# 查看redis的节点信息

info replication

192.168.222.100:6382> info replication

# Replication

role:master

connected_slaves:0

master_failover_state:no-failover

master_replid:9d16b7c4b9f484fb748ff837ca9992276e32bd54

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:0

second_repl_offset:-1

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

role后面会显示该节点是master或者slave,如果该节点为slave节点,那么还会显示主节点的ip和端口号,master_link_status的值为up表示从节点和主节点的关系已经连接上,为down则表示关系未连接。

我们的redis集群虽然搭建成功了,但是并没有达到我们要的效果,也就是三主六从的效果。实际效果是:

主节点

从节点

100:6380

104:6381

100:6381

103:6381

100:6382

103:6380

104:6382

104:6380

103:6382

下面我们移除100:6382master节点,并分配到100:6380节点上。

# 查看节点信息

cluster nodes

# 找到100:6382节点的id和100:6380节点的id

# 删除100:6382节点

redis-cli --cluster del-node 192.168.222.100:6382 d06230f7438a45927d7bba6aa56cec0b7337ed27

 

主要是最后一句话:

[ERR] Node 192.168.222.100:6382 is not empty! Reshard data away and try again.

意思是该节点不为空,请重新分片数据并重试。

因为100:6382节点上有数据,我们将100:6382上的所有哈希槽都移动到100:6380上

redis-cli --cluster reshard 192.168.222.100:6382 --cluster-from d06230f7438a45927d7bba6aa56cec0b7337ed27 --cluster-to 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f --cluster-slots 4096 --cluster-yes

# 这里的4096不一定准确,因为分配的太松散了,我不可能一个一个的数一下到底多少个

# 而且我也没有找到命令如何查看redis集群某一节点的哈希槽的数量的

 

# 再次查看节点情况

cluster nodes

 

100:6382节点已经没有分配哈希槽了,此时应该可以执行删除命令了。

# 也可以使用如下命令查看该节点信息:

redis-cli --cluster info 192.168.222.100:6382

 

上图是我后面找到的命令。该命令也显示,集群中已经没有了100:6382节点,只剩下四个了。

上图也说明我们将一个主节点的哈希槽重新分片到其他主节点之后,其实可以通过上面的命令查看该节点的哈希槽是否全部重新分片完成。当然,再重新分片的时候也可以使用该命令来查看所有节点的哈希槽分配情况。

看上图,我们可以知道,该命令是在docker容器内部执行的,也就是说要先进入redis容器中,通过指定某一个master节点的ip和端口即可查看全部集群的哈希槽分配情况以及key的简单情况。

而cluster info命令是在连接redis命令行中执行的,显示的是集群的一些简单信息,如下:

 

执行该命令时,不能在登入该节点当中,否则不能正常移除该节点。同时,如果该节点是master节点且还有slave节点的时候,不能先移除该master节点,因为会触发故障自动切换,从节点会变成master节点。

redis-cli --cluster del-node 192.168.222.100:6382 d06230f7438a45927d7bba6aa56cec0b7337ed27

 

由此可见,节点100:6382已经移除完毕!

我们还可以使用其他命令查看

cluster nodes

或者

cluster info

 

已知的集群节点数量为8。

或者

redis-cli --cluster info 192.168.222.103:6380

这些命令的执行地方可以看截图,这里再重申一下

凡是redis-cli(不包括redis-cli --cluster)类的命令都要在进入redis容器之后再连接redis命令行才可以执行,其他的都要在进入redis容器中执行。

不过也不尽然,在redis容器之外,也就是在虚拟机上其实也可以执行,只是需要安装redis-cli命令行工具

此时我们的集群就变成了这样的:

主节点

从节点

100:6380

104:6381

100:6381

103:6381

100:6382

103:6380

104:6382

104:6380

103:6382

变成了四主四从的集群。

你是不是也以为是这样的,我们删除了100:6382master节点,就变成了上图的集群模式。实际上不是这样的,我是在后面删除

100:6381

103:6381

这个节点的时候发现,原来的集群它变了,为了确认我没有看错,我翻看了之前集群信息。

d06230f7438a45927d7bba6aa56cec0b7337ed27 192.168.222.100:6382@16382 master

665fa7b34846eebee7d18e9aa2f75576a97bdca4 192.168.222.104:6380@16380 master

245cfdac475fe50d6ef1a37c43e042d280fecca2 192.168.222.103:6381@16381 slave bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db 192.168.222.100:6381@16381 master

f42465b62e889facf2ab37f92a36566dec0aa419 192.168.222.103:6380@16380 myself,slave d712f9e3331d83412f83107be779f0e51a8d08b3

d712f9e3331d83412f83107be779f0e51a8d08b3 192.168.222.104:6382@16382 master

ca008f89db1d7ade8fa474a4545a310c881997da 192.168.222.104:6381@16381 slave 3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

2290e52c0933bcac9261b213553b738937d0e6e8 192.168.222.103:6382@16382 slave 665fa7b34846eebee7d18e9aa2f75576a97bdca4

3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f 192.168.222.100:6380@16380 master

我们看到原来的master节点分别是:

Master节点

Master节点id

100:6382

d06230f7438a45927d7bba6aa56cec0b7337ed27

104:6380

665fa7b34846eebee7d18e9aa2f75576a97bdca4

100:6381

bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

104:6382

d712f9e3331d83412f83107be779f0e51a8d08b3

100:6380

3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

Slave节点分别是:

Slave节点

Slave节点id

所属master节点id

所属master节点

103:6381

245cfdac475fe50d6ef1a37c43e042d280fecca2

bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

100:6381

103:6380

f42465b62e889facf2ab37f92a36566dec0aa419

d712f9e3331d83412f83107be779f0e51a8d08b3

104:6382

104:6381

ca008f89db1d7ade8fa474a4545a310c881997da

3f7dad8c7c9eabae3a8aa17d8756ca136b8ce54f

100:6380

103:6382

2290e52c0933bcac9261b213553b738937d0e6e8

665fa7b34846eebee7d18e9aa2f75576a97bdca4

104:6380

和我们最初那张图做一个对比

下图是我对上面的图做了修改,发现可能是最初我们搞错了。

主节点

从节点

100:6380

104:6381

100:6381

103:6381

100:6382

104:6382

103:6380

104:6380

103:6382

原来并没有变化。

这不是我们想要的,我们下一步要将100:6381主节点和103:6381从节点以及104:6382和103:6380从集群中移除,最终实现的要求是6380为主节点的端口,6381和6382为从节点的端口。

# 进入192.168.222.100:6380节点容器

docker exec -it redis-master-6380 bash

# 连接redis命令行

redis-cli -c -h 192.168.222.100 -p 6380

# 查看redis集群节点情况

cluster nodes

# 获取到100:6381和103:6381节点id

bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

245cfdac475fe50d6ef1a37c43e042d280fecca2

# 退出redis连接

Ctrl + c

# 将100:6381主节点的哈希槽分配给

# 删除100:6381主节点

redis-cli --cluster del-node 192.168.222.100:6381 bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

 

# 此时我们需要对100:6381进行重新分片,将它的哈希槽分配给其他主节点。

# 但是我们看到104:6382和103:6380这一对主从集群中的从节点正是我们需要最终要的主节点,那么我们可以把104:6382宕机,然后103:6380自动进行故障主从自动切换。此时103:6380变成了主节点,当把104:6382重新启动的时候103:6380依然是主节点。

我们进入104:6382容器中,执行如下命令:

redis-cli -h 192.168.222.104 -p 6382 shutdown

如果我们当初设置的有密码,则需要:

redis-cli -h 192.168.222.104 -p 6382 -a '123456' shutdown

但是我们发现这种方式是不行的,为什么呢?在我们最开始创建运行容器的时候没有添加 --restart=always参数,但是后面我们通过如下命令修改了redis自动重启的命令:

docker container update --restart=always redis-master-6380 redis-slave-6381 redis-slave-6382

所以我们的104:6382宕机之后就自动重启,此时依然是主节点。

 

 

我们看到104:6382依然是主节点,而且还是拥有一个从节点。

既然这样不行,那我们就直接停掉这个容器。

docker stop redis-slave-6382

docker ps

redis-cli --cluster info 192.168.222.104:6380

 

*** WARNING: 192.168.222.103:6380 claims to be slave of unknown node ID d712f9e3331d83412f83107be779f0e51a8d08b3.

这句话的意思是:

***警告:192.168.222.103:6380声称是未知节点ID d712f9e3331d83412f83107be779f0e51a8d08b3的从属节点。

我丢!

竟然没有故障自动进行主从切换。

而且上图中原来的4个主节点被我们干掉一个,就剩余一个了,确实没有自动故障切换。

等我百度了一番之后,回来再查看集群信息:

redis-cli --cluster info 192.168.222.104:6380

 

此时竟然发现103:6380变成了主节点。

那这是什么缘故呢?

可能的原因是,故障自动切换是需要时间的,主节点刚宕掉的时候,从节点没有了主节点就准备进行切换主节点。但是不一定会立马进行主从切换,比如在副本漂移的情况下,是可能不存在单主机节点,也不存在单从节点。此时成对出现的主节点就会自动执行主节点的读写任务,或者指定的节点变成主节点,那么此时我们的103:6380可能就不会启动切换成主节点了。

所以等待一定的时间,大概几分钟时间,如果不存在那些情况,103:6380就自动切换成了主节点。

此时我们的集群情况是:

主节点

从节点

100:6380

104:6381

100:6381

103:6381

100:6382

103:6380

104:6382(宕掉)

104:6380

103:6382

那我们继续删除节点100:6381和103:6381

对100:6381进行reshard,将该节点的哈希槽分配给103:6380

redis-cli --cluster reshard 192.168.222.100:6381 --cluster-from bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db --cluster-to f42465b62e889facf2ab37f92a36566dec0aa419 --cluster-slots 3276 --cluster-yes

上图第一个id是100:6381的主节点id,第二个id是103:6380被分配的主节点的id,3276是我们上图中看到的103:6380中的哈希槽的个数。

再查看集群信息

redis-cli --cluster info 192.168.222.104:6380

 

删除100:6381节点

redis-cli --cluster del-node 192.168.222.100:6381 bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

失败了

 

执行其他命令也有错误:

将100:6381切换成104:6380的从节点

redis-cli -h 192.168.222.100 -p 6381 slaveof 192.168.222.104  6380

 

将当前节点设置为指定nodeid节点的从节点

cluster replicate 665fa7b34846eebee7d18e9aa2f75576a97bdca4

(error) ERR To set a master the node must be empty and without assigned slots.

# 列出某个节点slave列表

cluster slaves 665fa7b34846eebee7d18e9aa2f75576a97bdca4

删除对应节点下的data目录下的配置文件,然后重启该容器

重新删除该节点

redis-cli --cluster del-node 192.168.222.100:6381 bfda95bc9abbed4d4e4c86a4fe6ab8f76a9716db

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北冥牧之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值