Redis集群是一个由多个节点组成的分布式服务器群,它具有复制、高可用和分片特性;
Redis集群没有中心节点,并且带有复制和故障转移特性,这可以避免单个节点成为性能瓶颈,或者因为某个节点下线而导致整个集群下线;
集群中的主节点负责处理槽(存储数据),从节点则是主节点的复制品;
Redis集群将整个数据库分成16384个槽,数据库中的每个键都属于16384个槽中的其中一个;
集群中的每个主节点都可以负责0到16384个槽,当16384个槽都有节点在负责时,集群进入上线状态,可以执行客户端发送的数据命令;
主节点只会执行和自己负责的槽相关的命令,当节点接收到不属于自己处理的槽的命令时,它会将处理指定槽的节点的地址返回给客户端,而客户端会向正确的节点重新发送命令,这个过程称为“转向”;
Redis 集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
Redis 集群提供了以下两个好处:
Redis Cluster 是Redis的集群实现,内置数据自动分片机制,集群内部将所有的key映射到16384个Slot中,集群中的每个Redis Instance负责其中的一部分的Slot的读写。集群客户端连接集群中任一Redis Instance即可发送命令,当Redis Instance收到自己不负责的Slot的请求时,会将负责请求Key所在Slot的Redis Instance地址返回给客户端,客户端收到后自动将原请求重新发往这个地址,对外部透明。一个Key到底属于哪个Slot由crc16(key)% 16384 决定。
关于集群成员管理,集群的节点(Redis Instance)和节点之间两两定期交换集群内节点信息并且更新,从发送节点的角度看,这些信息包括:集群内有哪些节点,IP和PORT是什么,节点名字是什么,节点的状态(比如OK,PFAIL,FAIL,后面详述)是什么,包括节点角色(master或者 slave)等。
关于可用性,集群由N组主从Redis Instance组成。主可以没有从,但是没有从 意味着主宕机后主负责的Slot读写服务不可用。一个主可以有多个从,主宕机时,某个从会被提升为主,具体哪个从被提升为主,协议类似于Raft,参见这里。如何检测主宕机?Redis Cluster采用quorum+心跳的机制。从节点的角度看,节点会定期给其他所有的节点发送Ping,cluster-node-timeout(可配置,秒级)时间内没有收到对方的回复,则单方面认为对端节点宕机,将该节点标为PFAIL状态。通过节点之间交换信息收集到quorum个节点都认为这个节点为PFAIL,则将该节点标记为FAIL,并且将其发送给其他所有节点,其他所有节点收到后立即认为该节点宕机。从这里可以看出,主宕机后,至少cluster-node-timeout时间内该主所负责的Slot的读写服务不可用。
Redis集群配置之前需要依赖一些相关库配置,因此需要先安装以下相关库;
(1) 确保系统安装zlib,否则gem install会报(no such file to load -- zlib)
# download:zlib-1.2.8.tar.gz
# tar –zxvfzlib-1.2. 8.tar.gz
# cd zlib-1.2.8
#./configure
# make
# makeinstall
(2) 安装ruby:version(2.2.2)
# download:ruby-2.2.2.tar.gz
# tar –zxvf ruby-2.2.2.tar.gz
# cd /ruby-2.2.2
#./configure-prefix=/usr/local/ruby
# make
# makeinstall
# cp ruby/usr/local/bin
安装完成后可以查看相应的版本信息:
# ruby –v
(3)安装rubygem:version(1.8.16)
# down rubygems-2.4.7.tar.gz
# tar –zxvf rubygems-2.4.7.tar.gz
# cd rubygems-2.4.7
# rubysetup.rb
# cp rubygems-2.4.7/bin/gem/usr/local/bin
安装完成后可以查看相应的版本信息:
# gem –v
(4)安装redis与ruby接口gem-redis:version(3.0.6)
gem install -l /data/soft/redis-3.0.6.gem
集群配置案例:
1、 redis源码下载,make安装;
$ tar xzf redis-3.0.1.tar.gz
$ cd redis-3.0.1
$ make
The binaries that are nowcompiled are available in the src directory. Run Redis with:
2、新建6个instance,3个master,3个slave;
新建实例时需要更改每一个实例redis.conf的内容,需要绑定网卡IP以及修改相应端口号,集群配置如下:
daemonize yes #是否以后台进程运行,默认为no
pidfile /var/run/redis_xxxx.pid #如以后台进程运行,则需指定一个pid文件
logfile /var/log/redis.log #日志记录方式,默认值为stdout
dbfilename dump.rdb #本地数据库文件名,默认值为dump.rdb
dir ./ #本地数据库存放路径,默认值为 ./
bind x.x.x.x #绑定主机IP,必须绑定相应的网卡IP
port xxxx #监听端口,默认为6379
cluster-enabledyes #是否启用集群
cluster-config-file/user/software/redis/nodefile/nodes-设置为相应端口号xxxx.conf
cluster-node-timeout15
本例中的最后相应master与slave配置如下:
master:
ip port
--------------------------------------------------------
172.168.10.252 7000
172.168.10.253 7000
172.168.10.254 7000
slave
ip port
--------------------------------------------------------
172.168.10.252 7001
172.168.10.253 7001
172.168.10.254 7001
3、创建集群节点:
创建集群的操作可以通过使用位于Redis安装文件夹内的redis-trib.rb来完成,
使用redis任意一实例src下redis-trib.rb进行集群节点配置;
其中—replicas表示设置slave节点
如不设置slave节点则 --replicas 0:
[root@node01 src]# ./redis-trib.rb create --replicas 0172.168.10.252:7000 172.168.10.253:7000 172.168.10.254:7000
若设置一个slave节点则 --replicas 1:
[root@node01 src]# ./redis-trib.rb create --replicas 1172.168.10.252:7000 172.168.10.253:7000 172.168.10.254:7000 172.168.10.252:7001172.168.10.253:7001 172.168.10.254:7001
>>> Creating cluster
Connecting to node 172.168.10.252:7000: OK
Connecting to node 172.168.10.253:7000: OK
Connecting to node 172.168.10.254:7000: OK
Connecting to node 172.168.10.252:7001: OK
Connecting to node 172.168.10.253:7001: OK
Connecting to node 172.168.10.254:7001: OK ###首先尝试连接给定的六个节点,检查它们是否存在
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
172.168.10.252:7000
172.168.10.253:7000
172.168.10.254:7000
Adding replica 172.168.10.253:7001 to 172.168.10.252:7000
Adding replica 172.168.10.252:7001 to 172.168.10.253:7000
Adding replica 172.168.10.254:7001 to 172.168.10.254: 7000 ###在确定这些节点都是可连接之后,redistrib.rb 再将7000设置为主节点,而7001、7001和7001则分别被设置为三个主节点的从节点
M: 50a69c4c99413b86e1afbe0eee499b11d0ea4bb7 172.168.10.252:7000
slots:0-5460 (5461slots) master
M: 3c7a80e633fc9318c9adbb95d56109f11e0a5f39 172.168.10.253:7000
slots:5461-10922 (5462slots) master
###对于三个主节点,redis-trib.rb 会分别为它们指派5461、5462和5461个槽(默认情况下使用平均分配)
M: 4e20023a126560c39832e56456898a54816b6daa 172.168.10.254:7000
slots:10923-16383(5461 slots) master
S: 62078686a716e7ee402725fcd1853cbf8f127355 172.168.10.252:7001
replicates3c7a80e633fc9318c9adbb95d56109f11e0a5f39
S: f1409c7ec4619f6c964cf7fa413710009e55ef04 172.168.10.253:7001
replicates50a69c4c99413b86e1afbe0eee499b11d0ea4bb7
S: e16542a68d0a5b0aec0e3cf0d85ad37638677aad 172.168.10.254:7001
replicates 4e20023a126560c39832e56456898a54816b6daa
Can I set the aboveconfiguration? (type 'yes' to accept): yes
###这个配置没问题的话,就可以键入 yes 并按下回车
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
….
….
…
###redis-trib.rb 会对集群进行测试,检查是否每个节点都按照原先展示的配置设置好了
…
[OK] All nodesagree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384slots covered.
至此集群配置完成.
[root@node01 src]# ./redis-cli -h 172.168.10.252 -p 7000
172.168.10.252:7000> get date
(nil)
172.168.10.252:7000> get aa
(nil)
172.168.10.252:7000> get name
(error) MOVED 5798 172.168.10.253:7000
172.168.10.252:7000>
使用集群客户端向集群发送命令请求
目前主要的 Redis 集群客户端(或者说,支持集群功能的 Redis 客户端)有以下这些:
1、redis-rb-cluster:antirez 使用Ruby 编写的 Redis 集群客户端,集群客户端的官方实现;
2、predis:Redis的 PHP 客户端,支持集群功能;
3、jredis:Redis的 JAVA 客户端,支持集群功能;
4、StackExchange.Redis:Redis 的C# 客户端,支持集群功能;
5、内置的 redis-cli :在启动时给定 -c 参数即可进入集群模式,支持部分集群功能;