一、前言
点此在学习redis集群时可以利用官方网站来完成!
学习redis前面学习了主从复制模式和哨兵模式,但是主从复制是最简单的节点同步方案无法主从自动故障转移;哨兵模式的作用很鸡肋,为什么这么说呢?因为如果企业有100台服务器,那么我们需要到每一台服务器上开启哨兵模式,远程客户端无法连接redis。哨兵可以同时管理多个主从同步方案同时也可以处理主从自动故障转移,通过配置多个哨兵节点可以解决单点网络故障问题,但是单个节点的性能压力问题无法解决。
但是集群解决了前面两个方案的所有问题。
(1)Redis-Cluster采用无中心结构
每个节点都和其它节点通过互ping保持连接,每个节点保存整个集群的状态信息,可以通过连接任意节点读取或者写入数据
(甚至是没有数据的空节点)。
(2)只有当集群中的大多数节点同时fail整个集群才fail
一般情况下是集群当中超过一半以上的节点fail的时候,集群才会fail
(3)整个集群有16384个slot
当需要在 Redis 集群中放置一个key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。
读取一个key时也是相同的算法。
(4)当主节点fail时从节点会升级为主节点
fail的主节点online之后自动变成了从节点
Redis集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用 crc16 算法算出一个结果,
然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,
redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
二、集群的简单介绍
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:
自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
三、什么是哈希槽?
为什么要选择的槽是16384个呢?
crc16会输出16bit的结果,可以看作是一个分布在0-216-1之间的数,redis的作者测试发现这个数对2{14}求模的会将key在0-2^{14-1}之间分布得很均匀,因此选了这个值。
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,
这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
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集群的环境搭建
(1)在server1上进行配置
先关闭之前的redis服务:/etc/init.d/redis_6379 stop
新建一个redis集群目录:mkdir /usr/local/rediscluster
并在 /usr/local/rediscluster目录先下并创建6个目录7001-7006,作为6个
编辑配置文件。编写redis.conf文件
cat redis.conf
port 7000 #根据节点不同在变换
cluster-enabled yes #开启集群
cluster-config-file nodes.conf #集群的配置,配置文件首次启动自动生成 7001,7002,7003,7004,7005,7006
cluster-node-timeout 5000 #请求超时 默认15秒,可自行设置,这里的单位是毫秒
appendonly yes #aof日志开启 有需要就开启,它会每次写操作都记录一条日志
pidfile “/usr/local/rediscluster/7001/redis.pid”
logfile “/usr/local/rediscluster/7001/redis.log”
daemonize yes #redis后台运行
dir “/usr/local/rediscluster/7001”
重启服务:redis-server redis.conf
ps ax 查看7001的运行情况
同样的其余的5个节点做相同的工作 ,配置文件---->重启服务 -----> 查看运行状态
拷贝ruby脚本
在server1上创建redis-cluster集群
要指定一主一从–cluster-replicas 1表示为每一个master创建1个slave
可以看到节点1、2、3为master
节点4、5、6为slave
可以看到集群已经创建好
查看集群信息
测试存储信息
我们可以i看到数据保存在5462个哈希槽中,在7002上
在任意节点都可以获取到信息,但是都会跳转到7002
接下来测试集群的高可用
假设现在我们挂掉7002,key还会保存在7006上
再挂掉7006,key丢失
再次查看发现只有两个master了
再次启动2和6的服务,注意2和6一定是匹配的
查看集群状态,查看到6个节点的状态都正常
数据恢复了!
查看自己的master和slave相对应信息,可以查看到刚才添加的信息,节点2和节点6是相对应的master和cluster
注意:在本次实验中,我们只是宕掉了一个master,接着再宕掉了master对应的slave,但是当集群当中的一半以上的master都down掉以后,集群也会down掉了
如果节点不够用,我们可以添加新的节点
先将redis服务关闭
查看其他6个节点是否运行正常
添加的新节点跟上面的6个节点是一样的
在 /etc/local/rediscluster 下建立7007 和7008 的目录,将7001目录下面的内容拷贝到这两个目录下面。
将目录下面的配置文件对应的内容修改
将服务开启,参考前面6个节点
查看集群信息,看到7007和7008并没有添加到集群里面去,所以我们需要将7007和7008添加到集群中去
添加节点到集群
查看节点信息
发现7007没有哈希槽,尽管新节点没有包含任何哈希槽, 但它仍然是一个主节点, 所以在集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中,所以要添加一个slave
我们将7008添加为7007节点的slave
再次查看节点信息,7007已经有了slave
为新节点分配哈希槽
id为前面接收哈希槽的节点ID
检查可以看到已经分配哈希槽:redis-cli --cluster check 127.0.0.1:7001
通过上面的分配哈希槽,上面分配不均等,可能导致数据不同步,所以我们需要均分哈希槽
查看均分后的哈希槽
均分哈希槽后,数据不会丢失,但是数据会转移。
集群的搭建完成!!