Redis Cluster终于出了Stable,这让人非常激动,等Stable好久了,因此仍是先玩玩。html
一. 集群简单概念。node
Redis 集群是一个能够在多个 Redis 节点之间进行数据共享的设施(installation)。git
Redis 集群不支持那些须要同时处理多个键的 Redis 命令, 由于执行这些命令须要在多个 Redis 节点之间移动数据, 而且在高负载的状况下, 这些命令将下降 Redis 集群的性能, 并致使不可预测的行为。github
Redis 集群经过分区(partition)来提供必定程度的可用性(availability): 即便集群中有一部分节点失效或者没法进行通信, 集群也能够继续处理命令请求。redis
Redis 集群提供了如下两个好处:数据库
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每一个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪一个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。ruby
集群中的每一个节点负责处理一部分哈希槽。 举个例子, 一个集群能够有三个哈希槽, 其中:架构
这种将哈希槽分布到不一样节点的作法使得用户能够很容易地向集群中添加或者删除节点。 好比说:app
由于将一个哈希槽从一个节点移动到另外一个节点不会形成节点阻塞, 因此不管是添加新节点仍是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会形成集群下线。性能
为了使得集群在一部分节点下线或者没法与集群的大多数(majority)节点进行通信的状况下, 仍然能够正常运做, Redis 集群对节点使用了主从复制功能: 集群中的每一个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其他的 N-1 个复制品为从节点(slave)。
在以前列举的节点 A 、B 、C 的例子中, 若是节点 B 下线了, 那么集群将没法正常运行, 由于集群找不到节点来处理 5501 号至 11000号的哈希槽。
另外一方面, 假如在建立集群的时候(或者至少在节点 B 下线以前), 咱们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会由于主节点 B 的下线而没法正常运做了。
不过若是节点 B 和 B1 都下线的话, Redis 集群仍是会中止运做。
Redis-cluster 架构图以下:
架构细节:
(1)全部的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是经过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不须要中间proxy层.客户端不须要链接集群全部节点,链接集群中任何一个可用节点便可
(4)redis-cluster把全部的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
二. Redis Cluster搭建使用
要让集群正常工做至少须要3个主节点,在这里咱们要建立6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系以下(为了简单演示都在同一台机器上面)
127.0.0.1:7000
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
1. 下载最新版redis。
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
2. 解压,安装
tar xf redis-3.0.0.tar.gz cd redis-3.0.0 make && make install
3.建立存放多个实例的目录
mkdir /data/cluster -p cd /data/cluster mkdir 7000 7001 7002 7003 7004 7005
4.修改配置文件
cp redis-3.0.0/redis.conf /data/cluster/7000/
修改配置文件中下面选项
port 7000
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
文件中的 cluster-enabled 选项用于开实例的集群模式, 而 cluster-conf-file 选项则设定了保存节点配置文件的路径, 默认值为nodes.conf 。其余参数相信童鞋们都知道。节点配置文件无须人为修改, 它由 Redis 集群在启动时建立, 并在有须要时自动进行更新。
修改完成后,把修改完成的redis.conf复制到7001-7005目录下,而且端口修改为和文件夹对应。
5.分别启动6个redis实例。
cd /data/cluster/7000 redis-server redis.conf cd /data/cluster/7001 redis-server redis.conf cd /data/cluster/7002 redis-server redis.conf cd /data/cluster/7003 redis-server redis.conf cd /data/cluster/7004 redis-server redis.conf cd /data/cluster/7005 redis-server redis.conf
查看进程否存在。
[root@redis-server 7005]# ps -ef | grep redis root 4168 1 0 11:49 ? 00:00:00 redis-server *:7000 [cluster] root 4176 1 0 11:49 ? 00:00:00 redis-server *:7001 [cluster] root 4186 1 0 11:50 ? 00:00:00 redis-server *:7002 [cluster] root 4194 1 0 11:50 ? 00:00:00 redis-server *:7003 [cluster] root 4202 1 0 11:50 ? 00:00:00 redis-server *:7004 [cluster] root 4210 1 0 11:50 ? 00:00:00 redis-server *:7005 [cluster] root 4219 4075 0 11:50 pts/2 00:00:00 grep redis
6.执行命令建立集群,首先安装依赖,不然建立集群失败。
yum install ruby rubygems -y
安装gem-redis
下载地址:https://rubygems.org/gems/redis/versions/3.0.0
gem install -l redis-3.0.0.gem
复制集群管理程序到/usr/local/bin
cp redis-3.0.0/src/redis-trib.rb /usr/local/bin/redis-trib
建立集群:
redis-trib create --replicas 1 127.0.0.1:7000 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
命令的意义以下:
简单来讲, 以上命令的意思就是让 redis-trib 程序建立一个包含三个主节点和三个从节点的集群。
接着, redis-trib 会打印出一份预想中的配置给你看, 若是你以为没问题的话, 就能够输入 yes , redis-trib 就会将这份配置应用到集群当中:
>>> Creating cluster Connecting to node 127.0.0.1:7000: OK Connecting to node 127.0.0.1:7001: OK Connecting to node 127.0.0.1:7002: OK Connecting to node 127.0.0.1:7003: OK Connecting to node 127.0.0.1:7004: OK Connecting to node 127.0.0.1:7005: OK >>> Performing hash slots allocation on 6 nodes... Using 3 masters: 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 Adding replica 127.0.0.1:7003 to 127.0.0.1:7000 Adding replica 127.0.0.1:7004 to 127.0.0.1:7001 Adding replica 127.0.0.1:7005 to 127.0.0.1:7002 M: 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 slots:5461-10922 (5462 slots) master M: 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 slots:10923-16383 (5461 slots) master S: 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 replicates 2774f156af482b4f76a5c0bda8ec561a8a1719c2 S: e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 replicates 2d03b862083ee1b1785dba5db2987739cf3a80eb S: 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 replicates 0456869a2c2359c3e06e065a09de86df2e3135ac Can I set the above configuration? (type 'yes' to accept):
输入 yes 并按下回车确认以后, 集群就会将配置应用到各个节点, 并链接起(join)各个节点 —— 也便是, 让各个节点开始互相通信:
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 127.0.0.1:7000) M: 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 slots:5461-10922 (5462 slots) master M: 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 slots:10923-16383 (5461 slots) master M: 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 slots: (0 slots) master replicates 2774f156af482b4f76a5c0bda8ec561a8a1719c2 M: e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slots: (0 slots) master replicates 2d03b862083ee1b1785dba5db2987739cf3a80eb M: 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slots: (0 slots) master replicates 0456869a2c2359c3e06e065a09de86df2e3135ac [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
一切正常输出如下信息:
[OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
集群的客户端
Redis 集群现阶段的一个问题是客户端实现不多。 如下是一些我知道的实现:
测试 Redis 集群比较简单的办法就是使用 redis-rb-cluster 或者 redis-cli , 接下来咱们将使用 redis-cli 为例来进行演示:
[root@redis-server ~]# redis-cli -c -p 7001 127.0.0.1:7001> set name yayun OK 127.0.0.1:7001> get name "yayun" 127.0.0.1:7001>
咱们能够看看还有哪些命令能够用:
[root@redis-server ~]# redis-trib help Usage: redis-trib <command> <options> <arguments ...> set-timeout host:port milliseconds add-node new_host:new_port existing_host:existing_port --master-id <arg> --slave fix host:port help (show this help) del-node host:port node_id import host:port --from <arg> check host:port call host:port command arg arg .. arg create host1:port1 ... hostN:portN --replicas <arg> reshard host:port --yes --to <arg> --from <arg> --slots <arg> For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. [root@redis-server ~]#
能够看见有add-node,不用想了,确定是添加节点。那么del-node就是删除节点。还有check确定就是检查状态了。
[root@redis-server ~]# redis-cli -p 7000 cluster nodes 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 master - 0 1428293673322 2 connected 5461-10922 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 slave 2774f156af482b4f76a5c0bda8ec561a8a1719c2 0 1428293672305 4 connected e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428293674340 5 connected 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428293670262 3 connected 10923-16383 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428293675362 6 connected [root@redis-server ~]#
能够看到7000-7002是master,7003-7005是slave。
故障转移测试:
127.0.0.1:7001> KEYS * 1) "name" 127.0.0.1:7001> get name "yayun" 127.0.0.1:7001>
能够看见7001是正常的,而且获取到了key,value,如今kill掉7000实例,再进行查询。
[root@redis-server ~]# ps -ef | grep 7000 root 4168 1 0 11:49 ? 00:00:03 redis-server *:7000 [cluster] root 4385 4361 0 12:39 pts/3 00:00:00 grep 7000 [root@redis-server ~]# kill 4168 [root@redis-server ~]# ps -ef | grep 7000 root 4387 4361 0 12:39 pts/3 00:00:00 grep 7000 [root@redis-server ~]# redis-cli -c -p 7001 127.0.0.1:7001> get name "yayun" 127.0.0.1:7001>
能够正常获取到value,如今看看状态。
[root@redis-server ~]# redis-cli -c -p 7001 cluster nodes 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 myself,master - 0 0 2 connected 5461-10922 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428295271619 3 connected 10923-16383 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 master - 0 1428295270603 7 connected 0-5460 e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428295272642 5 connected 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 master,fail - 1428295159553 1428295157205 1 disconnected 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428295269587 6 connected [root@redis-server ~]#
原来的7000端口实例已经显示fail,原来的7003是slave,如今自动提高为master。
关于更多的在线添加节点,删除节点,以及对集群进行从新分片请参考官方文档。
总结:
redis-cluster是个好东西,只是stable才出来不久,确定坑略多,并且如今使用的人比较少,前期了解学习一下是能够的,生产环境确定要慎重考虑。且须要进行严格的测试。生产环境中redis的集群能够考虑使用Twitter开源的twemproxy,以及豌豆荚开源的codis,这两个项目都比较成熟,如今使用的公司不少。已经向业界朋友获得证明。后面也会写博客介绍twemproxy和codis。
参考资料:
http://redis.readthedocs.org/en/latest/topic/cluster-tutorial.html