最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis集群擴(kuò)容數(shù)據(jù)遷移方案分析

 更新時(shí)間:2026年02月25日 09:42:12   作者:rchmin  
本文主要介紹了Redis集群擴(kuò)容數(shù)據(jù)遷移方案分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

問(wèn)題:一個(gè)Redis集群如果從原先的3個(gè)節(jié)點(diǎn)擴(kuò)容為4個(gè)節(jié)點(diǎn),存量數(shù)據(jù)是否需要遷移?如果需要該怎么遷移?

首先對(duì)于數(shù)據(jù)是否需要遷移答案是肯定的:需要遷移,但只需遷移部分?jǐn)?shù)據(jù)(約 25%的數(shù)據(jù))。

原因:從 3 個(gè)節(jié)點(diǎn)擴(kuò)到 4 個(gè)節(jié)點(diǎn),需要重新分配數(shù)據(jù)分布,使每個(gè)節(jié)點(diǎn)承擔(dān)約 25%的數(shù)據(jù)量,而不是原來(lái)的 33%。以下是具體的數(shù)據(jù)遷移方案:

一、遷移前準(zhǔn)備

1.1 環(huán)境檢查

# 1. 檢查當(dāng)前集群狀態(tài)
redis-cli --cluster check 192.168.1.101:6379

# 2. 查看槽分布情況
redis-cli -h 192.168.1.101 -p 6379 cluster slots
# 或使用更詳細(xì)的查看方式
echo "cluster slots" | redis-cli -h 192.168.1.101 -p 6379 | python -m json.tool

# 3. 檢查數(shù)據(jù)量預(yù)估
for node in 192.168.1.{101,102,103}:6379; do
    echo "=== $node ==="
    redis-cli -c -h ${node%:*} -p ${node#*:} dbsize
    redis-cli -c -h ${node%:*} -p ${node#*:} info memory | grep used_memory_human
done

# 4. 備份當(dāng)前集群配置
redis-cli -h 192.168.1.101 -p 6379 cluster nodes > cluster_nodes_backup_$(date +%Y%m%d).txt
redis-cli -h 192.168.1.101 -p 6379 cluster info > cluster_info_backup_$(date +%Y%m%d).txt

1.2 新節(jié)點(diǎn)準(zhǔn)備

# 1. 新節(jié)點(diǎn)配置文件(redis-4.conf)
port 6379
cluster-enabled yes
cluster-config-file nodes-4.conf
cluster-node-timeout 15000
cluster-require-full-coverage yes
appendonly yes
daemonize yes
logfile "/var/log/redis/redis-4.log"
dir /var/lib/redis/4/
maxmemory 8gb
maxmemory-policy volatile-lru

# 2. 創(chuàng)建數(shù)據(jù)目錄和日志目錄
mkdir -p /var/lib/redis/4/
mkdir -p /var/log/redis/
chown -R redis:redis /var/lib/redis/4/ /var/log/redis/

# 3. 啟動(dòng)新節(jié)點(diǎn)
redis-server /etc/redis/redis-4.conf

# 4. 驗(yàn)證新節(jié)點(diǎn)啟動(dòng)
redis-cli -h 192.168.1.104 -p 6379 ping

1.3 業(yè)務(wù)準(zhǔn)備

通知業(yè)務(wù)方:提前通知相關(guān)業(yè)務(wù)團(tuán)隊(duì)遷移時(shí)間窗口

設(shè)置維護(hù)窗口:建議在業(yè)務(wù)低峰期進(jìn)行(如凌晨2:00-5:00)

客戶(hù)端檢查

  • 確??蛻?hù)端使用集群模式連接
  • 檢查客戶(hù)端重試機(jī)制是否完善
  • 驗(yàn)證客戶(hù)端是否支持MOVEDASK重定向

二、詳細(xì)遷移步驟

2.1 添加新節(jié)點(diǎn)到集群

如果你的集群數(shù)據(jù)量不大(<10GB),可以直接將新節(jié)點(diǎn)作為主節(jié)點(diǎn)加入集群。對(duì)于大型Redis集群,先添加為從節(jié)點(diǎn)再提升為主節(jié)點(diǎn)是更優(yōu)的擴(kuò)容策略。(具體可看后面的完整遷移腳本)

# 1. 將新節(jié)點(diǎn)作為主節(jié)點(diǎn)加入集群
redis-cli --cluster add-node 192.168.1.104:6379 192.168.1.101:6379

# 2. 驗(yàn)證節(jié)點(diǎn)已加入但未分配槽
redis-cli -h 192.168.1.101 -p 6379 cluster nodes | grep 192.168.1.104
# 輸出應(yīng)顯示新節(jié)點(diǎn),但flags為"master"且沒(méi)有槽分配

# 3. 確認(rèn)當(dāng)前槽分布(遷移前)
echo "當(dāng)前槽分布:"
redis-cli --cluster info 192.168.1.101:6379

2.2 計(jì)算遷移計(jì)劃

#!/usr/bin/env python3
# calculate_slots_redistribution.py

import sys

TOTAL_SLOTS = 16384
CURRENT_NODES = 3
NEW_NODES = 4

# 理想分布
slots_per_node = TOTAL_SLOTS // NEW_NODES  # 4096

print("=" * 60)
print("Redis集群槽遷移計(jì)算")
print("=" * 60)
print(f"總槽數(shù): {TOTAL_SLOTS}")
print(f"當(dāng)前節(jié)點(diǎn)數(shù): {CURRENT_NODES}")
print(f"目標(biāo)節(jié)點(diǎn)數(shù): {NEW_NODES}")
print(f"目標(biāo)每個(gè)節(jié)點(diǎn)槽數(shù): {slots_per_node}")
print()

# 從每個(gè)現(xiàn)有節(jié)點(diǎn)需要遷移出的槽數(shù)
slots_to_move_from_each = (TOTAL_SLOTS // CURRENT_NODES) - slots_per_node
print(f"從每個(gè)現(xiàn)有節(jié)點(diǎn)需要遷移出槽數(shù): {slots_to_move_from_each}")
print()

# 實(shí)際分配方案
print("建議遷移方案:")
print(f"1. 從節(jié)點(diǎn)1遷移 {slots_to_move_from_each} 個(gè)槽到新節(jié)點(diǎn)")
print(f"2. 從節(jié)點(diǎn)2遷移 {slots_to_move_from_each} 個(gè)槽到新節(jié)點(diǎn)")
print(f"3. 從節(jié)點(diǎn)3遷移 {slots_to_move_from_each} 個(gè)槽到新節(jié)點(diǎn)")
print()
print(f"遷移后分布:")
print(f"? 節(jié)點(diǎn)1: {slots_per_node} 槽")
print(f"? 節(jié)點(diǎn)2: {slots_per_node} 槽")
print(f"? 節(jié)點(diǎn)3: {slots_per_node} 槽")
print(f"? 節(jié)點(diǎn)4: {slots_per_node} 槽")
print("=" * 60)

2.3 執(zhí)行遷移操作

方案A:自動(dòng)重新分片(推薦)

#!/bin/bash
# auto_reshard.sh

CLUSTER_NODE="192.168.1.101:6379"
NEW_NODE_ID=""  # 需要先獲取新節(jié)點(diǎn)的ID

# 1. 獲取新節(jié)點(diǎn)ID
NEW_NODE_ID=$(redis-cli -h 192.168.1.104 -p 6379 cluster myid | tr -d '"')
echo "新節(jié)點(diǎn)ID: $NEW_NODE_ID"

# 2. 執(zhí)行自動(dòng)重新平衡
# --cluster-use-empty-masters: 使用空的主節(jié)點(diǎn)
# --cluster-threshold: 平衡閾值,默認(rèn)2表示差異超過(guò)2%時(shí)觸發(fā)平衡
# --cluster-timeout: 遷移超時(shí)時(shí)間(毫秒)
redis-cli --cluster rebalance $CLUSTER_NODE \
    --cluster-weight ${NEW_NODE_ID}=1 \
    --cluster-use-empty-masters \
    --cluster-threshold 1 \
    --cluster-timeout 60000

方案B:手動(dòng)控制遷移(更精確)

#!/bin/bash
# manual_reshard.sh

SOURCE_NODE1="192.168.1.101:6379"
SOURCE_NODE2="192.168.1.102:6379"
SOURCE_NODE3="192.168.1.103:6379"
NEW_NODE="192.168.1.104:6379"
SLOTS_PER_MOVE=100  # 每次遷移100個(gè)槽,避免一次性遷移過(guò)多

# 1. 獲取所有節(jié)點(diǎn)ID
NODE1_ID=$(redis-cli -h 192.168.1.101 -p 6379 cluster myid | tr -d '"')
NODE2_ID=$(redis-cli -h 192.168.1.102 -p 6379 cluster myid | tr -d '"')
NODE3_ID=$(redis-cli -h 192.168.1.103 -p 6379 cluster myid | tr -d '"')
NEW_NODE_ID=$(redis-cli -h 192.168.1.104 -p 6379 cluster myid | tr -d '"')

echo "節(jié)點(diǎn)ID列表:"
echo "- 節(jié)點(diǎn)1: $NODE1_ID"
echo("- 節(jié)點(diǎn)2: $NODE2_ID")
echo("- 節(jié)點(diǎn)3: $NODE3_ID")
echo("- 新節(jié)點(diǎn): $NEW_NODE_ID")

# 2. 從每個(gè)源節(jié)點(diǎn)遷移槽到新節(jié)點(diǎn)
for source in "$NODE1_ID" "$NODE2_ID" "$NODE3_ID"; do
    echo "從節(jié)點(diǎn) $source 遷移槽到新節(jié)點(diǎn)..."
    
    # 交互式遷移,每次遷移1365個(gè)槽(根據(jù)計(jì)算得出)
    redis-cli --cluster reshard $SOURCE_NODE1 \
        --cluster-from $source \
        --cluster-to $NEW_NODE_ID \
        --cluster-slots 1365 \
        --cluster-yes \
        --cluster-timeout 30000 \
        --cluster-pipeline 10  # 每次遷移10個(gè)key
    
    # 等待10秒,讓集群穩(wěn)定
    sleep 10
    
    # 檢查遷移進(jìn)度
    redis-cli --cluster check $SOURCE_NODE1 | grep -A5 "Slot distribution"
done

# 3. 驗(yàn)證最終槽分布
echo "最終槽分布驗(yàn)證:"
redis-cli --cluster check $SOURCE_NODE1

2.4 遷移過(guò)程監(jiān)控

#!/bin/bash
# migration_monitor.sh

CLUSTER_NODE="192.168.1.101:6379"
LOG_FILE="migration_monitor_$(date +%Y%m%d_%H%M%S).log"

monitor_migration() {
    while true; do
        echo "========================================" >> $LOG_FILE
        echo "時(shí)間: $(date)" >> $LOG_FILE
        echo "========================================" >> $LOG_FILE
        
        # 1. 檢查集群健康狀態(tài)
        echo "[集群狀態(tài)]" >> $LOG_FILE
        redis-cli --cluster check $CLUSTER_NODE 2>&1 | tail -20 >> $LOG_FILE
        
        # 2. 檢查槽遷移狀態(tài)
        echo -e "\n[槽狀態(tài)]" >> $LOG_FILE
        redis-cli -h 192.168.1.101 -p 6379 cluster slots | \
            awk '{print "節(jié)點(diǎn)區(qū)間:", $1"-"$2, "數(shù)量:", $2-$1+1}' | \
            sort -n >> $LOG_FILE
        
        # 3. 檢查各節(jié)點(diǎn)內(nèi)存使用
        echo -e "\n[內(nèi)存使用]" >> $LOG_FILE
        for node in 192.168.1.{101,102,103,104}:6379; do
            mem=$(redis-cli -c -h ${node%:*} -p ${node#*:} info memory | \
                  grep "used_memory_human" | cut -d: -f2)
            echo "$node: $mem" >> $LOG_FILE
        done
        
        # 4. 檢查遷移中的key數(shù)量
        echo -e "\n[各節(jié)點(diǎn)鍵數(shù)量]" >> $LOG_FILE
        for node in 192.168.1.{101,102,103,104}:6379; do
            count=$(redis-cli -c -h ${node%:*} -p ${node#*:} dbsize)
            echo "$node: $count keys" >> $LOG_FILE
        done
        
        # 5. 檢查連接數(shù)
        echo -e "\n[連接數(shù)]" >> $LOG_FILE
        for node in 192.168.1.{101,102,103,104}:6379; do
            conn=$(redis-cli -c -h ${node%:*} -p ${node#*:} info clients | \
                   grep "connected_clients" | cut -d: -f2)
            echo "$node: $conn connections" >> $LOG_FILE
        done
        
        # 等待30秒后再次檢查
        sleep 30
        
        # 清屏并顯示最新?tīng)顟B(tài)
        clear
        tail -50 $LOG_FILE
    done
}

# 啟動(dòng)監(jiān)控
monitor_migration

2.5 遷移后驗(yàn)證

#!/bin/bash
# post_migration_validation.sh

echo "=========== 遷移后驗(yàn)證 ==========="

# 1. 驗(yàn)證集群狀態(tài)
echo "1. 集群狀態(tài)檢查..."
redis-cli --cluster check 192.168.1.101:6379
if [ $? -eq 0 ]; then
    echo "? 集群狀態(tài)正常"
else
    echo "? 集群狀態(tài)異常"
    exit 1
fi

# 2. 驗(yàn)證槽分布
echo -e "\n2. 槽分布驗(yàn)證..."
TOTAL_SLOTS=$(redis-cli -h 192.168.1.101 -p 6379 cluster info | grep "cluster_slots_assigned" | cut -d: -f2)
if [ "$TOTAL_SLOTS" -eq 16384 ]; then
    echo "? 所有槽已分配 (16384)"
else
    echo "? 槽分配不完整: $TOTAL_SLOTS"
    exit 1
fi

# 3. 驗(yàn)證槽是否均勻分布
echo -e "\n3. 槽分布均勻性檢查..."
SLOT_DISTRIBUTION=$(redis-cli --cluster info 192.168.1.101:6379 | grep -A4 "Slot distribution")
echo "$SLOT_DISTRIBUTION"

# 4. 數(shù)據(jù)抽樣驗(yàn)證
echo -e "\n4. 數(shù)據(jù)抽樣驗(yàn)證..."
# 隨機(jī)測(cè)試一些key是否可訪問(wèn)
TEST_KEYS=("user:1001" "session:abc123" "product:500" "order:20230101")
for key in "${TEST_KEYS[@]}"; do
    # 先設(shè)置測(cè)試key(如果不存在)
    redis-cli -c -h 192.168.1.101 -p 6379 set "$key" "test_value_$(date +%s)" > /dev/null 2>&1
    
    # 獲取key值
    result=$(redis-cli -c -h 192.168.1.101 -p 6379 get "$key" 2>/dev/null)
    if [ -n "$result" ]; then
        echo "? Key '$key' 訪問(wèn)正常"
    else
        echo "? Key '$key' 訪問(wèn)失敗"
    fi
done

# 5. 性能測(cè)試
echo -e "\n5. 簡(jiǎn)單性能測(cè)試..."
START_TIME=$(date +%s%N)
for i in {1..100}; do
    redis-cli -c -h 192.168.1.101 -p 6379 set "perf_test:$i" "value_$i" > /dev/null 2>&1
done
END_TIME=$(date +%s%N)
DURATION=$((($END_TIME - $START_TIME)/1000000))
echo "100次SET操作耗時(shí): ${DURATION}ms"

# 6. 清理測(cè)試數(shù)據(jù)
echo -e "\n6. 清理測(cè)試數(shù)據(jù)..."
for i in {1..100}; do
    redis-cli -c -h 192.168.1.101 -p 6379 del "perf_test:$i" > /dev/null 2>&1
done
for key in "${TEST_KEYS[@]}"; do
    redis-cli -c -h 192.168.1.101 -p 6379 del "$key" > /dev/null 2>&1
done

echo -e "\n=========== 驗(yàn)證完成 ==========="

三、遷移優(yōu)化和注意事項(xiàng)

3.1 性能優(yōu)化參數(shù)

# 在遷移命令中調(diào)整以下參數(shù)優(yōu)化性能:

redis-cli --cluster reshard <host>:<port> \
    --cluster-slots <num> \
    --cluster-pipeline 100 \           # 增大pipeline大小
    --cluster-timeout 120000 \         # 增加超時(shí)時(shí)間
    --cluster-replace \               # 允許替換已存在的key
    --cluster-yes                     # 自動(dòng)確認(rèn)

3.2 大key特殊處理

如果集群中有大key(> 1MB),需要特殊處理:

# 1. 查找大key
redis-cli -h 192.168.1.101 -p 6379 --bigkeys

# 2. 對(duì)大key所在槽單獨(dú)遷移
# 使用較小的pipeline值
redis-cli --cluster reshard 192.168.1.101:6379 \
    --cluster-from <source_node_id> \
    --cluster-to <target_node_id> \
    --cluster-slots <slot_number> \
    --cluster-pipeline 1 \            # 對(duì)大key使用較小的pipeline
    --cluster-timeout 300000

3.3 回滾方案

如果遷移出現(xiàn)問(wèn)題,需要回滾:

# 1. 停止新節(jié)點(diǎn)
redis-cli -h 192.168.1.104 -p 6379 shutdown

# 2. 將槽遷移回原節(jié)點(diǎn)
# 需要記錄遷移前的槽分布,然后反向遷移

# 3. 從集群中移除問(wèn)題節(jié)點(diǎn)
redis-cli --cluster del-node 192.168.1.101:6379 <new_node_id>

# 4. 恢復(fù)備份配置
# 如果有配置備份,恢復(fù)到之前的狀態(tài)

3.4 客戶(hù)端配置更新

遷移完成后,更新客戶(hù)端配置:更新配置時(shí)采用滾動(dòng)更新,避免全量重啟

# Python客戶(hù)端配置示例
import redis

# 更新節(jié)點(diǎn)列表
cluster_nodes = [
    {"host": "192.168.1.101", "port": 6379},
    {"host": "192.168.1.102", "port": 6379},
    {"host": "192.168.1.103", "port": 6379},
    {"host": "192.168.1.104", "port": 6379},  # 新增節(jié)點(diǎn)
]

# 重新初始化集群連接
cluster_client = redis.RedisCluster(
    startup_nodes=cluster_nodes,
    decode_responses=True,
    socket_connect_timeout=5,
    retry_on_timeout=True,
    max_connections=50
)

3.5 平滑遷移策略:

  1. 分批次遷移:按 key 前綴或槽位范圍分批遷移
  2. 監(jiān)控遷移速度:控制遷移速度,避免影響線上性能
  3. 數(shù)據(jù)校驗(yàn):遷移后驗(yàn)證數(shù)據(jù)一致性
  4. 回滾計(jì)劃:準(zhǔn)備回滾方案

3.6. 最佳實(shí)踐建議

  • 選擇低峰期:在業(yè)務(wù)低峰時(shí)段執(zhí)行遷移
  • 充分備份:遷移前備份所有節(jié)點(diǎn)數(shù)據(jù)
  • 監(jiān)控指標(biāo):內(nèi)存使用率、QPS 和延遲、網(wǎng)絡(luò)帶
  • 測(cè)試驗(yàn)證:在測(cè)試環(huán)境先演練完整流程

3.7 注意事項(xiàng)

  • 數(shù)據(jù)一致性:遷移過(guò)程中確保數(shù)據(jù)不丟失
  • 客戶(hù)端連接:客戶(hù)端需要感知新的節(jié)點(diǎn)拓?fù)?/li>
  • 主從復(fù)制:如果有主從架構(gòu),需要考慮復(fù)制鏈路的調(diào)整
  • 持久化:遷移期間可能需要暫時(shí)關(guān)閉 AOF 重寫(xiě)等操作

四、完整遷移腳本

適合生產(chǎn)環(huán)境中,特別是對(duì)于大型Redis集群,先添加為從節(jié)點(diǎn)再提升為主節(jié)點(diǎn),以利用數(shù)據(jù)預(yù)同步,減少遷移時(shí)間。

#!/bin/bash
# complete_migration.sh
#
# Redis集群從3節(jié)點(diǎn)擴(kuò)容到4節(jié)點(diǎn)完整遷移腳本
# 使用方法: ./complete_migration.sh <new_node_ip>

set -e  # 遇到錯(cuò)誤立即退出

NEW_NODE="${1:-192.168.1.104}"
PORT=6379
CLUSTER_ENTRY="192.168.1.101:6379"
LOG_DIR="/var/log/redis_migration"
mkdir -p $LOG_DIR

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_DIR/migration.log
}

check_prerequisites() {
    log "檢查前置條件..."
    
    # 檢查Redis版本
    redis_version=$(redis-cli -v | awk '{print $2}' | cut -d. -f1)
    if [ "$redis_version" -lt 5 ]; then
        log "錯(cuò)誤: Redis版本需要5.0以上"
        exit 1
    fi
    
    # 檢查集群狀態(tài)
    if ! redis-cli --cluster check $CLUSTER_ENTRY > /dev/null 2>&1; then
        log "錯(cuò)誤: 集群狀態(tài)不正常"
        exit 1
    fi
    
    # 檢查新節(jié)點(diǎn)是否可訪問(wèn)
    if ! redis-cli -h $NEW_NODE -p $PORT ping > /dev/null 2>&1; then
        log "錯(cuò)誤: 新節(jié)點(diǎn)無(wú)法訪問(wèn)"
        exit 1
    fi
    
    log "? 前置條件檢查通過(guò)"
}

add_new_node() {
    log "添加新節(jié)點(diǎn)到集群..."
    
    redis-cli --cluster add-node ${NEW_NODE}:${PORT} $CLUSTER_ENTRY \
        --cluster-slave \
        --cluster-master-id $(redis-cli -h $CLUSTER_ENTRY cluster nodes | grep master | head -1 | awk '{print $1}') \
        2>&1 | tee -a $LOG_DIR/add_node.log
    
    # 等待節(jié)點(diǎn)同步
    sleep 10
    
    # 將新節(jié)點(diǎn)提升為主節(jié)點(diǎn)
    NEW_NODE_ID=$(redis-cli -h $NEW_NODE -p $PORT cluster myid | tr -d '"')
    redis-cli --cluster rebalance $CLUSTER_ENTRY \
        --cluster-weight ${NEW_NODE_ID}=1 \
        --cluster-use-empty-masters \
        --cluster-threshold 1 \
        2>&1 | tee -a $LOG_DIR/promote_node.log
    
    log "? 新節(jié)點(diǎn)添加完成"
}

perform_migration() {
    log "開(kāi)始數(shù)據(jù)遷移..."
    
    # 獲取新節(jié)點(diǎn)ID
    NEW_NODE_ID=$(redis-cli -h $NEW_NODE -p $PORT cluster myid | tr -d '"')
    
    # 執(zhí)行重新分片
    redis-cli --cluster reshard $CLUSTER_ENTRY \
        --cluster-from all \
        --cluster-to $NEW_NODE_ID \
        --cluster-slots 4096 \
        --cluster-yes \
        --cluster-timeout 120000 \
        --cluster-pipeline 50 \
        2>&1 | tee -a $LOG_DIR/reshard.log
    
    log "? 數(shù)據(jù)遷移完成"
}

post_migration_checks() {
    log "執(zhí)行遷移后檢查..."
    
    # 檢查集群狀態(tài)
    if redis-cli --cluster check $CLUSTER_ENTRY > $LOG_DIR/final_check.log 2>&1; then
        log "? 集群狀態(tài)正常"
    else
        log "? 集群狀態(tài)異常,請(qǐng)檢查日志: $LOG_DIR/final_check.log"
        exit 1
    fi
    
    # 驗(yàn)證槽分布
    slots_assigned=$(redis-cli -h ${CLUSTER_ENTRY%:*} -p ${CLUSTER_ENTRY#*:} cluster info | \
        grep "cluster_slots_assigned" | cut -d: -f2 | tr -d '\r')
    
    if [ "$slots_assigned" -eq 16384 ]; then
        log "? 所有槽已正確分配"
    else
        log "? 槽分配不完整: $slots_assigned/16384"
        exit 1
    fi
    
    log "? 所有檢查通過(guò)"
}

main() {
    log "開(kāi)始Redis集群擴(kuò)容遷移"
    log "目標(biāo): 從3節(jié)點(diǎn)擴(kuò)容到4節(jié)點(diǎn)"
    log "新節(jié)點(diǎn): $NEW_NODE:$PORT"
    
    check_prerequisites
    add_new_node
    perform_migration
    post_migration_checks
    
    log "遷移完成!"
    log "詳細(xì)信息請(qǐng)查看: $LOG_DIR/"
}

main "$@"

五、監(jiān)控和告警腳本

遷移期間設(shè)置監(jiān)控:

# 監(jiān)控關(guān)鍵指標(biāo)
watch -n 5 '
echo "=== Redis集群遷移監(jiān)控 ==="
echo "時(shí)間: $(date)"
echo
echo "1. 集群狀態(tài):"
redis-cli -h 192.168.1.101 -p 6379 cluster info | grep -E "(cluster_state|cluster_slots_ok|cluster_known_nodes)"
echo
echo "2. 遷移進(jìn)度:"
redis-cli --cluster info 192.168.1.101:6379 | grep -A2 "Slot distribution"
echo
echo "3. 節(jié)點(diǎn)狀態(tài):"
for node in 101 102 103 104; do
    echo -n "192.168.1.$node: "
    redis-cli -h 192.168.1.$node -p 6379 ping 2>/dev/null && \
    redis-cli -h 192.168.1.$node -p 6379 info memory | grep used_memory_human | cut -d: -f2
done
'

這個(gè)詳細(xì)方案提供了完整的遷移流程,包括準(zhǔn)備、執(zhí)行、驗(yàn)證和監(jiān)控各個(gè)階段的具體操作步驟和腳本,可以根據(jù)實(shí)際情況進(jìn)行調(diào)整使用。

六、 Redis Cluster 為什么只有 16384 個(gè)槽位?

技術(shù)原因 - 心跳包大小限制

Redis 集群節(jié)點(diǎn)之間通過(guò) CLUSTER MEET 消息通信,其中包含了節(jié)點(diǎn)負(fù)責(zé)的槽位信息。每個(gè)槽位用 1 個(gè) bit 表示(0 或 1)。

如果槽位數(shù)太多

  • 假設(shè) 65536 個(gè)槽位(2^16),心跳包需要 65536 / 8 = 8192 bytes = 8KB
  • 每個(gè)節(jié)點(diǎn)每秒鐘向其他 N-1 個(gè)節(jié)點(diǎn)發(fā)送心跳
  • 10 個(gè)節(jié)點(diǎn)的集群:8KB * 10 * 2(收發(fā))≈ 160KB/s 的網(wǎng)絡(luò)開(kāi)銷(xiāo)

16384 個(gè)槽位

  • 16384 / 8 = 2048 bytes = 2KB
  • 同樣的 10 節(jié)點(diǎn)集群:2KB * 10 * 2 ≈ 40KB/s
  • 網(wǎng)絡(luò)開(kāi)銷(xiāo)更合理

性能與擴(kuò)展性的平衡

# 計(jì)算示例
65536 槽位:節(jié)點(diǎn)數(shù)太少時(shí),每個(gè)節(jié)點(diǎn)槽位太多 → 數(shù)據(jù)傾斜
16384 槽位:更合理的分布,即使節(jié)點(diǎn)少也能均勻分布

# 實(shí)際最大節(jié)點(diǎn)數(shù)理論
16384 個(gè)槽位 / 最低建議每個(gè)節(jié)點(diǎn) 100 個(gè)槽位 ≈ 163 個(gè)節(jié)點(diǎn)
對(duì)于絕大多數(shù)場(chǎng)景,163 個(gè)節(jié)點(diǎn)已經(jīng)足夠。

Redis 作者的解釋

Antirez(Redis 作者)在 GitHub issue 中解釋?zhuān)?/p>

  • 16384 是 2^14,足夠大以實(shí)現(xiàn)良好分布
  • 65536 會(huì)增加心跳包大小,網(wǎng)絡(luò)開(kāi)銷(xiāo)較大
  • CRC16 算法輸出 16 位(65536),但 Redis 只使用 14 位(16384)

為什么不能修改這個(gè)數(shù)字?

  • 兼容性:所有 Redis 客戶(hù)端都硬編碼了 16384
  • 協(xié)議固定:Redis 集群協(xié)議中槽位數(shù)量是固定的
  • 工具鏈依賴(lài):所有集群管理工具都基于這個(gè)設(shè)計(jì)

為什么不需要修改這個(gè)數(shù)字?

16384 是 Redis Cluster 的硬編碼限制,它是在性能、擴(kuò)展性和實(shí)現(xiàn)復(fù)雜度之間的最佳平衡點(diǎn)。這個(gè)設(shè)計(jì)雖然限制了理論最大節(jié)點(diǎn)數(shù),但足以滿(mǎn)足絕大多數(shù)生產(chǎn)場(chǎng)景的需求。如果你的應(yīng)用需要更多節(jié)點(diǎn),可能需要考慮其他分片方案,如基于代理的分片(Codis)或客戶(hù)端分片。

七、槽位分配示例

3 個(gè)節(jié)點(diǎn)的分配(原本):

Node1: slots 0-5460
Node2: slots 5461-10922  
Node3: slots 10923-16383

增加到 4 個(gè)節(jié)點(diǎn)后:

Node1: slots 0-4095        # 遷移 1365 個(gè)槽位給 Node4
Node2: slots 4096-8191     # 遷移 1365 個(gè)槽位給 Node4
Node3: slots 8192-12287    # 遷移 1365 個(gè)槽位給 Node4
Node4: slots 12288-16383   # 獲得 4096 個(gè)槽位

槽位計(jì)算公式

Redis 使用 CRC16 算法計(jì)算 key 屬于哪個(gè)槽位:

def slot(key):
    # 1. 如果 key 包含 "{}",只計(jì)算括號(hào)內(nèi)的部分
    # 2. 計(jì)算 CRC16(key) mod 16384
    return crc16(key_with_hash_tag) % 16384

實(shí)踐建議

雖然槽位數(shù)量固定,但實(shí)際應(yīng)用中:

  • 每個(gè)節(jié)點(diǎn)建議最少 100 個(gè)槽位,保證數(shù)據(jù)分布均勻
  • 最大推薦節(jié)點(diǎn)數(shù)16384 / 100 ≈ 163 個(gè)主節(jié)點(diǎn)
  • 如果節(jié)點(diǎn)數(shù) < 槽位數(shù),Redis 會(huì)自動(dòng)平均分配槽位
  • 數(shù)據(jù)傾斜時(shí):可以手動(dòng)調(diào)整槽位分布

到此這篇關(guān)于Redis集群擴(kuò)容數(shù)據(jù)遷移方案分析的文章就介紹到這了,更多相關(guān)Redis集群擴(kuò)容數(shù)據(jù)遷移內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis中zSet實(shí)現(xiàn)排行榜的使用示例

    redis中zSet實(shí)現(xiàn)排行榜的使用示例

    在工作中,有時(shí)候需要實(shí)現(xiàn)排行榜功能,本文主要介紹了redis中zSet實(shí)現(xiàn)排行榜的使用示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • Redis增減庫(kù)存避坑的實(shí)現(xiàn)

    Redis增減庫(kù)存避坑的實(shí)現(xiàn)

    在電商平臺(tái)或者倉(cāng)庫(kù)管理系統(tǒng)中,庫(kù)存的管理是非常重要的一項(xiàng)任務(wù),本文主要介紹了Redis增減庫(kù)存避坑的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 解決 Redis 數(shù)據(jù)傾斜、熱點(diǎn)等問(wèn)題

    解決 Redis 數(shù)據(jù)傾斜、熱點(diǎn)等問(wèn)題

    ?單臺(tái)機(jī)器的硬件配置有上限制約,一般我們會(huì)采用分布式架構(gòu)將多臺(tái)機(jī)器組成一個(gè)集群,這篇文章主要介紹了解決 Redis 數(shù)據(jù)傾斜、熱點(diǎn)等問(wèn)題,需要的朋友可以參考下
    2022-12-12
  • Redis的數(shù)據(jù)類(lèi)型和內(nèi)部編碼詳解

    Redis的數(shù)據(jù)類(lèi)型和內(nèi)部編碼詳解

    Redis是通過(guò)Key-Value的形式來(lái)組織數(shù)據(jù)的,而Key的類(lèi)型都是String,而Value的類(lèi)型可以有很多,在Redis中最通用的數(shù)據(jù)類(lèi)型大致有這幾種:String、List、Set、Hash、Sorted Set,下面通過(guò)本文介紹Redis數(shù)據(jù)類(lèi)型和內(nèi)部編碼,感興趣的朋友一起看看吧
    2024-04-04
  • Redis緩存更新策略詳解

    Redis緩存更新策略詳解

    本文介紹了4種核心緩存更新策略(Cache-Aside、Write-Through、Write-Behind、Refresh-Ahead),并討論了3種補(bǔ)充策略(Read-Through、最終一致性、過(guò)期淘汰),感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • Redis分布式鎖中8個(gè)常見(jiàn)面試題小結(jié)

    Redis分布式鎖中8個(gè)常見(jiàn)面試題小結(jié)

    本文主要介紹了Redis分布式鎖中8個(gè)常見(jiàn)面試題小結(jié),包括使用Redis、RedLock算法和ZooKeeper等工具,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • Redis中l(wèi)ua腳本實(shí)現(xiàn)及其應(yīng)用場(chǎng)景

    Redis中l(wèi)ua腳本實(shí)現(xiàn)及其應(yīng)用場(chǎng)景

    本文主要介紹了Redis中l(wèi)ua腳本實(shí)現(xiàn)及其應(yīng)用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Redis swap空間(虛擬內(nèi)存)的使用詳解

    Redis swap空間(虛擬內(nèi)存)的使用詳解

    這篇文章主要介紹了Redis swap空間的使用示例,幫助大家更好的理解和學(xué)習(xí)使用Redis數(shù)據(jù)庫(kù),感興趣的朋友可以了解下
    2021-03-03
  • redis?setex使用方法示例代碼

    redis?setex使用方法示例代碼

    SETEX?是?Redis?中的一個(gè)命令,用于設(shè)置鍵的值以及過(guò)期時(shí)間(以秒為單位),這篇文章主要介紹了redis?setex使用方法,需要的朋友可以參考下
    2024-07-07
  • 16個(gè)Redis的常見(jiàn)使用場(chǎng)景

    16個(gè)Redis的常見(jiàn)使用場(chǎng)景

    這篇文章主要介紹了Redis 常見(jiàn)使用場(chǎng)景的相關(guān)資料,需要的朋友可以參考下文
    2021-08-08

最新評(píng)論

新乡市| 浙江省| 德化县| 新巴尔虎左旗| 荥阳市| 临沭县| 普安县| 军事| 麻城市| 万宁市| 淮南市| 双辽市| 大宁县| 金湖县| 阿拉善右旗| 科尔| 昌平区| 辽阳市| 清苑县| 阿瓦提县| 汉川市| 萍乡市| 泽州县| 瓦房店市| 高尔夫| 延吉市| 托克托县| 鄯善县| 临武县| 高邑县| 弥勒县| 凤城市| 齐河县| 丰顺县| 临湘市| 尉犁县| 衡水市| 增城市| 略阳县| 岢岚县| 咸阳市|