国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Redis Sentinel和Cluster模式如何選擇

馬哥Linux運維 ? 來源:馬哥Linux運維 ? 2025-09-08 09:31 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Redis集群模式選擇:Sentinel vs Cluster深度對比實戰指南

引言:為什么這個選擇如此關鍵?

在我十年的運維生涯中,見過太多團隊在Redis集群方案選擇上踩坑。有的團隊盲目追求"高大上"的Cluster模式,結果運維復雜度爆表;有的團隊死守Sentinel不放,最后擴展性成了瓶頸。今天,我想通過這篇萬字長文,把我在生產環境中積累的經驗全部分享給你。

記得2019年,我們團隊面臨一個艱難的抉擇:電商大促在即,Redis承載的QPS即將突破50萬,是繼續優化現有的Sentinel架構,還是徹底遷移到Cluster?這個決策直接關系到大促的成敗。最終,通過深入的技術分析和壓測驗證,我們做出了正確的選擇,不僅順利度過大促,還將系統可用性提升到了99.99%。

這篇文章,我會把所有的技術細節、踩坑經驗、最佳實踐都分享出來。無論你是正在選型的架構師,還是想深入了解Redis的運維工程師,相信都能從中獲得價值。

一、架構本質:理解兩種模式的設計哲學

1.1 Redis Sentinel:主從復制的智能守護者

Redis Sentinel本質上是一個分布式監控系統,它并不改變Redis主從復制的基本架構,而是在其上增加了一層智能化的故障檢測和自動故障轉移機制。

核心設計理念:

?簡單性優先:保持Redis原有的主從架構不變,只增加監控層

?數據完整性:所有數據都在主節點,保證強一致性

?運維友好:配置簡單,易于理解和維護

讓我通過一個真實案例來說明Sentinel的工作原理

# Sentinel配置示例 - sentinel.conf
port 26379
dir/tmp
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

# 配置解析
# - monitor: 監控名為mymaster的主節點
# - 2: 表示需要2個Sentinel同意才能判定主節點失效(quorum)
# - down-after-milliseconds: 30秒內無響應則認為主觀下線
# - parallel-syncs: 故障轉移時,同時進行同步的從節點數量
# - failover-timeout: 故障轉移超時時間

Sentinel的工作流程深度剖析:

1.主觀下線(SDOWN)檢測

# 模擬Sentinel的心跳檢測邏輯
importtime
importredis

classSentinelMonitor:
 def__init__(self, master_addr, check_interval=1):
   self.master_addr = master_addr
   self.check_interval = check_interval
   self.last_ping_time = time.time()
   self.down_after_ms =30000# 30秒
   
 defcheck_master_health(self):
   try:
      r = redis.Redis(host=self.master_addr[0],
             port=self.master_addr[1],
             socket_timeout=1)
      r.ping()
     self.last_ping_time = time.time()
     return"MASTER_OK"
   except:
     if(time.time() -self.last_ping_time) *1000>self.down_after_ms:
       return"SDOWN"# 主觀下線
     return"CHECKING"

2.客觀下線(ODOWN)判定

# Sentinel間的協商機制
classSentinelCluster:
 def__init__(self, sentinels, quorum):
   self.sentinels = sentinels
   self.quorum = quorum
   
 defis_master_down(self, master_addr):
    down_votes =0
   forsentinelinself.sentinels:
     ifsentinel.check_master_health() =="SDOWN":
        down_votes +=1
   
   ifdown_votes >=self.quorum:
     return"ODOWN"# 客觀下線,觸發故障轉移
   return"ALIVE"

3.Leader選舉與故障轉移

Sentinel使用Raft協議的簡化版本進行Leader選舉。這里是核心流程:

# 故障轉移腳本示例
#!/bin/bash

# 步驟1:選舉Leader Sentinel
functionelect_leader() {
 localepoch=$(redis-cli -p 26379 sentinel get-master-addr-by-name mymaster | grep epoch)
 localleader_id=$(redis-cli -p 26379 sentinel masters | grep leader-id)
 echo"Current epoch:$epoch, Leader:$leader_id"
}

# 步驟2:選擇新的主節點
functionselect_new_master() {
 # 優先級最高的從節點
 # 復制偏移量最大的從節點(數據最新)
 # run_id最小的從節點(啟動時間最早)
  redis-cli -p 26379 sentinel slaves mymaster | 
    awk'/slave-priority/{print $2}'| 
   sort-n |head-1
}

# 步驟3:執行故障轉移
functionperform_failover() {
 localnew_master=$1
 
 # 將選中的從節點提升為主節點
  redis-cli -h$new_masterslaveof no one
 
 # 將其他從節點重新指向新主節點
 forslavein$(get_other_slaves);do
    redis-cli -h$slaveslaveof$new_master6379
 done
 
 # 更新客戶端配置
  update_client_config$new_master
}

1.2 Redis Cluster:分布式哈希的藝術

Redis Cluster是一個完全不同的架構思路,它通過數據分片實現了真正的分布式存儲。

核心設計理念:

?水平擴展:通過增加節點線性提升容量和性能

?中心:沒有代理層,客戶端直連數據節點

?高可用內置:每個主節點都可以有多個從節點

Cluster的槽位機制詳解:

Redis Cluster將整個數據空間劃分為16384個槽位(slot),每個鍵通過CRC16算法映射到特定槽位:

# Redis Cluster的槽位計算實現
defkeyHashSlot(key):
 """計算key對應的槽位"""
 # 處理hash tag的情況
  s = key.find('{')
 ifs != -1:
    e = key.find('}', s+1)
   ife != -1ande > s+1:
      key = key[s+1:e]
 
 # CRC16算法
  crc = crc16(key.encode())
 returncrc &0x3FFF# 16383 = 0x3FFF

# 槽位分配示例
classClusterNode:
 def__init__(self, node_id, slots_range):
   self.node_id = node_id
   self.slots = slots_range
   self.data = {}
 
 defis_my_slot(self, slot):
   returnslotinself.slots
 
 defhandle_key(self, key, value=None):
    slot = keyHashSlot(key)
   ifself.is_my_slot(slot):
     ifvalueisnotNone:
       self.data[key] = value
       return"OK"
     returnself.data.get(key)
   else:
     # 返回MOVED錯誤,告知客戶端正確的節點
      correct_node =self.find_node_for_slot(slot)
     returnf"MOVED{slot}{correct_node}"

Cluster的通信協議:Gossip的精妙設計

# Gossip協議實現示例
importrandom
importtime

classGossipProtocol:
 def__init__(self, node_id, all_nodes):
   self.node_id = node_id
   self.all_nodes = all_nodes
   self.node_states = {} # 存儲其他節點的狀態信息
   self.heartbeat_interval =1# 1秒
   
 defgossip_round(self):
   """執行一輪Gossip通信"""
   # 隨機選擇節點進行通信
    target_nodes = random.sample(
      [nforninself.all_nodesifn !=self.node_id],
     min(3,len(self.all_nodes)-1) # 每次最多與3個節點通信
    )
   
   fortargetintarget_nodes:
     self.exchange_info(target)
 
 defexchange_info(self, target_node):
   """與目標節點交換信息"""
    my_info = {
     'node_id':self.node_id,
     'timestamp': time.time(),
     'slots':self.get_my_slots(),
     'state':'ok',
     'config_epoch':self.config_epoch
    }
   
   # 發送PING消息
    response =self.send_ping(target_node, my_info)
   
   # 處理PONG響應
   ifresponse:
     self.update_node_state(target_node, response)
     
 defdetect_failure(self):
   """故障檢測邏輯"""
    current_time = time.time()
   fornode_id, stateinself.node_states.items():
      last_seen = state.get('last_seen',0)
     ifcurrent_time - last_seen >30: # 30秒未響應
       self.mark_node_as_fail(node_id)

二、性能對比:用數據說話

2.1 基準測試環境搭建

為了公平對比兩種模式的性能,我搭建了如下測試環境:

# 測試環境配置
硬件配置:
CPU:IntelXeonGold6248R@3.0GHz(48核)
內存:256GBDDR43200MHz
磁盤:NVMeSSD3.2TB
網絡:萬兆網卡

軟件版本:
Redis:7.0.11
OS:CentOS8.5
Kernel:5.4.0

測試工具:
-redis-benchmark
-memtier_benchmark
-自研壓測工具

網絡拓撲:
-3個主節點+3個從節點
-客戶端與Redis節點同機房
-網絡延遲

2.2 性能測試結果

場景1:單鍵操作性能對比

# 測試腳本
importtime
importredis
fromredis.sentinelimportSentinel
fromredisclusterimportRedisCluster

defbenchmark_single_key_ops(client, operation_count=1000000):
 """單鍵操作性能測試"""
  results = {
   'set': [],
   'get': [],
   'incr': [],
   'del': []
  }
 
 # SET操作測試
  start = time.time()
 foriinrange(operation_count):
    client.set(f'key_{i}',f'value_{i}')
  results['set'] = (time.time() - start) / operation_count *1000# ms
 
 # GET操作測試
  start = time.time()
 foriinrange(operation_count):
    client.get(f'key_{i}')
  results['get'] = (time.time() - start) / operation_count *1000
 
 returnresults

# Sentinel模式測試
sentinel = Sentinel([('localhost',26379)])
master = sentinel.master_for('mymaster', socket_timeout=0.1)
sentinel_results = benchmark_single_key_ops(master)

# Cluster模式測試
startup_nodes = [
  {"host":"127.0.0.1","port":"7000"},
  {"host":"127.0.0.1","port":"7001"},
  {"host":"127.0.0.1","port":"7002"}
]
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
cluster_results = benchmark_single_key_ops(rc)

測試結果數據:

操作類型 Sentinel模式 Cluster模式 性能差異
SET (10萬QPS) 0.082ms 0.095ms +15.8%
GET (10萬QPS) 0.076ms 0.089ms +17.1%
INCR (10萬QPS) 0.079ms 0.091ms +15.2%
Pipeline SET (1000條) 8.2ms 12.6ms +53.7%
MGET (100個key) 0.92ms 3.87ms +320.7%

場景2:批量操作性能對比

# 使用redis-benchmark進行批量操作測試

# Sentinel模式 - Pipeline批量寫入
redis-benchmark -h 127.0.0.1 -p 6379 -tset-n 1000000 -P 100 -q
SET: 892857.14 requests per second

# Cluster模式 - Pipeline批量寫入(注意:需要同槽位)
redis-benchmark -h 127.0.0.1 -p 7000 -tset-n 1000000 -P 100 -q
SET: 657894.74 requests per second

# 跨槽位批量操作性能測試
foriin{1..10000};do
  redis-cli -c -p 7000eval"
    for i=1,100 do
      redis.call('set', 'key'..math.random(1,1000000), 'value')
    end
  "0
done
# 平均耗時:15.3ms(由于需要多次網絡往返)

2.3 內存使用對比

# 內存占用分析腳本
defanalyze_memory_usage():
 """分析兩種模式的內存占用"""
 
 # Sentinel模式內存分析
  sentinel_info = {
   'used_memory':'8.5GB',
   'used_memory_rss':'9.2GB',
   'mem_fragmentation_ratio':1.08,
   'overhead': {
     'replication_buffer':'256MB',
     'client_buffer':'128MB',
     'aof_buffer':'64MB'
    }
  }
 
 # Cluster模式內存分析
  cluster_info = {
   'used_memory':'9.8GB', # 相同數據量
   'used_memory_rss':'11.1GB',
   'mem_fragmentation_ratio':1.13,
   'overhead': {
     'cluster_state':'512MB', # 集群狀態信息
     'gossip_buffer':'256MB',
     'migration_buffer':'128MB',
     'slots_bitmap':'64MB'
    }
  }
 
 # 內存額外開銷對比
  sentinel_overhead =sum(sentinel_info['overhead'].values())
  cluster_overhead =sum(cluster_info['overhead'].values())
 
 print(f"Sentinel額外內存開銷:{sentinel_overhead}MB")
 print(f"Cluster額外內存開銷:{cluster_overhead}MB")
 print(f"Cluster相比Sentinel多占用:{cluster_overhead - sentinel_overhead}MB")

三、運維復雜度:真實場景的挑戰

3.1 部署復雜度對比

Sentinel模式部署實戰:

#!/bin/bash
# Sentinel一鍵部署腳本

# 配置參數
REDIS_VERSION="7.0.11"
MASTER_IP="192.168.1.10"
SLAVE_IPS=("192.168.1.11""192.168.1.12")
SENTINEL_IPS=("192.168.1.20""192.168.1.21""192.168.1.22")

# 部署主節點
functiondeploy_master() {
  ssh$MASTER_IP< /etc/redis.conf <> /etc/redis.conf
      echo "slave-read-only yes" >> /etc/redis.conf
     
      # 啟動從節點
      redis-server /etc/redis.conf
EOF
 done
}

# 部署Sentinel節點
functiondeploy_sentinels() {
 forsentinel_ipin"${SENTINEL_IPS[@]}";do
    ssh$sentinel_ip< /etc/sentinel.conf << 'EOC'
? ? ? ? ? ? port 26379
? ? ? ? ? ? daemonize yes
? ? ? ? ? ? pidfile /var/run/redis-sentinel.pid
? ? ? ? ? ? logfile /var/log/redis-sentinel.log
? ? ? ? ? ? dir /tmp
? ? ? ? ? ??
? ? ? ? ? ? # 監控配置
? ? ? ? ? ? sentinel monitor mymaster $MASTER_IP 6379 2
? ? ? ? ? ? sentinel auth-pass mymaster yourpassword
? ? ? ? ? ? sentinel down-after-milliseconds mymaster 30000
? ? ? ? ? ? sentinel parallel-syncs mymaster 1
? ? ? ? ? ? sentinel failover-timeout mymaster 180000
? ? ? ? ? ??
? ? ? ? ? ? # 通知腳本
? ? ? ? ? ? sentinel notification-script mymaster /usr/local/bin/notify.sh
EOC
? ? ? ? ? ??
? ? ? ? ? ? # 啟動Sentinel
? ? ? ? ? ? redis-sentinel /etc/sentinel.conf
EOF
? ??done
}

# 執行部署
deploy_master
deploy_slaves
deploy_sentinels

echo?"Sentinel集群部署完成!"

Cluster模式部署實戰:

#!/bin/bash
# Cluster一鍵部署腳本

# 配置參數
CLUSTER_NODES=("192.168.1.30:7000""192.168.1.31:7001""192.168.1.32:7002"
       "192.168.1.33:7003""192.168.1.34:7004""192.168.1.35:7005")

# 部署所有節點
functiondeploy_cluster_nodes() {
 fornodein"${CLUSTER_NODES[@]}";do
    IFS=':'read-r ip port << /data/redis-cluster/$port/redis.conf << 'EOC'
? ? ? ? ? ? port $port
? ? ? ? ? ? cluster-enabled yes
? ? ? ? ? ? cluster-config-file nodes-$port.conf
? ? ? ? ? ? cluster-node-timeout 5000
? ? ? ? ? ? appendonly yes
? ? ? ? ? ? appendfilename "appendonly-$port.aof"
? ? ? ? ? ? dbfilename dump-$port.rdb
? ? ? ? ? ? logfile /var/log/redis-$port.log
? ? ? ? ? ? daemonize yes
? ? ? ? ? ??
? ? ? ? ? ? # 集群特定配置
? ? ? ? ? ? cluster-require-full-coverage no
? ? ? ? ? ? cluster-migration-barrier 1
? ? ? ? ? ? cluster-replica-validity-factor 10
? ? ? ? ? ??
? ? ? ? ? ? # 性能配置
? ? ? ? ? ? tcp-backlog 511
? ? ? ? ? ? timeout 0
? ? ? ? ? ? tcp-keepalive 300
EOC
? ? ? ? ? ??
? ? ? ? ? ? # 啟動節點
? ? ? ? ? ? redis-server /data/redis-cluster/$port/redis.conf
EOF
? ??done
}

# 創建集群
function?create_cluster() {
? ??# 使用redis-cli創建集群
? ? redis-cli --cluster create 
? ? ? ? 192.168.1.30:7000 192.168.1.31:7001 192.168.1.32:7002 
? ? ? ? 192.168.1.33:7003 192.168.1.34:7004 192.168.1.35:7005 
? ? ? ? --cluster-replicas 1 
? ? ? ? --cluster-yes
}

# 驗證集群狀態
function?verify_cluster() {
? ? redis-cli --cluster check 192.168.1.30:7000
? ??
? ??# 檢查槽位分配
? ? redis-cli -c -h 192.168.1.30 -p 7000 cluster slots
? ??
? ??# 檢查節點狀態
? ? redis-cli -c -h 192.168.1.30 -p 7000 cluster nodes
}

# 執行部署
deploy_cluster_nodes
sleep?5
create_cluster
verify_cluster

echo?"Redis Cluster部署完成!"

3.2 日常運維對比

監控指標采集:

# 統一監控腳本
importredis
importjson
fromprometheus_clientimportGauge, start_http_server

# 定義Prometheus指標
redis_up = Gauge('redis_up','Redis server is up', ['instance','role'])
redis_connected_clients = Gauge('redis_connected_clients','Connected clients', ['instance'])
redis_used_memory = Gauge('redis_used_memory_bytes','Used memory', ['instance'])
redis_ops_per_sec = Gauge('redis_ops_per_sec','Operations per second', ['instance'])
redis_keyspace_hits = Gauge('redis_keyspace_hits','Keyspace hits', ['instance'])
redis_keyspace_misses = Gauge('redis_keyspace_misses','Keyspace misses', ['instance'])

classRedisMonitor:
 def__init__(self, mode='sentinel'):
   self.mode = mode
   self.connections = []
   
 defsetup_connections(self):
   ifself.mode =='sentinel':
     # Sentinel模式監控
      sentinel = Sentinel([('localhost',26379)])
     self.connections.append({
       'client': sentinel.master_for('mymaster'),
       'role':'master',
       'instance':'mymaster'
      })
     forslaveinsentinel.slaves('mymaster'):
       self.connections.append({
         'client': slave,
         'role':'slave',
         'instance':f'slave_{slave.connection_pool.connection_kwargs["host"]}'
        })
   else:
     # Cluster模式監控
      startup_nodes = [
        {"host":"127.0.0.1","port":"7000"},
        {"host":"127.0.0.1","port":"7001"},
        {"host":"127.0.0.1","port":"7002"}
      ]
      rc = RedisCluster(startup_nodes=startup_nodes)
     fornode_id, node_infoinrc.cluster_nodes().items():
       self.connections.append({
         'client': redis.Redis(host=node_info['host'], port=node_info['port']),
         'role':'master'if'master'innode_info['flags']else'slave',
         'instance':f'{node_info["host"]}:{node_info["port"]}'
        })
 
 defcollect_metrics(self):
   """采集監控指標"""
   forconninself.connections:
     try:
        client = conn['client']
        info = client.info()
       
       # 基礎指標
        redis_up.labels(instance=conn['instance'], role=conn['role']).set(1)
        redis_connected_clients.labels(instance=conn['instance']).set(
          info.get('connected_clients',0)
        )
        redis_used_memory.labels(instance=conn['instance']).set(
          info.get('used_memory',0)
        )
       
       # 性能指標
        redis_ops_per_sec.labels(instance=conn['instance']).set(
          info.get('instantaneous_ops_per_sec',0)
        )
        redis_keyspace_hits.labels(instance=conn['instance']).set(
          info.get('keyspace_hits',0)
        )
        redis_keyspace_misses.labels(instance=conn['instance']).set(
          info.get('keyspace_misses',0)
        )
       
       # Cluster特有指標
       ifself.mode =='cluster':
          cluster_info = client.cluster_info()
         # 采集集群狀態、槽位信息等
         
     exceptExceptionase:
        redis_up.labels(instance=conn['instance'], role=conn['role']).set(0)
       print(f"Error collecting metrics from{conn['instance']}:{e}")

3.3 故障處理實戰

場景1:主節點故障

Sentinel模式處理:

# 故障檢測和自動切換日志分析
tail-f /var/log/redis-sentinel.log | grep -E"sdown|odown|switch-master"

# 輸出示例:
# +sdown master mymaster 192.168.1.10 6379
# +odown master mymaster 192.168.1.10 6379#quorum2/2
# +vote-for-leader 7f7e7c7e7d7e7f7e7g7h 1
# +elected-leader master mymaster 192.168.1.10 6379
# +failover-state-select-slave master mymaster 192.168.1.10 6379
# +selected-slave slave 192.168.1.11:6379 192.168.1.11 6379 @ mymaster 192.168.1.10 6379
# +failover-state-send-slaveof-noone slave 192.168.1.11:6379
# +switch-master mymaster 192.168.1.10 6379 192.168.1.11 6379

# 手動故障轉移(如需要)
redis-cli -p 26379 sentinel failover mymaster

Cluster模式處理:

# Cluster故障檢測和處理腳本
classClusterFailoverHandler:
 def__init__(self, cluster_nodes):
   self.rc = RedisCluster(startup_nodes=cluster_nodes)
   
 defdetect_failed_nodes(self):
   """檢測故障節點"""
    failed_nodes = []
    cluster_state =self.rc.cluster_nodes()
   
   fornode_id, node_infoincluster_state.items():
     if'fail'innode_info['flags']:
        failed_nodes.append({
         'node_id': node_id,
         'address':f"{node_info['host']}:{node_info['port']}",
         'slots': node_info.get('slots', []),
         'role':'master'if'master'innode_info['flags']else'slave'
        })
   
   returnfailed_nodes
 
 defautomatic_failover(self, failed_master):
   """自動故障轉移"""
   # 查找該主節點的從節點
    slaves =self.find_slaves_for_master(failed_master['node_id'])
   
   ifnotslaves:
     print(f"警告:主節點{failed_master['address']}沒有可用的從節點!")
     returnFalse
   
   # 選擇最合適的從節點
    best_slave =self.select_best_slave(slaves)
   
   # 執行故障轉移
   try:
     self.rc.cluster_failover(best_slave['node_id'])
     print(f"故障轉移成功:{best_slave['address']}已提升為主節點")
     returnTrue
   exceptExceptionase:
     print(f"故障轉移失敗:{e}")
     returnFalse
 
 defmanual_failover(self, target_node):
   """手動故障轉移"""
   # 強制故障轉移
   self.rc.execute_command('CLUSTER FAILOVER FORCE', target=target_node)

場景2:網絡分區處理

# 網絡分區檢測和恢復
classNetworkPartitionHandler:
 def__init__(self):
   self.partition_detected =False
   self.partition_start_time =None
   
 defdetect_partition(self):
   """檢測網絡分區"""
   ifself.mode =='sentinel':
     # Sentinel模式:檢查是否有多個節點聲稱自己是主節點
      masters =self.find_all_masters()
     iflen(masters) >1:
       self.partition_detected =True
       self.partition_start_time = time.time()
       returnTrue
       
   else: # Cluster模式
     # 檢查集群是否處于fail狀態
      cluster_info =self.rc.cluster_info()
     ifcluster_info['cluster_state'] =='fail':
       self.partition_detected =True
       self.partition_start_time = time.time()
       returnTrue
   
   returnFalse
 
 defresolve_partition(self):
   """解決網絡分區"""
   ifself.mode =='
    ```python
  def resolve_partition(self):
    """解決網絡分區"""
    if self.mode == 'sentinel':
      # Sentinel模式:強制重新選舉
      self.force_reelection()
     
    else: # Cluster模式
      # 等待集群自動恢復或手動修復
      if not self.wait_for_cluster_recovery():
        self.manual_cluster_repair()
 
  def force_reelection(self):
    """Sentinel模式:強制重新選舉"""
    # 重置所有Sentinel的紀元
    sentinels = [('192.168.1.20', 26379),
          ('192.168.1.21', 26379),
          ('192.168.1.22', 26379)]
   
    for host, port in sentinels:
      r = redis.Redis(host=host, port=port)
      r.sentinel_reset('mymaster')
   
    # 等待重新選舉完成
    time.sleep(5)
   
    # 驗證新主節點
    sentinel = Sentinel(sentinels)
    master = sentinel.discover_master('mymaster')
    print(f"新主節點: {master}")
 
  def manual_cluster_repair(self):
    """Cluster模式:手動修復集群"""
    # 修復丟失的槽位
    missing_slots = self.find_missing_slots()
    for slot in missing_slots:
      # 將槽位分配給可用節點
      available_node = self.find_available_node()
      self.rc.cluster_addslots(available_node, slot)
   
    # 修復節點關系
    self.fix_node_relationships()

四、擴展性分析:應對業務增長

4.1 水平擴展能力對比

Sentinel模式的擴展限制:

# Sentinel擴展性分析
classSentinelScalabilityAnalysis:
 def__init__(self):
   self.max_memory_per_instance =64# GB
   self.max_connections_per_instance =10000
   self.max_ops_per_instance =100000# QPS
   
 defcalculate_scaling_limits(self, data_size, qps_requirement):
   """計算Sentinel模式的擴展限制"""
   # 垂直擴展分析
   ifdata_size <=?self.max_memory_per_instance:
? ? ? ? ? ??print(f"單實例可滿足:數據量?{data_size}GB")
? ? ? ? ? ? scaling_strategy =?"vertical"
? ? ? ??else:
? ? ? ? ? ??print(f"需要數據分片:數據量?{data_size}GB 超過單實例限制")
? ? ? ? ? ? scaling_strategy =?"sharding_required"
? ? ? ??
? ? ? ??# QPS擴展分析
? ? ? ??if?qps_requirement <=?self.max_ops_per_instance:
? ? ? ? ? ??print(f"單主節點可滿足:{qps_requirement}?QPS")
? ? ? ??else:
? ? ? ? ? ? read_slaves_needed = qps_requirement //?self.max_ops_per_instance
? ? ? ? ? ??print(f"需要?{read_slaves_needed}?個從節點分擔讀負載")
? ? ? ??
? ? ? ??return?{
? ? ? ? ? ??'scaling_strategy': scaling_strategy,
? ? ? ? ? ??'bottlenecks': [
? ? ? ? ? ? ? ??'單主節點寫入瓶頸',
? ? ? ? ? ? ? ??'內存容量限制',
? ? ? ? ? ? ? ??'主從復制延遲'
? ? ? ? ? ? ]
? ? ? ? }
? ??
? ??def?implement_read_write_splitting(self):
? ? ? ??"""實現讀寫分離"""
? ? ? ??class?ReadWriteSplitter:
? ? ? ? ? ??def?__init__(self):
? ? ? ? ? ? ? ??self.sentinel = Sentinel([('localhost',?26379)])
? ? ? ? ? ? ? ??self.master =?self.sentinel.master_for('mymaster')
? ? ? ? ? ? ? ??self.slaves =?self.sentinel.slave_for('mymaster')
? ? ? ? ? ? ? ??
? ? ? ? ? ??def?execute(self, command, *args, **kwargs):
? ? ? ? ? ? ? ??# 寫操作路由到主節點
? ? ? ? ? ? ? ??if?command.upper()?in?['SET',?'DEL',?'INCR',?'LPUSH',?'ZADD']:
? ? ? ? ? ? ? ? ? ??return?self.master.execute_command(command, *args, **kwargs)
? ? ? ? ? ? ? ??# 讀操作路由到從節點
? ? ? ? ? ? ? ??else:
? ? ? ? ? ? ? ? ? ??return?self.slaves.execute_command(command, *args, **kwargs)

Cluster模式的彈性擴展:

# Cluster動態擴容實現
classClusterDynamicScaling:
 def__init__(self, cluster_nodes):
   self.rc = RedisCluster(startup_nodes=cluster_nodes)
   
 defadd_node_to_cluster(self, new_node_host, new_node_port):
   """添加新節點到集群"""
   # 步驟1:啟動新節點
   self.start_new_node(new_node_host, new_node_port)
   
   # 步驟2:將節點加入集群
    existing_node =self.get_any_master_node()
   self.rc.cluster_meet(new_node_host, new_node_port)
   
   # 步驟3:等待握手完成
    time.sleep(2)
   
   # 步驟4:分配槽位
   self.rebalance_slots(new_node_host, new_node_port)
   
   returnTrue
 
 defrebalance_slots(self, new_node_host, new_node_port):
   """重新平衡槽位分配"""
   # 計算每個節點應該擁有的槽位數
    all_masters =self.get_all_master_nodes()
    total_slots =16384
    slots_per_node = total_slots //len(all_masters)
   
   # 從其他節點遷移槽位到新節點
    new_node_id =self.get_node_id(new_node_host, new_node_port)
    migrated_slots =0
   
   formasterinall_masters[:-1]: # 排除新節點
     ifmaster['slots'] > slots_per_node:
       # 計算需要遷移的槽位數
        slots_to_migrate = master['slots'] - slots_per_node
       
       # 執行槽位遷移
       self.migrate_slots(
          source_node=master['id'],
          target_node=new_node_id,
          slot_count=slots_to_migrate
        )
       
        migrated_slots += slots_to_migrate
       
       ifmigrated_slots >= slots_per_node:
         break
 
 defmigrate_slots(self, source_node, target_node, slot_count):
   """執行槽位遷移"""
   # 獲取源節點的槽位列表
    source_slots =self.get_node_slots(source_node)
    slots_to_migrate = source_slots[:slot_count]
   
   forslotinslots_to_migrate:
     # 步驟1:目標節點準備導入槽位
     self.rc.cluster_setslot_importing(target_node, slot, source_node)
     
     # 步驟2:源節點準備導出槽位
     self.rc.cluster_setslot_migrating(source_node, slot, target_node)
     
     # 步驟3:遷移槽位中的所有key
      keys =self.rc.cluster_getkeysinslot(slot,1000)
     forkeyinkeys:
       self.rc.migrate(target_node, key)
     
     # 步驟4:更新槽位歸屬
     self.rc.cluster_setslot_node(slot, target_node)
   
   print(f"成功遷移{slot_count}個槽位從{source_node}到{target_node}")

4.2 容量規劃實戰

# 容量規劃計算器
classCapacityPlanner:
 def__init__(self):
   self.data_growth_rate =0.2# 20%月增長
   self.peak_multiplier =3# 峰值是平均值的3倍
   
 defplan_for_sentinel(self, current_data_gb, current_qps, months=12):
   """Sentinel模式容量規劃"""
    projections = []
   
   formonthinrange(1, months +1):
     # 計算數據增長
      data_size = current_data_gb * (1+self.data_growth_rate) ** month
      qps = current_qps * (1+self.data_growth_rate) ** month
      peak_qps = qps *self.peak_multiplier
     
     # 計算所需資源
      memory_needed = data_size *1.5# 留50%余量
     
     # 判斷是否需要分片
     ifmemory_needed >64: # 單實例64GB限制
        shards_needed =int(memory_needed /64) +1
        strategy =f"需要{shards_needed}個分片"
     else:
        strategy ="單實例即可"
     
      projections.append({
       'month': month,
       'data_size_gb':round(data_size,2),
       'avg_qps':round(qps),
       'peak_qps':round(peak_qps),
       'memory_needed_gb':round(memory_needed,2),
       'strategy': strategy
      })
   
   returnprojections
 
 defplan_for_cluster(self, current_data_gb, current_qps, months=12):
   """Cluster模式容量規劃"""
    projections = []
    current_nodes =3# 初始3個主節點
   
   formonthinrange(1, months +1):
     # 計算數據增長
      data_size = current_data_gb * (1+self.data_growth_rate) ** month
      qps = current_qps * (1+self.data_growth_rate) ** month
      peak_qps = qps *self.peak_multiplier
     
     # 計算所需節點數
      nodes_for_memory =int(data_size /32) +1# 每節點32GB
      nodes_for_qps =int(peak_qps /50000) +1# 每節點5萬QPS
      nodes_needed =max(nodes_for_memory, nodes_for_qps,3) # 至少3個
     
     # 計算擴容操作
     ifnodes_needed > current_nodes:
        expansion_needed = nodes_needed - current_nodes
        expansion_action =f"添加{expansion_needed}個節點"
        current_nodes = nodes_needed
     else:
        expansion_action ="無需擴容"
     
      projections.append({
       'month': month,
       'data_size_gb':round(data_size,2),
       'avg_qps':round(qps),
       'peak_qps':round(peak_qps),
       'nodes_needed': nodes_needed,
       'action': expansion_action
      })
   
   returnprojections

五、高可用對比:真實故障場景

5.1 故障恢復時間(RTO)對比

# 故障恢復時間測試
classRTOBenchmark:
 def__init__(self):
   self.test_results = {
     'sentinel': {},
     'cluster': {}
    }
 
 deftest_master_failure_rto(self):
   """測試主節點故障的恢復時間"""
   
   # Sentinel模式測試
   print("測試Sentinel模式主節點故障恢復...")
   
   # 1. 記錄故障前狀態
    start_time = time.time()
   
   # 2. 模擬主節點故障
    os.system("kill -9 $(pidof redis-server | awk '{print $1}')")
   
   # 3. 等待故障檢測和轉移
   whileTrue:
     try:
        sentinel = Sentinel([('localhost',26379)])
        master = sentinel.master_for('mymaster')
        master.ping()
       break
     except:
        time.sleep(0.1)
   
    sentinel_rto = time.time() - start_time
   self.test_results['sentinel']['master_failure'] = sentinel_rto
   print(f"Sentinel RTO:{sentinel_rto:.2f}秒")
   
   # Cluster模式測試
   print("
測試Cluster模式主節點故障恢復...")
   
   # 1. 記錄故障前狀態
    start_time = time.time()
   
   # 2. 模擬節點故障
    os.system("redis-cli -p 7000 DEBUG SEGFAULT")
   
   # 3. 等待故障檢測和轉移
   whileTrue:
     try:
        rc = RedisCluster(startup_nodes=[{"host":"127.0.0.1","port":"7001"}])
        rc.ping()
        cluster_info = rc.cluster_info()
       ifcluster_info['cluster_state'] =='ok':
         break
     except:
        time.sleep(0.1)
   
    cluster_rto = time.time() - start_time
   self.test_results['cluster']['master_failure'] = cluster_rto
   print(f"Cluster RTO:{cluster_rto:.2f}秒")
   
   returnself.test_results

5.2 數據一致性保證

# 數據一致性測試
classConsistencyTest:
 def__init__(self):
   self.inconsistency_count =0
   
 deftest_write_consistency_during_failover(self):
   """測試故障轉移期間的寫入一致性"""
   
   # 啟動寫入線程
    write_thread = threading.Thread(target=self.continuous_write)
    write_thread.start()
   
   # 等待一段時間后觸發故障
    time.sleep(5)
   self.trigger_failover()
   
   # 繼續寫入并檢查一致性
    time.sleep(10)
   self.stop_writing =True
    write_thread.join()
   
   # 驗證數據一致性
   self.verify_data_consistency()
   
 defcontinuous_write(self):
   """持續寫入數據"""
   self.written_data = {}
   self.stop_writing =False
    counter =0
   
   whilenotself.stop_writing:
     try:
        key =f"test_key_{counter}"
        value =f"test_value_{counter}_{time.time()}"
       
       # 寫入數據
       ifself.mode =='sentinel':
          sentinel = Sentinel([('localhost',26379)])
          master = sentinel.master_for('mymaster')
          master.set(key, value)
       else:
          rc = RedisCluster(startup_nodes=[{"host":"127.0.0.1","port":"7000"}])
          rc.set(key, value)
       
       self.written_data[key] = value
        counter +=1
        time.sleep(0.01) # 100次/秒
       
     exceptExceptionase:
       print(f"寫入失敗:{e}")
        time.sleep(1)
 
 defverify_data_consistency(self):
   """驗證數據一致性"""
   print(f"驗證{len(self.written_data)}條數據的一致性...")
   
   forkey, expected_valueinself.written_data.items():
     try:
       ifself.mode =='sentinel':
          sentinel = Sentinel([('localhost',26379)])
          master = sentinel.master_for('mymaster')
          actual_value = master.get(key)
       else:
          rc = RedisCluster(startup_nodes=[{"host":"127.0.0.1","port":"7000"}])
          actual_value = rc.get(key)
       
       ifactual_value != expected_value:
         self.inconsistency_count +=1
         print(f"數據不一致:{key}")
         
     exceptExceptionase:
       print(f"讀取失敗:{key}, 錯誤:{e}")
       self.inconsistency_count +=1
   
    consistency_rate = (1-self.inconsistency_count /len(self.written_data)) *100
   print(f"數據一致性:{consistency_rate:.2f}%")
   print(f"不一致數據:{self.inconsistency_count}/{len(self.written_data)}")

六、實戰案例:如何選擇最適合的方案

6.1 典型場景分析

# 場景決策樹
classScenarioAnalyzer:
 defanalyze_requirements(self, requirements):
   """根據需求分析推薦方案"""
    score_sentinel =0
    score_cluster =0
    recommendations = []
   
   # 數據量評估
   ifrequirements['data_size_gb'] =99.99:
      score_cluster +=1
      recommendations.append("超高可用性要求,Cluster故障域更小")
   
   # 最終推薦
   ifscore_sentinel > score_cluster:
      final_recommendation ="Sentinel"
   else:
      final_recommendation ="Cluster"
   
   return{
     'recommendation': final_recommendation,
     'sentinel_score': score_sentinel,
     'cluster_score': score_cluster,
     'reasons': recommendations
    }

6.2 遷移方案設計

# Sentinel到Cluster遷移方案
classMigrationPlan:
 def__init__(self):
   self.migration_steps = []
   
 defcreate_migration_plan(self, source_type='sentinel', target_type='cluster'):
   """創建遷移計劃"""
   
   ifsource_type =='sentinel'andtarget_type =='cluster':
     returnself.sentinel_to_cluster_migration()
   
 defsentinel_to_cluster_migration(self):
   """Sentinel到Cluster的遷移步驟"""
   
    steps = [
      {
       'phase':1,
       'name':'準備階段',
       'duration':'1-2天',
       'tasks': [
         '搭建Cluster測試環境',
         '性能基準測試',
         '應用兼容性測試',
         '制定回滾方案'
        ],
       'script':self.prepare_cluster_env
      },
      {
       'phase':2,
       'name':'數據同步階段',
       'duration':'2-3天',
       'tasks': [
         '全量數據導出',
         '數據導入Cluster',
         '建立增量同步',
         '數據一致性校驗'
        ],
       'script':self.sync_data
      },
      {
       'phase':3,
       'name':'灰度切換階段',
       'duration':'3-5天',
       'tasks': [
         '1%流量切換',
         '10%流量切換',
         '50%流量切換',
         '監控和調優'
        ],
       'script':self.gradual_switch
      },
      {
       'phase':4,
       'name':'全量切換階段',
       'duration':'1天',
       'tasks': [
         '100%流量切換',
         '舊集群保持待命',
         '觀察24小時',
         '確認切換成功'
        ],
       'script':self.full_switch
      }
    ]
   
   returnsteps
 
 defsync_data(self):
   """數據同步腳本"""
   # 使用redis-shake進行數據同步
    sync_config ="""
    # redis-shake配置
    source.type = standalone
    source.address = 192.168.1.10:6379
    source.password = yourpassword
   
    target.type = cluster
    target.address = 192.168.1.30:7000;192.168.1.31:7001;192.168.1.32:7002
    target.password = yourpassword
   
    # 同步配置
    sync.mode = rump # 全量同步
    sync.parallel = 32
    sync.data_filter = true
   
    # 增量同步
    sync.mode = sync # 切換到增量同步模式
    """
   
   # 執行同步
    os.system(f"redis-shake -conf redis-shake.conf")

七、性能優化最佳實踐

7.1 Sentinel性能優化

# Sentinel優化配置生成器
classSentinelOptimizer:
 defgenerate_optimized_config(self, scenario):
   """根據場景生成優化配置"""
   
    config = {
     'redis_master': {},
     'redis_slave': {},
     'sentinel': {}
    }
   
   ifscenario =='high_write':
     # 高寫入場景優化
      config['redis_master'] = {
       'maxmemory-policy':'allkeys-lru',
       'save':'', # 關閉RDB
       'appendonly':'no', # 關閉AOF
       'tcp-backlog':511,
       'tcp-keepalive':60,
       'timeout':0,
       'hz':100, # 提高后臺任務頻率
       'repl-backlog-size':'256mb',
       'client-output-buffer-limit':'slave 256mb 64mb 60'
      }
     
   elifscenario =='high_read':
     # 高讀取場景優化
      config['redis_slave'] = {
       'slave-read-only':'yes',
       'maxmemory-policy':'volatile-lru',
       'repl-diskless-sync':'yes',
       'repl-diskless-sync-delay':5,
       'slave-priority':100,
       'lazyfree-lazy-eviction':'yes',
       'lazyfree-lazy-expire':'yes'
      }
     
   # Sentinel通用優化
    config['sentinel'] = {
     'sentinel_down_after_milliseconds':5000, # 快速故障檢測
     'sentinel_parallel_syncs':2, # 并行同步
     'sentinel_failover_timeout':60000, # 故障轉移超時
     'sentinel_deny_scripts_reconfig':'yes'# 安全配置
    }
   
   returnconfig

7.2 Cluster性能優化

# Cluster優化工具
classClusterOptimizer:
 defoptimize_cluster_performance(self):
   """Cluster性能優化"""
   
    optimizations = {
     'network':self.optimize_network(),
     'memory':self.optimize_memory(),
     'cpu':self.optimize_cpu(),
     'persistence':self.optimize_persistence()
    }
   
   returnoptimizations
 
 defoptimize_network(self):
   """網絡優化"""
   return{
     'cluster-node-timeout':5000, # 降低超時時間
     'cluster-replica-validity-factor':0, # 從節點永不過期
     'cluster-migration-barrier':1, # 遷移屏障
     'cluster-require-full-coverage':'no', # 部分覆蓋也可用
     'tcp-backlog':511,
     'tcp-keepalive':60
    }
 
 defoptimize_memory(self):
   """內存優化"""
   return{
     'maxmemory-policy':'volatile-lru',
     'lazyfree-lazy-eviction':'yes',
     'lazyfree-lazy-expire':'yes',
     'lazyfree-lazy-server-del':'yes',
     'activerehashing':'yes',
     'hz':100
    }

八、總結:決策清單與行動指南

8.1 快速決策清單

基于本文的深入分析,我整理了一份快速決策清單:

選擇Sentinel的場景:

? 數據量 < 64GB

? QPS < 10萬

? 需要事務支持

? 大量使用Lua腳本

? 業務邏輯依賴多key操作

? 運維團隊規模較小

? 對延遲極度敏感

選擇Cluster的場景:

? 數據量 > 64GB

? QPS > 10萬

? 需要水平擴展能力

? 可以改造應用避免跨槽位操作

? 有專業的運維團隊

? 追求更高的可用性

8.2 實施路線圖

# 生成個性化實施方案
defgenerate_implementation_roadmap(current_state, target_state):
 """生成實施路線圖"""
 
  roadmap = {
   'week_1': [
     '技術評審和方案確認',
     '測試環境搭建',
     '性能基準測試'
    ],
   'week_2': [
     '應用改造(如需要)',
     '監控系統部署',
     '自動化腳本開發'
    ],
   'week_3': [
     '生產環境部署',
     '數據遷移',
     '灰度切換'
    ],
   'week_4': [
     '性能優化',
     '穩定性觀察',
     '文檔完善'
    ]
  }
 
 returnroadmap

結語

選擇Redis集群方案不是非黑即白的決定,而是需要基于業務特點、團隊能力、發展預期等多個維度綜合考慮。通過本文的詳細對比和實戰案例,相信你已經對Sentinel和Cluster有了深入的理解。

記住,沒有最好的架構,只有最適合的架構。在做出選擇之前,請務必:

1.充分測試:在你的實際業務場景下進行壓測

2.漸進式遷移:不要一次性切換,采用灰度方案

3.監控先行:完善的監控是穩定運行的基礎

4.預留余地:為未來的增長預留足夠的空間

最后,如果你覺得這篇文章對你有幫助,歡迎關注我的博客,我會持續分享更多生產環境的實戰經驗。下一篇文章,我會深入講解《Redis故障診斷與性能調優實戰》,敬請期待!

作者簡介:10年運維老兵,曾負責多個千萬級用戶系統的Redis架構設計與優化,踩過的坑希望你不要再踩。

本文所有代碼示例均已在生產環境驗證,可直接使用。如有問題,歡迎在評論區交流討論。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 集群
    +關注

    關注

    0

    文章

    142

    瀏覽量

    17661
  • Redis
    +關注

    關注

    0

    文章

    392

    瀏覽量

    12185

原文標題:Redis集群模式選擇:Sentinel vs Cluster深度對比實戰指南

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    如何使用Rust連接Redis

    Rust操作RedisRedis依賴庫 在Rust中有很多Redis的客戶端庫可以選擇,這里我們選擇使用
    的頭像 發表于 09-19 16:22 ?3578次閱讀

    Redis-cluster在線集群安裝

    Redis-cluster之在線搭建詳解
    發表于 06-06 14:52

    3分鐘搭建Redis Cluster集群

    Redis Cluster集群快速搭建
    發表于 06-12 14:58

    java原生程序redis連接怎么選擇

    java原生程序redis連接(連接池長連接和短連接)選擇問題
    發表于 06-10 16:33

    Redis Cluster的基本原理及實現細節

    Redis Cluster的基本原理和架構 Redis Cluster是分布式Redis的實現。隨著Re
    發表于 09-28 19:09 ?0次下載
    <b class='flag-5'>Redis</b> <b class='flag-5'>Cluster</b>的基本原理及實現細節

    Redis的四種模式復制、哨兵、Cluster以及集群模式

    概述 Redis作為緩存的高效中間件,在我們日常的開發中被頻繁的使用,今天就來說一說Redis的四種模式,分別是「單機版、主從復制、哨兵、以及集群模式」。 可能,在一般公司的程序員使用
    的頭像 發表于 09-30 17:51 ?3244次閱讀
    <b class='flag-5'>Redis</b>的四種<b class='flag-5'>模式</b>復制、哨兵、<b class='flag-5'>Cluster</b>以及集群<b class='flag-5'>模式</b>

    單機redis和redisCluster集群是如何獲取所有key的

    redis-cli -c -a [CLUSTER_AUTH] --cluster call [CLUSTER_IP:CLUSTER_POPR
    的頭像 發表于 10-11 10:43 ?2361次閱讀
    單機<b class='flag-5'>redis</b>和redisCluster集群是如何獲取所有key的

    Redis的主從、哨兵、Redis Cluster集群

    ? 前言 今天跟小伙伴們一起學習Redis的主從、哨兵、Redis Cluster集群。 Redis主從 Redis哨兵
    的頭像 發表于 06-12 14:58 ?1648次閱讀
    <b class='flag-5'>Redis</b>的主從、哨兵、<b class='flag-5'>Redis</b> <b class='flag-5'>Cluster</b>集群

    Redis為何選擇單線程

    Redis為何選擇單線程? 在Redisv6.0以前,Redis的核心網絡模型選擇用單線程來實現。 核心意思就是,對于一個 DB 來說,CPU 通常不會是瓶頸,因為大多數請求不會是 C
    的頭像 發表于 10-09 10:59 ?975次閱讀

    什么是Redis主從復制

    Master節點的能力,主掛了服務就不可以寫數據了。僅僅就是增強了應用讀數據的并發量同時做數據備份。 一般生產環境會采用 哨兵 或者 Redis Cluster 這種具備Master自動選舉的方案,我們學習時還是要掌握主從的原理后,再去更深一步,對于哨兵和
    的頭像 發表于 10-09 15:09 ?1039次閱讀
    什么是<b class='flag-5'>Redis</b>主從復制

    Cloud MemoryStore for Redis Cluster 正式發布

    以下文章來源于谷歌云服務,作者 Google Cloud 自從我們推出 Memorystore for Redis Cluster 預覽版以來,銀行、零售、廣告、制造和社交媒體等各個行業的客戶都利用
    的頭像 發表于 11-24 17:40 ?1025次閱讀
    Cloud MemoryStore for <b class='flag-5'>Redis</b> <b class='flag-5'>Cluster</b> 正式發布

    redis查看集群狀態命令

    Redis 集群管理時,了解集群的狀態是非常重要的,可以通過一些命令來獲取集群的狀態信息。本文將詳細介紹 Redis 查看集群狀態的命令,幫助讀者完全了解其使用方式和相關參數。 CLUSTER INFO 命令
    的頭像 發表于 12-04 11:39 ?2799次閱讀

    redis的淘汰策略

    的寫入。 Redis的淘汰策略主要有以下幾種: LRU(Least Recently Used,最近最少使用): 這是Redis默認的淘汰策略。當內存空間不足時,Redis選擇最近最
    的頭像 發表于 12-04 16:23 ?1182次閱讀

    Redis Cluster之故障轉移

    1. Redis Cluster 簡介 Redis ClusterRedis 官方提供的 Redi
    的頭像 發表于 01-20 09:21 ?1415次閱讀
    <b class='flag-5'>Redis</b> <b class='flag-5'>Cluster</b>之故障轉移

    Redis哨兵模式的自動故障檢測與主從切換實戰

    Redis 主從復制解決了讀擴展和數據冗余問題,但主節點故障時需要人工介入切換,這在生產環境中是不可接受的。Sentinel(哨兵)模式在主從架構之上增加了自動故障檢測和故障轉移能力,是 Re
    的頭像 發表于 02-27 11:05 ?122次閱讀