Redis Cluster 初探(1) - 集群搭建与扩容

Redis Cluster是Redis官方的集群实现方案,在此之前已经有一些民间的第三方Redis集群解决方案,如Twitter的Twenproxy,豌豆荚的Codis,与其不同的是,Redis Cluster并非使用Porxy的模式来连接集群节点,而是使用无中心节点的模式来组建集群,有一定性能优势也有缺点,本文主要是我调研Redis Cluster的一些知识整理与经验汇总。

首先我们来尝试下搭建一个Redis Cluster集群

前置准备

Redis Cluster需要Redis 3.0及以上版本才支持,此文发布的时候,Redis的最高版本为3.0.5。

wget http://download.redis.io/releases/redis-3.0.5.tar.gz
tar -xvf redis-3.0.5.tar.gz
cd redis-3.0.5
make

编译完Redis,生成的可执行文件在redis-3.0.5/src之中,为了方便使用,我们把可执行文件的目录加入PATH之中。

vim ~/.bashrc

# 增加以下内容

REDIS_HOME=/home/xiezefan/sofeware/redis-3.0.5/src
PATH=$REDIS_HOME:$PATH
export PATH

# 保存后让修改生效

source ~/.bashrc

要创建Redis Cluster,我们还需要安装Ruby以及RubyGems。

yum install ruby
yum install gcc g++ make automake autoconf curl-devel openssl-devel zlib-devel httpd-devel apr-devel apr-util-devel sqlite-devel
yum install ruby-rdoc ruby-devel
yum install rubygems
gem install redis

创建集群

此次此时我们需要创建8个节点,端口号7000~7007

复制redis-3.0.5/redis.conf,修改一下内容

mkdir cluster
cp ~/sofeware/redis-3.0.5/redis.conf cluster/
vim cluster/redis.conf
# 修改以下内容
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

批量复制7份,修改配置文件的端口号。修改完毕后,分别进入各个节点的目录中启动redis

cd 7000
redis-server redis.conf

cd 7001
redis-server redis.conf

# 依次启动7000-7007
...

至此,8个Redis全都启动完毕,但是他们还处于彼此互相不知道彼此的阶段。

xiezefan@ubuntu:~$ ps -ef | grep redis
xiezefan 13372     1  0 20:09 ?        00:00:08 redis-server *:7000 [cluster]
xiezefan 13376     1  0 20:09 ?        00:00:08 redis-server *:7001 [cluster]
xiezefan 13380     1  0 20:09 ?        00:00:08 redis-server *:7002 [cluster]
xiezefan 13382     1  0 20:09 ?        00:00:08 redis-server *:7003 [cluster]
xiezefan 13386     1  0 20:09 ?        00:00:08 redis-server *:7004 [cluster]
xiezefan 13390     1  0 20:09 ?        00:00:08 redis-server *:7005 [cluster]
xiezefan 13394     1  0 20:09 ?        00:00:08 redis-server *:7006 [cluster]
xiezefan 13400     1  0 20:09 ?        00:00:08 redis-server *:7007 [cluster]

下一步,我们要将7000-7005这六个节点连接成一个集群。

redis-trib.rb create --replicas 1 10.211.55.4:7000 10.211.55.4:7001 10.211.55.4:7002 10.211.55.4:7003 10.211.55.4:7004 10.211.55.4:7005

该命令表示,将7000-7006节点创建一个集群,冗余为1,就是3主3从。切记,此处指定的IP会在client发送move命令的时候返回,所以一定要指定为客户端能访问到的IP,例如下面这种IP是不可行的,client拿到的IP就位是127.0.0.1导致一直重定向失败。

redis-trib.rb 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自动分配给出一个slot的分配方案

>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
10.211.55.4:7000
10.211.55.4:7001
10.211.55.4:7002
Adding replica 10.211.55.4:7003 to 10.211.55.4:7000
Adding replica 10.211.55.4:7004 to 10.211.55.4:7001
Adding replica 10.211.55.4:7005 to 10.211.55.4:7002
M: 9dfef549f7917794cbabaf96781ed0e19957c1f3 10.211.55.4:7000
   slots:0-5460 (5461 slots) master
M: c14485e8d7f1f3ec5c505b41fe727b657c951d8d 10.211.55.4:7001
   slots:5461-10922 (5462 slots) master
M: 8b308093e99f4299b8c18ab1dd81c5a83a3528c6 10.211.55.4:7002
   slots:10923-16383 (5461 slots) master
S: 632409883570eb5cecf6089583fba64a41d1154f 10.211.55.4:7003
   replicates 9dfef549f7917794cbabaf96781ed0e19957c1f3
S: edd31196e2980360b0738c57af95e1a69b0f9c9b 10.211.55.4:7004
   replicates c14485e8d7f1f3ec5c505b41fe727b657c951d8d
S: 95063a99c5cf2cc4abc51ca1e8ff0f3b8d60271c 10.211.55.4:7005
   replicates 8b308093e99f4299b8c18ab1dd81c5a83a3528c6
Can I set the above configuration? (type 'yes' to accept):

输入yes后,集群自动创建,创建完毕后,通过redis-cli进入任一节点,使用cluster nodes命令可以查看各个节点的状态

xiezefan@ubuntu:~$ redis-cli -p 7000
127.0.0.1:7000>cluster nodes
c14485e8d7f1f3ec5c505b41fe727b657c951d8d 10.211.55.4:7001 master - 0 1449060968280 2 connected 5461-10922
95063a99c5cf2cc4abc51ca1e8ff0f3b8d60271c 10.211.55.4:7005 slave 8b308093e99f4299b8c18ab1dd81c5a83a3528c6 0 1449060968280 6 connected
edd31196e2980360b0738c57af95e1a69b0f9c9b 10.211.55.4:7004 slave c14485e8d7f1f3ec5c505b41fe727b657c951d8d 0 1449060967274 5 connected
8b308093e99f4299b8c18ab1dd81c5a83a3528c6 10.211.55.4:7002 master - 0 1449060966769 3 connected 10923-16383
632409883570eb5cecf6089583fba64a41d1154f 10.211.55.4:7003 slave 9dfef549f7917794cbabaf96781ed0e19957c1f3 0 1449060967274 4 connected
9dfef549f7917794cbabaf96781ed0e19957c1f3 10.211.55.4:7000 myself,master - 0 0 1 connected 0-5460

随便输入一个查询指令get user.1

127.0.0.1:7000> get user.1
(error) MOVED 9645 10.211.55.4:7001

因为user.1所在的solt-9645在7001节点上,cluster给你发送MOVED指令让你去7001节点查找数据,连接redis-cli的时候,使用-c参数可以指定查询时接收到MOVED指令自动跳转

xiezefan@ubuntu:~$ redis-cli -c -p 7000
127.0.0.1:7000> get user.1
-> Redirected to slot [9645] located at 10.211.55.4:7001
(nil)

集群扩容

现在我们已经有一个包含6个节点的集群,我写了段代码,往集群写入10W条测试数据。
现在模拟机器扩容场景,为集群加入一个master节点7006和一个slave节点7007。

redis-trib.rb add-node 10.211.55.4:7006 10.211.55.4:7000

以上命令将7006节点接入7000所在的集群。接下来,我们为7006增加一个slave节点。

redis-trib.rb add-node --slave 10.211.55.4:7007 10.211.55.4:7000

以上命令表示增加slave节点,将7006的节点加入7000节点所在的集群中作为slave节点,随机依附现有的master节点中slave最少的节点,如果需要再指定特别的master节点,使用

redis-trib.rb add-node --slave --master-id 23b412673af0506df6382353e3a65960d5b7e66d 10.211.55.4:7007 10.211.55.4:7000

其中的23b412673af0506df6382353e3a65960d5b7e66d是7006节点的id,我们可以通过cluster nodes命令查看节点的id。

接下来我们用坐负载均衡,Slot是Redis Cluster数据承载的最小单位,我们可以指定将一定范围的Slot转移到新的节点来实现负载均衡。

Redis Cluster转移一个Slot的步骤是:

  1. 在目标节点上声明将从源节点上迁入Slot CLUSTER SETSLOT <slot> IMPORTING <source_node_id>
  2. 在源节点上声明将往目标节点迁出Slot CLUSTER SETSLOT <slot> IMPORTING <source_node_id>
  3. 批量从源节点获取KEY CLUSTER GETKEYSINSLOT <slot> <count>
  4. 将获取的Key迁移到目标节点 MIGRATE <target_ip> <target_port> <key_name> 0 <timeout>
  5. 重复步骤3,4直到所有数据迁移完毕
  6. 分别向双方节点发送 CLUSTER SETSLOT <slot> NODE <target_node_id>,该命令将会广播给集群其他节点,已经将Slot转移到目标节点。
  7. 等待集群状态变为OK CLUSTER INFO 中的 cluster_state = ok

我编写了一个脚本来批量迁移Slot

#!/bin/bash
source_host=$1  # 源节点HOST
source_port=$2  # 源节点端口
target_host=$3  # 目标节点HOST
target_port=$4  # 目标节点端口
start_slot=$5   # 迁移节点的其实范围
end_slot=$6     # 迁移节点的结束范围


for slot in `seq ${start_slot} ${end_slot}`
do
    redis-cli -c -h ${target_host} -p ${target_port} cluster setslot ${slot} importing `redis-cli -c -h ${source_host} -p ${source_port} cluster nodes | grep ${source_port} | awk '{print $1}'`
    echo "Setslot importing ${slot} to ${target_host}:${target_port} success"
    redis-cli -c -h ${source_host} -p ${source_port} cluster setslot ${slot} migrating `redis-cli -c -h ${target_host} -p ${target_port} cluster nodes | grep ${target_port} | awk '{print $1}'`
    echo "Setslot migrating ${slot} from ${source_host}:${source_port} success"

    while [ 1 -eq 1 ]
    do
        allkeys=`redis-cli -c -h ${source_host} -p ${source_port} cluster getkeysinslot ${slot} 10`
        if [ -z "${allkeys}" ]
        then
            redis-cli -c -h ${source_host} -p ${source_port} cluster setslot ${slot} node `redis-cli -c -h ${target_host} -p ${target_port} cluster nodes | grep ${target_port} | awk '{print $1}'`
            redis-cli -c -h ${target_host} -p ${target_port} cluster setslot ${slot} node `redis-cli -c -h ${source_host} -p ${target_port} cluster nodes | grep ${target_port} | awk '{print $1}'`
            echo "Migrate slot ${slot} finish"
            break
        else 
            for key in ${allkeys}
            do
                redis-cli -c -h ${source_host} -p ${source_port} migrate ${target_host} ${target_port} ${key} 0 5000
                echo "Migrate slot ${slot} key ${key} success"
            done
        fi
    done
done

执行命令 bash rebalance-cluster.sh 10.211.55.4 7000 10.211.55.4 7006 0 1000 将7000节点上0-1000这个范围内的Slot转移到7006节点,通过cluster nodes命令我们可以看到0-1000这个区间是slot已经从7000转移到7006

xiezefan@ubuntu:~/sheel$ redis-cli -c -p 7000 cluster nodes
23b412673af0506df6382353e3a65960d5b7e66d 10.211.55.4:7006 master - 0 1449064402389 7 connected 0-1000
0c2954d21d7bcdae333f4fdecf468ce05aa25544 10.211.55.4:7001 master - 0 1449064400372 2 connected 5461-10922
384a3bb5bd9ecb2fc7db75c866abc715d7966f82 10.211.55.4:7002 master - 0 1449064401381 3 connected 10923-16383
c3e09d286ef2dce49843268b20832d65a5d516a1 10.211.55.4:7004 slave 0c2954d21d7bcdae333f4fdecf468ce05aa25544 0 1449064401885 5 connected
50737b4a91443ab1a34eec4ef99d4f6fe5d358f4 10.211.55.4:7005 slave 384a3bb5bd9ecb2fc7db75c866abc715d7966f82 0 1449064402389 6 connected
3c62cc6664bba378cceb8ae8e02f5d727deafe9d 10.211.55.4:7007 slave 23b412673af0506df6382353e3a65960d5b7e66d 0 1449064400878 7 connected
d6441916dcd89cbf431465d92dfc0eb3dd235295 10.211.55.4:7003 slave 6ee21c5d93a6d2f293a2df1b37e8c9c27cb55ad8 0 1449064402389 4 connected
6ee21c5d93a6d2f293a2df1b37e8c9c27cb55ad8 10.211.55.4:7000 myself,master - 0 0 1 connected 1001-5460

参考文章

本文首发: http://xiezefan.me/2015/12/03/redis_cluster_research_1/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容