Redis 3.0版之前未支持集群功能,一般通过结合Twemproxy(Twitter出品)或者Codis(豌豆荚使用)基于代理方式来实现分布式集群,性能和稳定性都还不错,只是配置和管理方面仍显复杂,性能相比官方自带的集群还是会有些许损失。新发布的3.0版现已默认内置支持集群功能,并完全去除中心化。Redis通过分区来保障集群的可用性,确保即使部分节点失效或者无法连接,集群仍然能够继续处理客户请求。
Redis使用数据分片而不是一致性哈希的方法来实现集群。集群总共包含16384个哈希槽,每个节点分配一部分哈希槽,每个键存放在其中的一个槽里。这也意味着如果集群未开启主从复制,其中的任何一个节点宕机或断网,这些槽中存放的键将无法访问到。所以开启Redis集群时,最好开启复制,确保当主节点失效或者连接失败时,该主节点对应的从节点能够顶替主节点继续运作。当然,如果是某个主节点发生故障以及该主节点对应的所有从节点也同时出现故障,那么此时集群仍然还是有问题的,也就意味着保存在已发生故障节点的那部分数据无法访问了。
下面介绍下Redis集群的搭建步骤,暂不涉及到太多的Redis集群理论知识,留待下次讲解。
一. 安装Redis
Redis常用安装管理脚本地址:http://dongsong.blog.51cto.com/916653/1649590
mkdir -p /App/src cd /App/src wget http://download.redis.io/releases/redis-3.0.1.tar.gz sh redis install
二. 搭建Redis集群
测试环境使用一台主机运行6个实例来构建集群,每个Redis实例通过启动时指定不同的配置文件,配置文件存放在6个目录下,区别在于端口号不同,未写明的参数将使用Redis默认的配置。端口号从6380至6385。由于默认配置的缘故,Redis将自动保存快照RDB文件至./目录下,为了避免各个Redis实例自动备份路径冲突,所以应该cd进入每个目录后再启动。或者修改每个配置文件的dir参数也可避免备份冲突。
(1). 新建集群测试基目录:
mkdir -p /App/redis/cluster cd /App/redis/cluster
(2). 新建Redis集群精简模板配置文件/App/redis/cluster/redis.conf,配置中文件nodes.conf为启动时自动创建,用于保存集群状态信息:
# redis.conf port 6380 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes daemonize yes logfile redis.log
(3). 添加一集群管理脚本/App/redis/cluster/cluster,该程序只需修改好模板/App/redis/cluster/redis.conf,执行init即可初始化每个实例的配置参数,并启动或停止Redis集群所有实例,(注意事项:Redis集群节点会额外开启一个新端口用于各节点交互通信,额外端口为redis.conf监听端口参数port指定的数值+10000):
#!/bin/sh # Redis集群实例管理 RedisSrv=/App/redis/bin/redis-server RedisCli=/App/redis/bin/redis-cli Dir=$(cd $(dirname $0); pwd) Script=$(basename $0) Conf=redis.conf # 最小端口 SPort=6380 # 最大端口 EPort=6385 # 初始化 fInit() { for Port in $(seq $SPort $EPort) do mkdir -p $Dir/$Port cp -f $Dir/$Conf $Dir/$Port sed -i "s#^port $SPort#port $Port#" $Dir/$Port/redis.conf done } # 启动 fStart() { for Port in $(seq $SPort $EPort) do cd $Dir/$Port $RedisSrv redis.conf done } # 停止 fStop() { for Port in $(seq $SPort $EPort) do cd $Dir/$Port $RedisCli -p $Port shutdown done } Arg=$1 case $Arg in "init" ) fInit ;; "start" ) fStart ;; "stop" ) fStop ;; * ) echo "$Script init|start|stop" ;; esac
(4). 初始化,为每个实例都新建一个和端口号一致的目录并修改监听端口:
sh cluster init
(5). 启动集群所有Redis实例:
sh cluster start
(6). 创建Redis集群,需要用到源码包中src下的Ruby程序redis-trib.rb文件:
cp /App/src/redis-3.0.1/src/redis-trib.rb /App/redis/cluster/ cd /App/redis/cluster/ ./redis-trib.rb create --replicas 1 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385
1. create,表示
创建一个新的集群。
2. 选项 --replicas 1
表示为集群中的每个主节点创建一个从节点。
3. 其余参数则是新建集群中实例的地址列表。
(7). 看到上图类似输出表示:监听6380端口Redis分配了0-5460共5461个槽,6383为6380的从;6381分配了5461-10922共5462个槽,6384为6381的从;6382分配了10923-16383共5461个槽,6385为6382的从。输入yes并回车确认。
(8). 看到上图表示集群已新建成功,3主3从节点,每个节点都有不同的ID。总共使用了16384个Hash槽。
三. 测试集群
1. redis-cli程序必须添加 -c 参数选项,才可实现基本的集群支持操作。
2. 停掉一个主库后
3. 检查集群状况
从以上可以看出,6383从节点成功代替了6380主节点并修改为主节点,集群服务未受影响。
四. 支持Redis集群客户端
Redis从刚发布的3.0版才正式开始支持集群功能,目前支持集群功能的客户端还比较缺乏,稳定性也尚需时间检验,下面列举一些已开始部分支持Redis集群的编程语言客户端:
1. Shell:新版自带redis-cli实用程序,加上 -c 参数已提供基本的集群支持。
2. PHP:Predis
3. Java:Jedis
4. Ruby:redis-rb-cluster
5. Python:redis-py-cluster
6. C#:StackExchange.Redis
7. Node.js:thunk-redis