一、Redis集群介绍
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令.
Redis 集群的优势:
1.自动分割数据到不同的节点上。
2.整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
二、Redis 集群的数据分片
Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

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节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
三、什么是哈希槽?
Redis 集群没有使用一致性hash, 而是引入了哈希槽的概念。
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽。
这种结构很容易添加或者删除节点,并且无论是添加删除或者修改某一个节点,都不会造成集群不可用的状态。
使用哈希槽的好处就在于可以方便的添加或移除节点。
当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;
当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;
在这一点上,我们以后新增或移除节点的时候不用先停掉所有的 redis 服务。

“用了哈希槽的概念,而没有用一致性哈希算法,不都是哈希么?这样做的原因是为什么呢?”
Redis Cluster是自己做的crc16的简单hash算法,没有用一致性hash。
Redis的作者认为它的crc16(key) mod 16384的效果已经不错了,
虽然没有一致性hash灵活,但实现很简单,节点增删时处理起来也很方便。

“为了动态增删节点的时候,不至于丢失数据么?”
节点增删时不丢失数据和hash算法没什么关系,不丢失数据要求的是一份数据有多个副本。
“还有集群总共有2的14次方,16384个哈希槽,那么每一个哈希槽中存的key 和 value是什么?”,当你往Redis Cluster中加入一个Key时,会根据crc16(key) mod 16384计算这个key应该分布到哪个hash slot中,一个hash slot中会有很多key和value。
你可以理解成表的分区,使用单节点时的redis时只有一个表,所有的key都放在这个表里;
改用Redis Cluster以后会自动为你生成16384个分区表,你insert数据时会根据上面的简单算法来决定你的key应该存在哪个分区,
每个分区里有很多key。

四、高可用redis cluster集群的实现过程:
开始之前先关闭前面实验所有主机的Redis

/etc/init.d/redis_6379 stop

在server1上

[root@server1 ~]# mkdir /usr/local/rediscluster  创建目录
[root@server1 ~]# cd /usr/local/rediscluster/
[root@server1 rediscluster]# ls
[root@server1 rediscluster]# mkdir 700{1..6} 创建六个以端口号为名字的子目录
[root@server1 rediscluster]# ls
7001  7002  7003  7004  7005  7006
[root@server1 rediscluster]# cd 7001
[root@server1 7001]# ls
[root@server1 7001]# vim redis.conf  编辑一个最少选项的集群的配置文件
[root@server1 7001]# cat redis.conf 
port 7001 端口7001
cluster-enabled yes 开启集群
cluster-config-file nodes.conf 集群的配置,配置文件首次启动自动生成 
cluster-node-timeout 5000 请求超时  默认5秒,可自行设置
appendonly yes of日志开启  有需要就开启,它会每次写操作都记录一条日志
pidfile "/usr/local/rediscluster/7001/redis.pid"   pid存放位置
logfile "/usr/local/rediscluster/7001/redis.log"  日志存放位置
daemonize yes   开启后台运行不占用终端
dir "/usr/local/rediscluster/7001"    指定当前配置文件目录
[root@server1 7001]# redis-server redis.conf  启动
[root@server1 7001]# ls  启动后会生成一系列文件
appendonly.aof  nodes.conf  redis.conf  redis.log  redis.pid
[root@server1 7001]# redis-cli -p 7001  
127.0.0.1:7001> info

redis集群初始化 redis集群rehash_linux


将写好的配置文件放入其他子目录中

[root@server1 7001]# cp redis.conf ../7002/
[root@server1 7001]# cp redis.conf ../7003/
[root@server1 7001]# cp redis.conf ../7004/
[root@server1 7001]# cp redis.conf ../7005/
[root@server1 7001]# cp redis.conf ../7006/

编辑并启动

redis集群初始化 redis集群rehash_Redis_02


redis集群初始化 redis集群rehash_redis_03

ps ax  查看状态

redis集群初始化 redis集群rehash_redis集群初始化_04


在server1上创建redis-cluster集群

[root@server1 ~]# redis-cli --cluster help 帮助

redis集群初始化 redis集群rehash_数据_05

[root@server1 ~]# redis-cli --cluster create --cluster-replicas 1 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

这个命令在这里用于创建一个新的集群, 选项–replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
之后跟着的其他参数则是这个集群实例的地址列表,3个master3个slave redis-trib 会打印出一份预想中的配置给你看, 如果你觉得没问题的话, 就可以输入 yes , redis-trib 就会将这份配置应用到集群当中,让各个节点开始互相通讯

redis集群初始化 redis集群rehash_数据_06


redis集群初始化 redis集群rehash_数据_07

集群已经创建好   三主三从
master:7001/7002/7003
slave:7004/7005/7006

redis集群初始化 redis集群rehash_redis集群初始化_08


查询7002master的slave

redis集群初始化 redis集群rehash_redis_09


redis集群初始化 redis集群rehash_数据_10


查看7005的master

[root@server1 ~]# redis-cli -c -p 7005
127.0.0.1:7005> info

redis集群初始化 redis集群rehash_redis集群初始化_11


redis集群初始化 redis集群rehash_redis_12


查看创建的westos(数据)存放位置

redis集群初始化 redis集群rehash_数据_13


redis集群初始化 redis集群rehash_数据_14


五、添加一个新节点

添加新的节点的基本过程就是添加一个空的节点然后移动一些数据给它,有两种情况,添加一个主节点和添加一个从节点(添加从节点时需要将这个新的节点设置为集群中某个节点的复制)

redis集群初始化 redis集群rehash_linux_15


复制配置文件到新的节点目录中

[root@server1 7007]# vim redis.conf 
[root@server1 7007]# cat redis.conf 
port 7007
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
pidfile "/usr/local/rediscluster/7007/redis.pid"
logfile "/usr/local/rediscluster/7007/redis.log"
daemonize yes
dir "/usr/local/rediscluster/7007"
[root@server1 7007]# redis-server redis.conf
[root@server1 7008]# vim redis.conf 
[root@server1 7008]# cat redis.conf 
port 7008
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
pidfile "/usr/local/rediscluster/7008/redis.pid"
logfile "/usr/local/rediscluster/7008/redis.log"
daemonize yes
dir "/usr/local/rediscluster/7008"
[root@server1 7008]# redis-server redis.conf 
[root@server1 7008]# ps ax  查看状态

redis集群初始化 redis集群rehash_linux_16


添加新建节点到现有的集群中

[root@server1 7008]# redis-cli --cluster help 查看帮助

redis集群初始化 redis集群rehash_Redis_17


redis集群初始化 redis集群rehash_数据_18


第一个参数是新节点的地址,第二个参数是任意一个已经存在的节点的IP和端口. 我们可以看到新的节点已经添加到集群中:

新节点现在已经连接上了集群, 成为集群的一份子, 并且可以对客户端的命令请求进行转向了, 但是和其他主节点相比, 新节点还有两点区别:

新节点没有包含任何数据, 因为它没有包含任何哈希槽.

尽管新节点没有包含任何哈希槽, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中。

redis集群初始化 redis集群rehash_redis集群初始化_19


添加一个从节点slave节点并指定其master节点为7007

若不指定指定添加的这个从节点的主节点,这种情况下系统会在其他的复制集中的主节点中随机选取一个作为这个从节点的主节点。

redis集群初始化 redis集群rehash_linux_20


redis集群初始化 redis集群rehash_redis集群初始化_21


给新节点分配哈希槽

redis集群初始化 redis集群rehash_redis_22


redis集群初始化 redis集群rehash_Redis_23


redis集群初始化 redis集群rehash_Redis_24


可以看到哈希槽都是从其他节点上索取的,分配不均匀

redis集群初始化 redis集群rehash_redis集群初始化_25


均匀分配哈希槽

[root@server1 7008]# redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 127.0.0.1:7001

redis集群初始化 redis集群rehash_redis集群初始化_26


redis集群初始化 redis集群rehash_linux_27


redis集群初始化 redis集群rehash_redis集群初始化_28