redis集群------------(redis cluster集群——高可用)
1.概述
在前面的文章中介绍过了redis的主从和哨兵两种集群方案,redis从3.0版本开始引入了redis-cluster(集群)。
从主从-哨兵-集群可以看到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之后自动变成了从节点
edis集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用 crc16 算法算出一个结果,
然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,
redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
2.什么是哈希槽?
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 Cluster中有多个节点,每个节点都负责进行数据读写操作,每个节点之间会进行通信。
meet操作:
节点之间会相互通信,而meet操作是节点之间完成相互通信的基础,meet操作有一定的频率和规则
3.Redis的集群搭建
做实验之前,将之前做的redis关掉:
/etc/init.d/redis_6379 stop
第一步:搭建集群环境使用7001到7006搭建六个集群节点
mkdir /usr/local/rediscluster
cd /usr/local/rediscluster
ls
mkdir 700{1..6}
第二步: 每个节点的目录在里面写配置文件redis.conf
cd 7001/
vim redis.conf
port 7001 /端口7001
cluster-enabled yes /开启集群
cluster-config-file nodes.conf /集群的配置,配置文件首次启动自动生成 7001
cluster-node-timeout 5000 /请求超时 默认5秒,可自行设置
appendonly yes /aof日志开启 有需要就开启,它会每次写操作都记录一条日志
pidfile "/usr/local/rediscluster/7001/redis.pid"
logfile "/usr/local/rediscluster/7001/redis.log"
daemonize yes
dir "/usr/local/rediscluster/7001"
redis-server redis.conf
ps aux | grep redis-server
其他5个目录作法一样,不再赘述 ,唯一不同就是每个配置文件要写对应的号(例如7002目录下的配置文件中相应的号就是7002)
可以把7001配置好的文件直接发送到每个目录中,进行相应的改变即可:
cp redis.conf ../7002
cp redis.conf ../7003
cp redis.conf ../7004
cp redis.conf ../7005
cp redis.conf ../7006
cd 7002/
vim redis.conf
redis-server redis.conf
...
cd 7006/
vim redis.conf
redis-server redis.conf
6个目录做好以后查看端口信息:
redis-cli -p 700{1..6}
127.0.0.1:7001> info
# Cluster
cluster_enabled:1 #表示集群状态是激活的
第三步:在server1上创建redis-cluster集群
cd redis-5.0.3/
cd src
cp redis-trib.rb /usr/local/bin
[root@server1 src]# redis-trib.rb #执行此命令,这是官网提供的命令
/usr/bin/env: ruby: No such file or directory 报错,需要安装ruby
yum install ruby -y
redis-trib.rb
redis-cli --cluster help #根据提示创建集群
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 #创建集群
创建成功:
第四步:查看集群节点对应关系:
redis-cli --cluster info 127.0.0.1:7001 #查看集群信息
此时7001 7002 7003作为master,并且每个都有一个slave
无中心检测
[root@server1 src]# redis-cli -c -p 7001
127.0.0.1:7001> set name xiaoxu #自动跳转到7002上
-> Redirected to slot [5798] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get name
"xiaoxu"
127.0.0.1:7002>
测试集群的高可用
当我们宕掉一个master,会有它的slave来接替:
[root@server1 src]# redis-cli -c -p 7003
127.0.0.1:7003> get name
-> Redirected to slot [5798] located at 127.0.0.1:7002
"xiaoxu"
127.0.0.1:7002> shutdown
not connected>
此时查看集群信息:
redis-cli --cluster info 127.0.0.1:7004
7004作为新的master来顶替7002
如果宕掉slave顶替的master,整个集群就不能用了:(也就是说宕掉7004)
[root@server1 src]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7004
"xiaoxu"
127.0.0.1:7004> shutdown
not connected>
此时查看集群信息:
redis-cli --cluster info 127.0.0.1:7001
同时,也读不到name信息了:
[root@server1 src]# redis-cli -c -p 7001
127.0.0.1:7001> get name
(error) CLUSTERDOWN The cluster is down
127.0.0.1:7001>
那么,怎么恢复集群呢?
重新加载7002和7004的配置文件:
cd /usr/local/rediscluster/7002/
cat appendonly.aof #其中存储了之前的数据
redis-server redis.conf
ps aux | grep redis-server
可以看出,7002已经恢复
同理,7004恢复和7002一样
全部恢复成功!!!!
此时查看集群信息:
redis-cli --cluster info 127.0.0.1:7001
这时候,7001 7003 7004作为master
并且,之前的信息也能读到了
如何给集群中添加节点呢?
第一步:创建两个新的节点7007 7008
具体步骤和上面创建一样
第二步:添加节点7007(master的添加)
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001 #7001引路
redis-cli -c -p 7007 #查看到此时7007作为master,但没有slave,也没有分配的槽
第三步: 添加节点7008:(slave的添加,master为7007)
[root@server1 7008]# redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7007 --cluster-slave --cluster-master-id c9b900b70f98332ad357519533115c01b70db69f
再次查看集群信息
redis-cli --cluster info 127.0.0.1:7001 #查看到此时7007作为master,有slave,但没有分配的槽
第四步:均匀分配哈希槽
redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 127.0.0.1:7001
再次查看集群信息:
redis-cli --cluster info 127.0.0.1:7001 #哈希槽分配均匀
这时候,读name信息时发现被存到了7007的哈希槽中
[root@server1 7008]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7007
"xiaoxu"
127.0.0.1:7007>