共计 28740 个字符,预计需要花费 72 分钟才能阅读完成。
Redis3.0 最大的特点就是有了 cluster 的能力,使用 redis-trib.rb 工具可以轻松构建 Redis Cluster。Redis Cluster 采用无中心结构,每个节点保存数据和整个集群状态, 每个节点都和其他所有节点连接。节点之间使用 gossip 协议传播信息以及发现新节点,这种结构和 Cassandra 很相似,Cassandra 节点可以转发请求。Redis 集群中节点不作为 client 请求的代理,client 根据 node 返回的错误信息重定向请求。
一、集群特性
1. 数据可以在 cluster 的多个 node 之间进行共享;
2. 一次请求处理多批 key 的命令将不再被支持,因为这些命令处理的 key 可能在不同的 node 之间,使用了它们反而会降低 cluster 的性能;
3. 提供高 HA,即某个 node failed 后 cluster 依旧提供高可用性。
cluster 提供如下能力保证:
1. 在 cluster 内自动把数据划分到不同的 set 上;
2. 当集群中一小群机器出现网络故障时或者其他种类的 failure 时,cluster 要保证系统继续可用;
redis 的每个 node 启动后占用两个 port 6379 & 16379。redis 通过 port 6379 继续对 client 提供服务,client 通过 redis 独有的文本协议与 node 进行通信,所以这个 port 被成为 client port or command port。redis node 通过 port 16379 与 cluster 内部的其他 node 进行二进制形式的通信,所以被称为 data port or bus port。通过 port 16379,node 之间进行 failure detection(探活)、configure update(配置更新)、failure authorization(失败确认)。如果 node 使用别的端口作为 command port,那么 data port 一定是 command port + 10000。
两个不同的 cluster 之间也可以通过 data port 进行 data migration。
二、分片
redis cluster 内部没用提供一致性 hash 算法来保证集群的可伸缩能力,而是通过简单的 crc16 hash 算法来进行 sharding,所以它最多提供 16384 个 slot。如果 cluster 有三个 node,分别为 A and B and C,则 A 负责 0 – 5500 slots,B 负责 5501 – 11000 slots,C 负责 11001 – 16383 slots。进行扩容的时候,就得在不同的 node 之间进行 slots 的迁移,不需要关机,也不会出现服务不可用现象。
cluster 内部每个 node(也成为一个 instance)由一个 master 和多个 slave 构成,当 master fail 的时候,可以通过选举机制选出一个 slave 代替 master。
Redis Cluster 不提供强一致性。例如 cluster 接受了一个写请求,给 client 返回 ok,这个写请求的内容也可能丢失。因为其写流程如下:
1 master B 接受了一个写请求;
2 B 写成功,返回 ok 给 client;
3 B 把数据广播给 slaves(B1、B2、B3)
如果第二步执行完毕后,B crash 了,则会发生数据不一致现象。这与传统的 DBMS 类似,它们接收了写请求后,每隔 1S 才会把数据写入 disk,这么做也是在性能和一致性之间做一个平衡。
如果用户对数据的一致性要求比较高,Redis 可能也会兼顾这种需求,将来会提供相应的选项,让 redis 中的 slave 没用成功的接受数据之前不会给 client 返回 ok 给 client。即先执行 step 3,然后再执行 step 2。
一致性还有一种场景。假设有 client Z,与 cluster 内各个 node A and B and C,以及各个 node 的 replica A1 and B1 and C1,Z 与 B 之间连接正常,但是 B 与 B1 以及 cluster 内其他 nodes 连接失败。如果 Z 发起 write request,那么 B 会给他返回 ok,但是 B1 无法获取到相应的数据,这就要求写的时候也要把 node 与 cluster 内其他的成员的探活也要考虑在内。基本要求就是,写时间周期要大于探活时间周期(node timeout)。当 node B timeout 之后,master B 会自动进入 failing 状态,拒绝外部 client 的连接请求,而 cluster 则会选出 slave B1 来代替 B。
下面关于 Redis 的文章您也可能喜欢,不妨参考下:
Ubuntu 14.04 下 Redis 安装及简单测试 http://www.linuxidc.com/Linux/2014-05/101544.htm
Redis 主从复制基本配置 http://www.linuxidc.com/Linux/2015-03/115610.htm
Redis 集群明细文档 http://www.linuxidc.com/Linux/2013-09/90118.htm
Ubuntu 12.10 下安装 Redis(图文详解)+ Jedis 连接 Redis http://www.linuxidc.com/Linux/2013-06/85816.htm
Redis 系列 - 安装部署维护篇 http://www.linuxidc.com/Linux/2012-12/75627.htm
CentOS 6.3 安装 Redis http://www.linuxidc.com/Linux/2012-12/75314.htm
Redis 安装部署学习笔记 http://www.linuxidc.com/Linux/2014-07/104306.htm
Redis 配置文件 redis.conf 详解 http://www.linuxidc.com/Linux/2013-11/92524.htm
Redis 的详细介绍:请点这里
Redis 的下载地址:请点这里
三、安装配置
1. 环境
使用 2 台 centos 服务器,每台机器上部署 3 个实例,集群为三个主节点与三个从节点:
192.168.36.54:6380
192.168.36.54:6381
192.168.36.54:6382
192.168.36.189:6380
192.168.36.189:6381
192.168.36.189:6382
2. 安装依赖
由于通过 redis-trib.rb 工具构建 Redis Cluster,需要 rudy 环境,执行如下命令安装:
yum -y install zlib ruby rubygems
安装 ruby 的 redis 库:
gem install redis
3. 安装 redis 3.0
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
tar -zxvf redis-3.0.0.tar.gz
mkdir redis
cd redis-3.0.0
make PREFIX=/home/slim/redis
make PREFIX=/home/slim/redis install
将集群工具复制到 /home/slim/redis/bin 下
cp /home/slim/redis-3.0.0/src/redis-trib.rb ./bin/
创建数据配置目录
mkdir -p /home/slim/redis/{conf,data,logs}
4. 配置
在 2 台机器上配置如下:
cd /home/slim/redis
cp /home/slim/redis-3.0.0/redis.conf ./conf/redis-6380.conf
cp /home/slim/redis-3.0.0/redis.conf ./conf/redis-6381.conf
cp /home/slim/redis-3.0.0/redis.conf ./conf/redis-6382.conf
修改配置:
# 基本配置
daemonize yes
pidfile /home/slim/redis/data/redis-6380.pid
port 6380
bind 192.168.36.189
unixsocket /home/slim/redis/data/redis-6380.sock
unixsocketperm 700
timeout 300
loglevel verbose
logfile /home/slim/redis/logs/redis-6380.log
databases 16
dbfilename dump-6380.rdb
dir /home/slim/redis/data/
#aof 持久化
appendonly yes
appendfilename appendonly-6380.aof
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 80-100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
# 集群配置
cluster-enabled yes
cluster-config-file /home/slim/redis/data/nodes-6380.conf
cluster-node-timeout 5000
每个实例配置类似,修改一下都应端口、IP 地址、文件名称即可。
Redis 集群由多个运行在集群模式(cluster mode)下的 Redis 实例组成,实例的集群模式需要通过配置来开启,开启集群模式的实例将可以使用集群特有的功能和命令。要让集群正常运作至少需要三个主节点,不过在刚开始试用集群功能时,强烈建议使用六个节点:其中三个为主节点,而其余三个则是各个主节点的从节点。
cluster-enabled:开实例的集群模式
cluster-conf-file:设定了保存节点配置文件的路径,默认值为 nodes.conf。节点配置文件无须人为修改,它由 Redis 集群在启动时创建,并在有需要时自动进行更新。
cluster-node-timeout:集群节点互连超时的阀值
5. 启动服务
1)启动 2 台机器实例
./bin/redis-server ./conf/redis-6380.conf ;tail -f logs/redis-6380.log
./bin/redis-server ./conf/redis-6381.conf ;tail -f logs/redis-6381.log
./bin/redis-server ./conf/redis-6382.conf ;tail -f logs/redis-6382.log
启动日志中打印:
“8591:M 11 Apr 22:20:46.134 * No cluster configuration found, I’m 83fc65283bbbb71b4c089337df05594d67f4cab6”
每个节点都使用 ID 而不是 IP 或者端口号来记录其他节点,因为 IP 地址和端口号都可能会改变,而这个独一无二的标识符(identifier)则会在节点的整个生命周期中一直保持不变。
查看启动进程:
ps -ef | grep redis
slim 8525 1 0 22:16 ? 00:00:01 ./bin/redis-server 192.168.36.54:6380 [cluster]
slim 8544 1 0 22:17 ? 00:00:00 ./bin/redis-server 192.168.36.54:6381 [cluster]
slim 8591 1 0 22:20 ? 00:00:00 ./bin/redis-server 192.168.36.54:6382 [cluster]
2)集群配置
在每台机器上启动的 redis 服务都是相互独立,下面我们就使用 redis-trib.rb 工具构建 Redis Cluster。
./bin/redis-trib.rb create –replicas 1 192.168.36.54:6380 192.168.36.54:6381 192.168.36.54:6382 192.168.36.189:6380 192.168.36.189:6381 192.168.36.189:6382
命令的意义如下:
给定 redis-trib.rb 程序的命令是 create,这表示我们希望创建一个新的集群。
选项 –replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
之后跟着的其他参数则是实例的地址列表,我们希望程序使用这些地址所指示的实例来创建新集群。
简单来说,以上命令的意思就是让 redis-trib 程序创建一个包含三个主节点和三个从节点的集群。
启动日志:
>>> Creating cluster
Connecting to node 192.168.36.54:6380: OK
Connecting to node 192.168.36.54:6381: OK
Connecting to node 192.168.36.54:6382: OK
Connecting to node 192.168.36.189:6380: OK
Connecting to node 192.168.36.189:6381: OK
Connecting to node 192.168.36.189:6382: OK
>>> Performing hash slots allocation on 6 nodes…
Using 3 masters:
192.168.36.54:6380
192.168.36.189:6380
192.168.36.54:6381
Adding replica 192.168.36.189:6381 to 192.168.36.54:6380
Adding replica 192.168.36.54:6382 to 192.168.36.189:6380
Adding replica 192.168.36.189:6382 to 192.168.36.54:6381
M: f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380
slots:0-5460 (5461 slots) master
M: 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381
slots:10923-16383 (5461 slots) master
S: 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382
replicates b1a15a3cd14ea65671a7134850e17b8919a17da5
M: b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380
slots:5461-10922 (5462 slots) master
S: 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381
replicates f6285c8a7506b224840d7b26b2b5d1671320c21f
S: de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382
replicates 26ce71d626175f88e0416e3f45b2bfb29304c7b3
Can I set the above configuration? (type ‘yes’ to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join…
>>> Performing Cluster Check (using node 192.168.36.54:6380)
M: f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380
slots:0-5460 (5461 slots) master
M: 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381
slots:10923-16383 (5461 slots) master
M: 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382
slots: (0 slots) master
replicates b1a15a3cd14ea65671a7134850e17b8919a17da5
M: b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380
slots:5461-10922 (5462 slots) master
M: 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381
slots: (0 slots) master
replicates f6285c8a7506b224840d7b26b2b5d1671320c21f
M: de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382
slots: (0 slots) master
replicates 26ce71d626175f88e0416e3f45b2bfb29304c7b3
[OK] All nodes agree about slots configuration.
>>> Check for open slots…
>>> Check slots coverage…
[OK] All 16384 slots covered. 从启动日志可以看出有 6 个集群实例,主节点为:
192.168.36.54:6380
192.168.36.189:6380
192.168.36.54:6381
每个主节点对应一个从节点
Adding replica 192.168.36.189:6381 to 192.168.36.54:6380
Adding replica 192.168.36.54:6382 to 192.168.36.189:6380
Adding replica 192.168.36.189:6382 to 192.168.36.54:6381
slots 划分:
192.168.36.54:6380 0-5460
192.168.36.189:6380 5461-10922
192.168.36.54:6381 10923-16383
一共 16384 slots
注:redis-trib.rb 使用参数
Usage: redis-trib <command> <options> <arguments …>
fix host:port
call host:port command arg arg .. arg
check host:port
import host:port
–from <arg>
set-timeout host:port milliseconds
add-node new_host:new_port existing_host:existing_port
–master-id <arg>
–slave
reshard host:port
–to <arg>
–from <arg>
–slots <arg>
–yes
create host1:port1 … hostN:portN
–replicas <arg>
help (show this help)
del-node host:port node_id
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. 参数说明:
call:执行 redis 命令
create:创建一个新的集群。host1:port1 … hostN:portN 指定了用于构建 Redis Cluster 的所有 redis 实例,节点角色由顺序决定, 先 master 之后是 slave。而 –replicas 则指定了为 Redis Cluster 中的每个 Master 节点配备几个 Slave 节点。
add-node 将一个节点添加到集群里面,第一个是新节点 ip:port, 第二个是任意一个已存在节点 ip:port,–master-id
reshard:重新分片
check:查看集群信息
del-node:移除一个节点
对于客户端 redis-cli 要访问集群,在启动的时候需要添加一个 - c 参数,如查看集群所有节点:
./bin/redis-cli -c -h 192.168.36.189 -p 6380 cluster nodes
1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 slave f6285c8a7506b224840d7b26b2b5d1671320c21f 0 1428817516066 5 connected
b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 myself,master – 0 0 4 connected 5461-10922
83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slave b1a15a3cd14ea65671a7134850e17b8919a17da5 0 1428817515047 4 connected
26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master – 0 1428817514946 2 connected 10923-16383
f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 master – 0 1428817514844 1 connected 0-5460
de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slave 26ce71d626175f88e0416e3f45b2bfb29304c7b3 0 1428817516578 6 connected
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2016-09/135123p2.htm
四、客户端集群命令
cluster 集群相关命令, 更多 Redis 相关命令见文档:http://redis.readthedocs.org/en/latest/
集群
cluster info 打印集群的信息
cluster nodes 列出集群当前已知的所有节点(node),以及这些节点的相关信息。
节点
cluster meet <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
cluster forget <node_id> 从集群中移除 node_id 指定的节点。
cluster replicate <node_id> 将当前节点设置为 node_id 指定的节点的从节点。
cluster saveconfig 将节点的配置文件保存到硬盘里面。
槽(slot)
cluster addslots <slot> [slot …] 将一个或多个槽(slot)指派(assign)给当前节点。
cluster delslots <slot> [slot …] 移除一个或多个槽对当前节点的指派。
cluster flushslots 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
cluster setslot <slot> node <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽 >,然后再进行指派。
cluster setslot <slot> migrating <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。
cluster setslot <slot> importing <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。
cluster setslot <slot> stable 取消对槽 slot 的导入(import)或者迁移(migrate)。
键
cluster keyslot <key> 计算键 key 应该被放置在哪个槽上。
cluster countkeysinslot <slot> 返回槽 slot 目前包含的键值对数量。
cluster getkeysinslot <slot> <count> 返回 count 个 slot 槽中的键。五、redis-trib.rb 操作集群
每台机器增加端口 6383 redis 实例节点,并启动实例。
1. 添加新 master 节点
1)add-node 将一个节点添加到集群里面,第一个是新节点 ip:port, 第二个是任意一个已存在节点 ip:port
./bin/redis-trib.rb add-node 192.168.36.54:6383 192.168.36.54:6380
>>> Adding node 192.168.36.54:6383 to cluster 192.168.36.54:6380
Connecting to node 192.168.36.54:6380: OK
Connecting to node 192.168.36.189:6380: OK
Connecting to node 192.168.36.189:6382: OK
Connecting to node 192.168.36.54:6382: OK
Connecting to node 192.168.36.54:6381: OK
Connecting to node 192.168.36.189:6381: OK
>>> Performing Cluster Check (using node 192.168.36.54:6380)
M: f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382
slots: (0 slots) slave
replicates 26ce71d626175f88e0416e3f45b2bfb29304c7b3
S: 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382
slots: (0 slots) slave
replicates b1a15a3cd14ea65671a7134850e17b8919a17da5
M: 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381
slots: (0 slots) slave
replicates f6285c8a7506b224840d7b26b2b5d1671320c21f
[OK] All nodes agree about slots configuration.
>>> Check for open slots…
>>> Check slots coverage…
[OK] All 16384 slots covered.
Connecting to node 192.168.36.54:6383: OK
>>> Send CLUSTER MEET to node 192.168.36.54:6383 to make it join the cluster.
[OK] New node added correctly. 新节点没有包含任何数据,因为它没有包含任何 slot。新加入的加点是一个主节点,当集群需要将某个从节点升级为新的主节点时,这个新节点不会被选中。
2)为新节点分配 slot
你只需要指定集群中其中一个节点的地址,redis-trib 就会自动找到集群中的其他节点。目前 redis-trib 只能在管理员的协助下完成重新分片的工作,要让 redis-trib 自动将哈希槽从一个节点移动到另一个节点,目前来说还做不到(不过实现这个功能并不难)。
./bin/redis-trib.rb reshard 192.168.36.54:6383
设定你打算移动的哈希槽 slots 的数量(这里槽数量设置为 1000)
How many slots do you want to move (from 1 to 16384)? 1000
除了移动的哈希槽数量之外,redis-trib 还需要知道重新分片的目标(target node),也即是,负责接收这 1000 个哈希槽的节点。指定目标需要使用节点的 ID,而不是 IP 地址和端口。比如说,我们打算使用集群的第一个主节点来作为目标,它的 IP 地址和端口是 192.168.36.54:6383,而节点 ID 则是 50cd88737109d0398e35b19747cc02832f05d125,那么我们应该向 redis-trib 提供节点的 ID:
What is the receiving node ID?50cd88737109d0398e35b19747cc02832f05d125
redis-trib 会打印出集群中所有节点的 ID,并且我们也可以通过执行以下命令来获得节点的运行 ID:
./bin/redis-cli -h 192.168.36.54 -p 6380 cluster nodes |grep 192.168.36.54:6383
接着,redis-trib 会向你询问重新分片的源节点(source node),也即是,要从哪个节点中取出 1000 个哈希槽,并将这些槽移动到目标节点上面。如果我们不打算从特定的节点上取出指定数量的哈希槽,那么可以向 redis-trib 输入 all,这样的话,集群中的所有主节点都会成为源节点,redis-trib 将从各个源节点中各取出一部分哈希槽,凑够 1000 个,然后移动到目标节点上面:
Please enter all the source node IDs.
Type ‘all’ to use all the nodes as source nodes for the hash slots.
Type ‘done’ once you entered all the source nodes IDs.
Source node #1:all
输入 all 并按下回车之后,redis-trib 将打印出哈希槽的移动计划,如果你觉得没问题的话,就可以输入 yes 并再次按下回车,redis-trib 就会正式开始执行重新分片操作,将指定的哈希槽从源节点一个个地移动到目标节点上面。
在重新分片操作执行完毕之后,可以使用以下命令来检查集群是否正常:
./bin/redis-trib.rb check 192.168.36.54:6380
根据检查结果显示,集群运作正常。
2. 添加新的 slave 节点
1)添加节点
./bin/redis-trib.rb add-node 192.168.36.189:6383 192.168.36.54:6380
2)redis-cli 连接上新节点 shell, 输入命令:cluster replicate 对应 master 的 node-id
./bin/redis-cli -c -h 192.168.36.189 -p 6383
>cluster replicate 50cd88737109d0398e35b19747cc02832f05d125
在线添加 slave 时,需要 dump 整个 master 进程,并传递到 slave,再由 slave 加载 rdb 文件到内存,rdb 传输过程中 Master 可能无法提供服务, 整个过程消耗大量 io, 小心操作.
查看执行结果:
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes | grep slave | grep 50cd88737109d0398e35b19747cc02832f05d125
5178d6342a6470f928cfa6d43d98640b9303ad38 192.168.36.189:6383 myself,slave 50cd88737109d0398e35b19747cc02832f05d125 0 0 0 connected
3)在线 reshard 数据
对于负载 / 数据不均匀的情况,可以在线 reshard slot 来解决, 方法与添加新 master 的 reshard 一样,只是需要 reshard 的 master 节点是老节点。
4)删除一个 slave 节点
./bin/redis-trib.rb del-node 192.168.36.54:6380 5178d6342a6470f928cfa6d43d98640b9303ad38
5)删除一个 master 节点
删除 master 节点之前首先要使用 reshard 移除 master 的全部 slot, 然后再删除当前节点 (目前只能把被删除 master 的 slot 迁移到一个节点上),操作和分配 slot 类似,指定具体的 Source node 即可。
然后在使用 4 步骤中的命令删除节点
六、集群测试
1. 数据测试
使用 redis 客户端 redis-cli 进行添加数据操作。
./bin/redis-cli -c -h 192.168.36.189 -p 6380
192.168.36.189:6380> set abc 123
OK
192.168.36.189:6380> set xxx 123
-> Redirected to slot [4038] located at 192.168.36.54:6380
OK
192.168.36.54:6380> set ttt aaa
-> Redirected to slot [15942] located at 192.168.36.54:6381
OKredis-cli 对集群的支持是非常基本的,所以它总是依靠 Redis 集群节点来将它转向(redirect)至正确的节点。
2. 故障转移测试
要触发一次故障转移,最简单的办法就是令集群中的某个主节点进入下线状态。
首先用以下命令列出集群中的所有主节点:
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes |grep master
50cd88737109d0398e35b19747cc02832f05d125 192.168.36.54:6383 master – 0 1428823692383 7 connected 0-332 5461-5794 10923-11255
26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master – 0 1428823692893 2 connected 11256-16383
f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 master – 0 1428823693918 1 connected 333-5460
b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 master – 0 1428823692893 4 connected 5795-10922 通过命令输出,我们知道端口号为 192.168.36.54:6380、192.168.36.54:6381、192.168.36.54:6383 和 192.168.36.189:6380 的节点都是主节点,然后我们可以通过向端口号为 192.168.36.54:6380 的主节点发送 DEBUG SEGFAULT 命令,让这个主节点崩溃:
./bin/redis-cli -h 192.168.36.54 -p 6380 debug segfault
Error: Server closed the connection
我们使用 cluster nodes 命令,查看集群在执行故障转移操作之后,主从节点的布局情况:
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes
50cd88737109d0398e35b19747cc02832f05d125 192.168.36.54:6383 master – 0 1428823969555 7 connected 0-332 5461-5794 10923-11255
1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 master – 0 1428823968475 8 connected 333-5460
de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slave 26ce71d626175f88e0416e3f45b2bfb29304c7b3 0 1428823968886 2 connected
26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master – 0 1428823967861 2 connected 11256-16383
83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slave b1a15a3cd14ea65671a7134850e17b8919a17da5 0 1428823969555 4 connected
f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 master,fail? – 1428823891006 1428823888448 1 disconnected
b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 master – 0 1428823970008 4 connected 5795-10922
5178d6342a6470f928cfa6d43d98640b9303ad38 192.168.36.189:6383 myself,slave 50cd88737109d0398e35b19747cc02832f05d125 0 0 0 connected 重启了之前下线的节点 192.168.36.54:6380,该节点已经从原来的主节点变成了从节点。
./bin/redis-cli -h 192.168.36.189 -p 6383 cluster nodes
50cd88737109d0398e35b19747cc02832f05d125 192.168.36.54:6383 master – 0 1428824165896 7 connected 0-332 5461-5794 10923-11255
1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 master – 0 1428824166406 8 connected 333-5460
de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slave 26ce71d626175f88e0416e3f45b2bfb29304c7b3 0 1428824165382 2 connected
26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master – 0 1428824165896 2 connected 11256-16383
83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slave b1a15a3cd14ea65671a7134850e17b8919a17da5 0 1428824164870 4 connected
f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 slave 1080e423a55a2c24dae649dac03ffa09ed26d3e8 0 1428824166920 8 connected
b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 master – 0 1428824166407 4 connected 5795-10922
5178d6342a6470f928cfa6d43d98640b9303ad38 192.168.36.189:6383 myself,slave 50cd88737109d0398e35b19747cc02832f05d125 0 0 0 connected 注:cluster nodes 命令的输出有点儿复杂,它的每一行都是由以下信息组成的:
节点 ID:例如 3fc783611028b1707fd65345e763befb36454d73。
ip:port:节点的 IP 地址和端口号,例如 127.0.0.1:7000,其中 :0 表示的是客户端当前连接的 IP 地址和端口号。
flags:节点的角色(例如 master、slave、myself)以及状态(例如 fail,等等)。
如果节点是一个从节点的话,那么跟在 flags 之后的将是主节点的节点 ID:例如 127.0.0.1:7002 的主节点的节点 ID 就是 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e。
集群最近一次向节点发送 PING 命令之后,过去了多长时间还没接到回复。
节点最近一次返回 PONG 回复的时间。
节点的配置纪元(configuration epoch):详细信息请参考 Redis 集群规范。
本节点的网络连接情况:例如 connected。
节点目前包含的槽:例如 192.168.36.189:6380 目前包含号码为 5795-10922 的哈希槽。
七、集群下 Java 客户端使用
如下以 jedis 为例:
package cn.slimsmart.redis.demo.cluster;
import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
public class RedisClusterTest {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(100);
config.setMinIdle(100);
config.setMaxWaitMillis(6 * 1000);
config.setTestOnBorrow(true);
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort(“192.168.36.54”, 6380));
jedisClusterNodes.add(new HostAndPort(“192.168.36.54”, 6381));
jedisClusterNodes.add(new HostAndPort(“192.168.36.54”, 6382));
jedisClusterNodes.add(new HostAndPort(“192.168.36.54”, 6383));
jedisClusterNodes.add(new HostAndPort(“192.168.36.189”, 6380));
jedisClusterNodes.add(new HostAndPort(“192.168.36.189”, 6381));
jedisClusterNodes.add(new HostAndPort(“192.168.36.189”, 6382));
jedisClusterNodes.add(new HostAndPort(“192.168.36.189”, 6383));
JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, 2000, 2, config);
try {
for (int i = 0; i < 1000; i++) {
long t1 = System.currentTimeMillis();
jedisCluster.set(“” + i, “” + i);
long t2 = System.currentTimeMillis();
String value = jedisCluster.get(“” + i);
long t3 = System.currentTimeMillis();
System.out.println(“” + value);
System.out.println((t2 – t1) + “mills”);
System.out.println((t3 – t2) + “mills”);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jedisCluster.close();
}
}
}
jedis 客户端不足之处:
1.cluster 环境下 redis 的 slave 不接受任何读写操作
2.client 端不支持 keys 批量操作, 不支持 select dbNum 操作,只有一个 db:select 0
3.JedisCluster 的 info() 等单机函数无法调用, 返回 (No way to dispatch this command to Redis Cluster) 错误
4.JedisCluster 没有针对 byte[] 的 API,需要自己扩展
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/135123.htm
Redis3.0 最大的特点就是有了 cluster 的能力,使用 redis-trib.rb 工具可以轻松构建 Redis Cluster。Redis Cluster 采用无中心结构,每个节点保存数据和整个集群状态, 每个节点都和其他所有节点连接。节点之间使用 gossip 协议传播信息以及发现新节点,这种结构和 Cassandra 很相似,Cassandra 节点可以转发请求。Redis 集群中节点不作为 client 请求的代理,client 根据 node 返回的错误信息重定向请求。
一、集群特性
1. 数据可以在 cluster 的多个 node 之间进行共享;
2. 一次请求处理多批 key 的命令将不再被支持,因为这些命令处理的 key 可能在不同的 node 之间,使用了它们反而会降低 cluster 的性能;
3. 提供高 HA,即某个 node failed 后 cluster 依旧提供高可用性。
cluster 提供如下能力保证:
1. 在 cluster 内自动把数据划分到不同的 set 上;
2. 当集群中一小群机器出现网络故障时或者其他种类的 failure 时,cluster 要保证系统继续可用;
redis 的每个 node 启动后占用两个 port 6379 & 16379。redis 通过 port 6379 继续对 client 提供服务,client 通过 redis 独有的文本协议与 node 进行通信,所以这个 port 被成为 client port or command port。redis node 通过 port 16379 与 cluster 内部的其他 node 进行二进制形式的通信,所以被称为 data port or bus port。通过 port 16379,node 之间进行 failure detection(探活)、configure update(配置更新)、failure authorization(失败确认)。如果 node 使用别的端口作为 command port,那么 data port 一定是 command port + 10000。
两个不同的 cluster 之间也可以通过 data port 进行 data migration。
二、分片
redis cluster 内部没用提供一致性 hash 算法来保证集群的可伸缩能力,而是通过简单的 crc16 hash 算法来进行 sharding,所以它最多提供 16384 个 slot。如果 cluster 有三个 node,分别为 A and B and C,则 A 负责 0 – 5500 slots,B 负责 5501 – 11000 slots,C 负责 11001 – 16383 slots。进行扩容的时候,就得在不同的 node 之间进行 slots 的迁移,不需要关机,也不会出现服务不可用现象。
cluster 内部每个 node(也成为一个 instance)由一个 master 和多个 slave 构成,当 master fail 的时候,可以通过选举机制选出一个 slave 代替 master。
Redis Cluster 不提供强一致性。例如 cluster 接受了一个写请求,给 client 返回 ok,这个写请求的内容也可能丢失。因为其写流程如下:
1 master B 接受了一个写请求;
2 B 写成功,返回 ok 给 client;
3 B 把数据广播给 slaves(B1、B2、B3)
如果第二步执行完毕后,B crash 了,则会发生数据不一致现象。这与传统的 DBMS 类似,它们接收了写请求后,每隔 1S 才会把数据写入 disk,这么做也是在性能和一致性之间做一个平衡。
如果用户对数据的一致性要求比较高,Redis 可能也会兼顾这种需求,将来会提供相应的选项,让 redis 中的 slave 没用成功的接受数据之前不会给 client 返回 ok 给 client。即先执行 step 3,然后再执行 step 2。
一致性还有一种场景。假设有 client Z,与 cluster 内各个 node A and B and C,以及各个 node 的 replica A1 and B1 and C1,Z 与 B 之间连接正常,但是 B 与 B1 以及 cluster 内其他 nodes 连接失败。如果 Z 发起 write request,那么 B 会给他返回 ok,但是 B1 无法获取到相应的数据,这就要求写的时候也要把 node 与 cluster 内其他的成员的探活也要考虑在内。基本要求就是,写时间周期要大于探活时间周期(node timeout)。当 node B timeout 之后,master B 会自动进入 failing 状态,拒绝外部 client 的连接请求,而 cluster 则会选出 slave B1 来代替 B。
下面关于 Redis 的文章您也可能喜欢,不妨参考下:
Ubuntu 14.04 下 Redis 安装及简单测试 http://www.linuxidc.com/Linux/2014-05/101544.htm
Redis 主从复制基本配置 http://www.linuxidc.com/Linux/2015-03/115610.htm
Redis 集群明细文档 http://www.linuxidc.com/Linux/2013-09/90118.htm
Ubuntu 12.10 下安装 Redis(图文详解)+ Jedis 连接 Redis http://www.linuxidc.com/Linux/2013-06/85816.htm
Redis 系列 - 安装部署维护篇 http://www.linuxidc.com/Linux/2012-12/75627.htm
CentOS 6.3 安装 Redis http://www.linuxidc.com/Linux/2012-12/75314.htm
Redis 安装部署学习笔记 http://www.linuxidc.com/Linux/2014-07/104306.htm
Redis 配置文件 redis.conf 详解 http://www.linuxidc.com/Linux/2013-11/92524.htm
Redis 的详细介绍:请点这里
Redis 的下载地址:请点这里
三、安装配置
1. 环境
使用 2 台 centos 服务器,每台机器上部署 3 个实例,集群为三个主节点与三个从节点:
192.168.36.54:6380
192.168.36.54:6381
192.168.36.54:6382
192.168.36.189:6380
192.168.36.189:6381
192.168.36.189:6382
2. 安装依赖
由于通过 redis-trib.rb 工具构建 Redis Cluster,需要 rudy 环境,执行如下命令安装:
yum -y install zlib ruby rubygems
安装 ruby 的 redis 库:
gem install redis
3. 安装 redis 3.0
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
tar -zxvf redis-3.0.0.tar.gz
mkdir redis
cd redis-3.0.0
make PREFIX=/home/slim/redis
make PREFIX=/home/slim/redis install
将集群工具复制到 /home/slim/redis/bin 下
cp /home/slim/redis-3.0.0/src/redis-trib.rb ./bin/
创建数据配置目录
mkdir -p /home/slim/redis/{conf,data,logs}
4. 配置
在 2 台机器上配置如下:
cd /home/slim/redis
cp /home/slim/redis-3.0.0/redis.conf ./conf/redis-6380.conf
cp /home/slim/redis-3.0.0/redis.conf ./conf/redis-6381.conf
cp /home/slim/redis-3.0.0/redis.conf ./conf/redis-6382.conf
修改配置:
# 基本配置
daemonize yes
pidfile /home/slim/redis/data/redis-6380.pid
port 6380
bind 192.168.36.189
unixsocket /home/slim/redis/data/redis-6380.sock
unixsocketperm 700
timeout 300
loglevel verbose
logfile /home/slim/redis/logs/redis-6380.log
databases 16
dbfilename dump-6380.rdb
dir /home/slim/redis/data/
#aof 持久化
appendonly yes
appendfilename appendonly-6380.aof
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 80-100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
# 集群配置
cluster-enabled yes
cluster-config-file /home/slim/redis/data/nodes-6380.conf
cluster-node-timeout 5000
每个实例配置类似,修改一下都应端口、IP 地址、文件名称即可。
Redis 集群由多个运行在集群模式(cluster mode)下的 Redis 实例组成,实例的集群模式需要通过配置来开启,开启集群模式的实例将可以使用集群特有的功能和命令。要让集群正常运作至少需要三个主节点,不过在刚开始试用集群功能时,强烈建议使用六个节点:其中三个为主节点,而其余三个则是各个主节点的从节点。
cluster-enabled:开实例的集群模式
cluster-conf-file:设定了保存节点配置文件的路径,默认值为 nodes.conf。节点配置文件无须人为修改,它由 Redis 集群在启动时创建,并在有需要时自动进行更新。
cluster-node-timeout:集群节点互连超时的阀值
5. 启动服务
1)启动 2 台机器实例
./bin/redis-server ./conf/redis-6380.conf ;tail -f logs/redis-6380.log
./bin/redis-server ./conf/redis-6381.conf ;tail -f logs/redis-6381.log
./bin/redis-server ./conf/redis-6382.conf ;tail -f logs/redis-6382.log
启动日志中打印:
“8591:M 11 Apr 22:20:46.134 * No cluster configuration found, I’m 83fc65283bbbb71b4c089337df05594d67f4cab6”
每个节点都使用 ID 而不是 IP 或者端口号来记录其他节点,因为 IP 地址和端口号都可能会改变,而这个独一无二的标识符(identifier)则会在节点的整个生命周期中一直保持不变。
查看启动进程:
ps -ef | grep redis
slim 8525 1 0 22:16 ? 00:00:01 ./bin/redis-server 192.168.36.54:6380 [cluster]
slim 8544 1 0 22:17 ? 00:00:00 ./bin/redis-server 192.168.36.54:6381 [cluster]
slim 8591 1 0 22:20 ? 00:00:00 ./bin/redis-server 192.168.36.54:6382 [cluster]
2)集群配置
在每台机器上启动的 redis 服务都是相互独立,下面我们就使用 redis-trib.rb 工具构建 Redis Cluster。
./bin/redis-trib.rb create –replicas 1 192.168.36.54:6380 192.168.36.54:6381 192.168.36.54:6382 192.168.36.189:6380 192.168.36.189:6381 192.168.36.189:6382
命令的意义如下:
给定 redis-trib.rb 程序的命令是 create,这表示我们希望创建一个新的集群。
选项 –replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
之后跟着的其他参数则是实例的地址列表,我们希望程序使用这些地址所指示的实例来创建新集群。
简单来说,以上命令的意思就是让 redis-trib 程序创建一个包含三个主节点和三个从节点的集群。
启动日志:
>>> Creating cluster
Connecting to node 192.168.36.54:6380: OK
Connecting to node 192.168.36.54:6381: OK
Connecting to node 192.168.36.54:6382: OK
Connecting to node 192.168.36.189:6380: OK
Connecting to node 192.168.36.189:6381: OK
Connecting to node 192.168.36.189:6382: OK
>>> Performing hash slots allocation on 6 nodes…
Using 3 masters:
192.168.36.54:6380
192.168.36.189:6380
192.168.36.54:6381
Adding replica 192.168.36.189:6381 to 192.168.36.54:6380
Adding replica 192.168.36.54:6382 to 192.168.36.189:6380
Adding replica 192.168.36.189:6382 to 192.168.36.54:6381
M: f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380
slots:0-5460 (5461 slots) master
M: 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381
slots:10923-16383 (5461 slots) master
S: 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382
replicates b1a15a3cd14ea65671a7134850e17b8919a17da5
M: b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380
slots:5461-10922 (5462 slots) master
S: 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381
replicates f6285c8a7506b224840d7b26b2b5d1671320c21f
S: de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382
replicates 26ce71d626175f88e0416e3f45b2bfb29304c7b3
Can I set the above configuration? (type ‘yes’ to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join…
>>> Performing Cluster Check (using node 192.168.36.54:6380)
M: f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380
slots:0-5460 (5461 slots) master
M: 26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381
slots:10923-16383 (5461 slots) master
M: 83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382
slots: (0 slots) master
replicates b1a15a3cd14ea65671a7134850e17b8919a17da5
M: b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380
slots:5461-10922 (5462 slots) master
M: 1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381
slots: (0 slots) master
replicates f6285c8a7506b224840d7b26b2b5d1671320c21f
M: de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382
slots: (0 slots) master
replicates 26ce71d626175f88e0416e3f45b2bfb29304c7b3
[OK] All nodes agree about slots configuration.
>>> Check for open slots…
>>> Check slots coverage…
[OK] All 16384 slots covered. 从启动日志可以看出有 6 个集群实例,主节点为:
192.168.36.54:6380
192.168.36.189:6380
192.168.36.54:6381
每个主节点对应一个从节点
Adding replica 192.168.36.189:6381 to 192.168.36.54:6380
Adding replica 192.168.36.54:6382 to 192.168.36.189:6380
Adding replica 192.168.36.189:6382 to 192.168.36.54:6381
slots 划分:
192.168.36.54:6380 0-5460
192.168.36.189:6380 5461-10922
192.168.36.54:6381 10923-16383
一共 16384 slots
注:redis-trib.rb 使用参数
Usage: redis-trib <command> <options> <arguments …>
fix host:port
call host:port command arg arg .. arg
check host:port
import host:port
–from <arg>
set-timeout host:port milliseconds
add-node new_host:new_port existing_host:existing_port
–master-id <arg>
–slave
reshard host:port
–to <arg>
–from <arg>
–slots <arg>
–yes
create host1:port1 … hostN:portN
–replicas <arg>
help (show this help)
del-node host:port node_id
For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. 参数说明:
call:执行 redis 命令
create:创建一个新的集群。host1:port1 … hostN:portN 指定了用于构建 Redis Cluster 的所有 redis 实例,节点角色由顺序决定, 先 master 之后是 slave。而 –replicas 则指定了为 Redis Cluster 中的每个 Master 节点配备几个 Slave 节点。
add-node 将一个节点添加到集群里面,第一个是新节点 ip:port, 第二个是任意一个已存在节点 ip:port,–master-id
reshard:重新分片
check:查看集群信息
del-node:移除一个节点
对于客户端 redis-cli 要访问集群,在启动的时候需要添加一个 - c 参数,如查看集群所有节点:
./bin/redis-cli -c -h 192.168.36.189 -p 6380 cluster nodes
1080e423a55a2c24dae649dac03ffa09ed26d3e8 192.168.36.189:6381 slave f6285c8a7506b224840d7b26b2b5d1671320c21f 0 1428817516066 5 connected
b1a15a3cd14ea65671a7134850e17b8919a17da5 192.168.36.189:6380 myself,master – 0 0 4 connected 5461-10922
83fc65283bbbb71b4c089337df05594d67f4cab6 192.168.36.54:6382 slave b1a15a3cd14ea65671a7134850e17b8919a17da5 0 1428817515047 4 connected
26ce71d626175f88e0416e3f45b2bfb29304c7b3 192.168.36.54:6381 master – 0 1428817514946 2 connected 10923-16383
f6285c8a7506b224840d7b26b2b5d1671320c21f 192.168.36.54:6380 master – 0 1428817514844 1 connected 0-5460
de4302f43ff89843675446396552fd19f741246a 192.168.36.189:6382 slave 26ce71d626175f88e0416e3f45b2bfb29304c7b3 0 1428817516578 6 connected
更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2016-09/135123p2.htm