1. 程式人生 > >redis 叢集-新增加節點並資料遷移

redis 叢集-新增加節點並資料遷移

現在我們已經有一個包含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



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