文章目录
一、redis集群简介
1、集群
集群是一组相互独立的、通过高速网络互相联通的节点,构成了一个组,并以单一系统的模式加以管理。一个客户与集群相互作用时,集群就是一个独立的服务器。
集群技术是一种通用的技术,其目的是为了解决单机运算能力的不足、IO能力的不足、提高服务的可靠性、获得规模可扩展能力,降低整体方案的运维成本(运行、升级、维护成本)。能在大流量访问下提供稳定的业务,集群化是存储的必然形态。
2、redis集群
Redis 集群是一个分布式(distributed)、容错(fault-tolerant)的 Redis 实现, 集群可以使用的功能是普通单机 Redis 所能使用的功能的一个子集(subset),提供在多个Redis节点之间共享数据的程序集。。
Redis 集群并不支持同时处理多个键的 Redis 命令,因为这需要在多个节点间移动数据,这样会降低redis集群的性能,在高负载的情况下可能会导致不可预料的错误。
Redis 集群通过分区来提供一定程度的可用性,即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
3、redis集群的优势
缓存永不宕机:启动集群,永远让集群的一部分起作用。主节点失效了子节点能迅速改变角色成为主节点,整个集群的部分节点失败或者不可达的情况下能够继续处理命令;
迅速恢复数据:持久化数据,能在宕机后迅速解决数据丢失的问题;
Redis可以使用所有机器的内存,变相扩展性能;
使Redis的计算能力通过简单地增加服务器得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长;
Redis集群没有中心节点,不会因为某个节点成为整个集群的性能瓶颈;
异步处理数据,实现快速读写。
4、redis集群工作原理
所有的节点通过服务通道直接相连(PING-PONG机制),各个节点之间通过二进制协议优化传输的速度和带宽。
客户端与节点之间通过 ascii 协议进行通信
客户端与节点直连,不需要中间 Proxy 层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
5、哈希槽
Redis集群(Cluster)并没有选用一致性哈希,而是采用了哈希槽(SLOT)的这种概念。主要的原因就是一致性哈希算法对于数据分布、节点位置的控制并不是很友好(整个哈希空间是一个虚拟圆环,数据顺时针存储到最近结点)。
首先哈希槽其实是两个概念,第一个是哈希算法。Redis Cluster的hash算法不是简单的hash(),而是crc16算法,一种校验算法。
另外一个就是槽位的概念,空间分配的规则。其实哈希槽的本质和一致性哈希算法非常相似,不同点就是对于哈希空间的定义。一致性哈希的空间是一个圆环,节点分布是基于圆环的,无法很好的控制数据分布。而Redis Cluster的槽位空间是自定义分配的,类似于Windows盘分区的概念。这种分区是可以自定义大小,自定义位置的。
Redis Cluster包含了16384个哈希槽,每个Key通过计算后都会落在具体一个槽位上,而这个槽位是属于哪个存储节点的,则由用户自己定义分配。例如机器硬盘小的,可以分配少一点槽位,硬盘大的可以分配多一点。如果节点硬盘都差不多则可以平均分配。所以哈希槽这种概念很好地解决了一致性哈希的弊端。
另外在容错性和扩展性上,表象与一致性哈希一样,都是对受影响的数据进行转移。而哈希槽本质上是对槽位的转移,把故障节点负责的槽位转移到其他正常的节点上。扩展节点也是一样,把其他节点上的槽位转移到新的节点上。
但一定要注意的是,对于槽位的转移和分派,Redis集群是不会自动进行的,而是需要人工配置的。所以Redis集群的高可用是依赖于节点的主从复制与主从间的自动故障转移。
Redis 集群内置了16384个哈希槽,每个key通过
CRC16算法校验后对16384取模
来决定放置哪个槽。集群的每个节点负责一部分hash槽
举例:
比如当前集群有3个节点,那么:
节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.
这种结构很容易添加或者删除节点.
比如如果我想新添加个节点D,我需要从节点 A, B, C中得部分槽到D上.
如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可.
由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
6、容错
-
集群中的节点不断的 PING 其他的节点,当一个节点向另一个节点发送 PING 命令, 但是目标节点未能在给定的时限内回复, 那么发送命令的节点会将目标节点标记为 PFAIL(possible failure,可能已失效)。
-
当节点接收到其他节点发来的信息时, 它会记下那些被其他节点标记为失效的节点。 这被称为失效报告(failure report)。
-
如果节点已经将某个节点标记为 PFAIL , 并且根据节点所收到的失效报告显式, 集群中的大部分其他主节点也认为那个节点进入了失效状态, 那么节点会将那个失效节点的状态标记为 FAIL 。
-
一旦某个节点被标记为 FAIL , 关于这个节点已失效的信息就会被广播到整个集群, 所有接收到这条信息的节点都会将失效节点标记为 FAIL 。
简单来说, 一个节点要将另一个节点标记为失效, 必须先询问其他节点的意见, 并且得到大部分主节点的同意才行。
如果被标记为 FAIL 的是从节点, 那么当这个节点重新上线时, FAIL 标记就会被移除。 一个从节点是否处于 FAIL 状态, 决定了这个从节点在有需要时能否被提升为主节点。
如果一个主节点被打上 FAIL 标记之后, 经过了节点超时时限的四倍时间, 再加上十秒钟之后, 针对这个主节点的槽的故障转移操作仍未完成, 并且这个主节点已经重新上线的话, 那么移除对这个节点的 FAIL 标记。在不符合上面的条件后,一旦某个主节点进入 FAIL 状态, 如果这个主节点有一个或多个从节点存在, 那么其中一个从节点会被升级为新的主节点, 而其他从节点则会开始对这个新的主节点进行复制。
二、实验
实验环境:
server1虚拟机作Redis缓存数据库:
ip为:172.25.76.1
关闭防火墙及selinux
2、搭建redis集群
在server1(master)上面:
步骤一:设置内核分配内存策略
overcommit_memory是一个内核对内存分配的一种策略。 具体可见/proc/sys/vm/overcommit_memory下的值
- overcommit_memory取值又三种分别为0, 1, 2
overcommit_memory=0, 表示内核将检查是否有足够的可用内存供应用进程使用;
如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。 - overcommit_memory=1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
- overcommit_memory=2, 表示内核允许分配超过所有物理内存和交换空间总和的内存
cd /proc/sys/vm
cat overcommit_memory
echo 1 > overcommit_memory
cat overcommit_memory
步骤二:在server1上创建 6个Redis 节点
首先在 server1 机器上 /usr/local/目录下创建 redis_cluster 目录;
在 redis_cluster 目录下,创建名为7001、7002、7003、7004、7005、7006的结点目录
cd /usr/local
mkdir redis-cluster
ls
cd redis-cluster/
mkdir 700{1..6}
ls
步骤三:对六个结点进行配置
首先配置7001结点:
cd 7001
vim redis.conf
port 7001 #结点名称
cluster-enabled yes #开启集群
cluster-config-file nodes.conf #集群的配置,配置文件首次启动自动生成
cluster-node-timeout 15000 #请求超时 默认15秒,可自行设置
appendonly yes #aof日志开启 有需要就开启,它会每次写操作都记录一条日志
redis-server ./redis.conf #开启结点服务
发现直此时一直占用我们的终端,修改配置文件
ls #查看到生成配置文件
vim redis.conf
daemonize yes #在后面加上这一行后台运行
redis-server ./redis.conf
后台运行,查看服务进程
ps ax
同理配置其他5个节点,修改配置文件结点名称并且开启服务
步骤四: 搭建集群
现在已经有了六个正在运行中的 Redis 实例, 接下来我们需要使用这些实例来创建集群, 并为每个节点编写配置文件。
通过使用 Redis 集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。
创建redis-trib.rb环境,要将Redis 源码的 src 文件中的改命令的配置文件复制到系统命令的环境下才能使用改命令
安装ruby
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
–cluster-replicas 1 #为集群中的每个主节点创建一个从节点
之后跟着的其他参数则是这个集群实例的地址列表,3个master3个slave redis-trib 会打印出一份预想中的配置给你看, 如果你觉得没问题的话, 就可以输入 yes , redis-trib 就会将这份配置应用到集群当中,让各个节点开始互相通讯,最后可以得到如下信息:
步骤五:测试
redis-cli --cluster info 127.0.0.1:7001 #查看主从信息
redis-cli -c -p 7001 #进入7001结点
info #查看信息
set name liu #定义key-value
get name #查看value值
测试集群的高可用:
关闭节点2(master节点之一)
redis-cli -c -p 7002
SHUTDOWN
ps ax #7002进程已经消失
测试集群能否正常工作
redis-cli -c -p 7001 #进入7001结点
get name #查看value值
查看结点信息
redis-cli --cluster info 127.0.0.1:7001
此时7002的备结点7006已经代替7002,作为主节点提供服务
测试集群能否正常工作
redis-cli -c -p 7001 #进入7001结点
get name #查看value值
继续关闭7006结点
redis-cli -c -p 7006
SHUTDOWN
查看结点信息
redis-cli --cluster info 127.0.0.1:7001
测试集群能否正常工作
redis-cli -c -p 7001 #进入7001结点
get name #查看value值
3、redis集群中添加新结点
添加新的节点的基本过程就是添加一个空的节点然后移动一些数据给它。有两种情况
- 添加一个主节点
- 添加一个从节点
(添加从节点时需要将这个新的节点设置为集群中某个节点的复制)
步骤一:创建新的节点并开启服务
cd /usr/local/redis-cluster/7002
mkdir 7007 7008
ls
cp 7001/redis.conf 7007/
cp 7001/redis.conf 7008/
cd 7007
vim redis.conf
redis-server redis.conf
cd ../7008
vim redis.conf
redis-server redis.conf
ps ax
步骤二:将新节点7007添加到集群
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001
查看新节点已经加入集群中:
redis-cli -c -p 7007
127.0.0.1:7007> cluster nodes
步骤三:为新节点7007添加从节点7008
redis-cli --cluster add-node 127.0.0.1:7007 --cluster-slave --cluster-master-id 29e1273f896c3d65bb693a7b533d6d23368182a5
查看新节点已经加入集群中:
redis-cli -c -p 7007
127.0.0.1:7007> cluster nodes
注意:新节点现在已经连接上了集群, 成为集群的一份子, 并且可以对客户端的命令请求进行转向了, 但是和其他主节点相比, 新节点还有两点区别
:
- 新节点没有包含任何数据, 因为它没有包含任何哈希槽.
- 尽管新节点没有包含任何哈希槽, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中。
4、集群重新分片
使用 redis-trib 程序, 将集群中的某些哈希桶移动到新节点里面, 新节点就会成为真正的主节点
(1)手动分配哈希槽
redis-cli --cluster reshard 127.0.0.1:7007
选完哈希槽个数后,又会问我们需要覆盖的节点id是什么,这个id就是我们新创建的节点id。然后让我们输入源节点,如果这里我们输入all的话,他会随机的从所有的节点中抽取300个作为新节点的哈希槽。
查看7007分配的哈希槽:
redis-cli --cluster info 127.0.0.1:7001
发现7007分配到了指定的哈希槽注意:因为哈希槽的数量是固定的,所以新的节点指定所分配到的哈希槽是其它主节点提供的,但是手动分配的哈希槽可能在使用时会出现问题,因此不建议使用该方式进行分配
(2)自动平均分配哈希槽
redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 127.0.0.1:7001
测试:
查看7007节点否分配到哈希槽
redis-cli --cluster check 127.0.0.1:7001
测试数据同步
redis-cli -c -p 7007
127.0.0.1:7007> info
127.0.0.1:7007> get name
数据同步成功
5、移除节点
(1)移除从Slave节点
redis-cli --cluster del-node 127.0.0.1:7008 d68359290c4015c7ca728e57edfe6298eeee1e6d
查看节点是否移除
redis-cli --cluster reshard 127.0.0.1:7001
(1)移除Master节点
删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点(目前只能把被删除master的slot迁移到一个节点上)
步骤一:查看7007节点上的哈希槽个数
redis-cli --cluster info 127.0.0.1:7007
步骤二:移除master的全部slot
查看各节点哈希槽个数
redis-cli --cluster info 127.0.0.1:7001
此时7007节点哈希槽已经全部转移到7001节点上
步骤三:删除7007节点
redis-cli --cluster del-node 127.0.0.1:7007 29e1273f896c3d65bb693a7b533d6d23368182a5
查看7007节点是否删除:
redis-cli --cluster info 127.0.0.1:7001
主节点7007删除成功
来源:CSDN
作者:CapejasmineY
链接:https://blog.csdn.net/CapejasmineY/article/details/104175758