Redis高可用

1、reids集羣

一、擴容集羣

準備新節點 =》 加入集羣 =》 遷移槽和數據
新節點:前端

  • 集羣模式
  • 配置和其餘節點統一
  • 孤立節點

加入集羣做用node

  • 爲它遷移槽和數據實現擴容
  • 做爲從節點負責故障轉移
    建議使用redis-trib.rb可以避免新節點加入其餘集羣,形成故障
    遷移槽和數據
  • 槽遷移計劃
  • 遷移數據
  • 對目標節點發送
  • 添加從節點

步驟redis

  1. 目標節點準備導入槽
  2. 源節點準備導出槽
  3. 獲取slot下count個鍵
  4. 批量遷移相關鍵的數據
  5. 循環遷移鍵
redis-cli -p 7000 cluster meet 127.0.0.1 7006
redis-trib.rb reshard 127.0.0.1 7000
二、收縮擴容

下線遷移槽
忘記節點:cluster forget downNodeId
關閉節點算法

redis-trib.rb reshard --from nodeId --to nodeId --slots 1366 127.0.0.1:7000
redis-trib.rb del-node 127.0.0.1:7000 nodeIdsql

三、客戶端路由

moved重定向數據庫

  • 發送鍵命令
  • 計算槽和對應節點
  • 回覆moved
  • 重定向發送命令

槽命中:直接返回
槽命不中:moved異常
ask重定向後端

  • 發送鍵命令
  • 回覆ask轉向
  • asking
  • 發送命令
  • 響應結果

moved和ask:二者都是客戶端重定向,moved槽已經肯定遷移,ask槽還在遷移中
smart客戶端緩存

  • 從集羣中選一個可運行節點,使用cluster slots初始化槽和節點映射
  • 將cluster slots的結果映射到本地,爲每一個節點建立JedisPool
  • 準備執行命令

批量優化的方法:
串行mget,串行IO,並行IO,hash_tag服務器

四、故障轉移

故障發現:
經過ping/pong消息實現故障發現,不須要sentinel
主觀下線和客觀下線網絡

主觀下線:某個節點認爲另外一個節點不可用,偏見
客觀下線:當半數以上持有槽的主節點都標記某節點主觀下線

故障恢復:

資格檢查

  • 每一個節點檢查與故障主節點的斷線時間
  • 超過cluster-node-timeout * cluster-slave-validity-factor取消資格
  • cluster-slave-validity-factor:默認是10

準備選舉時間

選舉投票

替換主節點

  • 當前從節點取消複製爲主節點
  • 執行clusterDelSlot撤銷故障主節點負責的槽,並執行clusterAddSlot把這些槽分配給本身
  • 向集羣廣播本身的pong消息,代表已經替換了故障從節點
五、集羣完整性

cluster-require-full-coverage默認爲yes

  • 集羣中16384個槽所有可用:保證集羣完整性
  • 節點故障或者正在故障轉移

大多業務沒法容忍,cluster-require-full-coverage建議設置爲no

帶寬消耗

  • 官方建議: 1000個節點
  • PING/PONG消息
  • 不容忽視的帶寬消耗

三個方面:消息發送頻率;消息數據量;節點部署的機器規模

避免大集羣:避免多業務使用一個集羣,大業務能夠多集羣
cluster-node-timeout:帶寬和故障轉移速度的均衡
儘可能均勻分配到多機器上:保證高可用和帶寬

數據傾斜

  • 節點和槽分配不均

redis-trib.rb info ip:port查看節點,槽,鍵值分佈
redis-trib.rb rebalance ip:port從新分配槽,節點,鍵值

  • 不一樣槽對應鍵值數量差別較大
  • 包含bigkey
  • 內存相關配置不一致

請求傾斜

熱點key:重要的key或者bigkey
優化:
避免bigkey
熱鍵不要使用hash_tag
當一致性不高時,可用使用本地緩存 + MQ

集羣讀寫分離

只讀鏈接:集羣模式的從節點不接受任何讀寫請求

  • 重定向到負責槽的主節點
  • readonly命令能夠讀 鏈接級別的命令

讀寫分離:更加複雜

  • 一樣的問題:複製延遲 讀取過時數據 從節點故障
  • 修改客戶端:cluster slaves nodeId

數據遷移
官方遷移工具:redis-trib.rb import
只能從單機遷移到集羣
不支持在線遷移:source須要停寫
不支持斷點續傳
單線程遷移:影響速度

集羣和單機

集羣限制
key批量操做支持有限:mget,mset必須再一個slot
key事物和lua支持有限:操做的key必須在一個節點
key時數據分區的最小粒度:不支持bigkey分區
不支持多個數據庫:集羣模式下只有一個db 0
複製只支持一層:不支持樹形複製結構

2、reids緩存成本和收益

一、緩存的受益和成本

受益:

  • 加速讀寫

經過緩存加速讀寫速度

  • 下降後端負載

後端服務器經過前端緩存下降負載,業務端使用Redis下降後端Mysql負載

成本:

  • 數據不一致:

緩存從和數據層有時間窗口不一致,和更新策略有關

  • 代碼維護成本

多了一層緩存邏輯

  • 運維成本

使用場景

  • 下降後端負載

對高消耗的SQL=>join結果集/分組統計結果緩存

  • 加速請求響應

利英Redis/Memcache優化IO響應時間

  • 大量寫合併爲批量寫

如計數器先Redis累加再批量寫DB

二、緩存更新策略
  • LRU/LFU/FIFO算法剔除
  • 超時剔除
  • 主動更新:開發控制生命週期
建議
低一致性:最大內存和淘汰策略
高一致性 超時剔除和主動更新結合,最大內存和淘汰策略兜底
三、緩存粒度控制
  • 通用性:全量屬性更好
  • 佔用空間:部分屬性更好
  • 代碼維護:表面上全量屬性更好
四、緩存穿透問題

大量請求不命中
緣由:

  • 業務代碼自身問題
  • 惡意攻擊,爬蟲等等

發現:

  • 業務的響應時間
  • 業務自己問題
  • 相關指標 總調用數 緩存層命中數 存儲層命中數

解決方案:

  • 緩存空對象

    兩個問題:
    須要更多的鍵
    緩存層和存儲層數據短時間不一致

  • 布隆過濾器攔截
五、緩存雪崩優化

因爲cache服務承載大量請求,當cache服務器異常/脫機,流量直接壓向後端組建,形成級聯故障

優化方案:
保證緩存高可用性

  • 個別節點,個別機器,甚至是機房
  • 依賴隔離組件爲後端限流
  • 提早演練:例如壓力測試
六、無底洞優化

優化IO的幾種方法

  • 命令自己優化:例如慢查詢keys hgetall bigkey
  • 減小網絡通訊次數
  • 下降接入成本:例如客戶端長鏈接/鏈接池 NIO等
  • 串行mget 串行IO 並行IO hash_tag
七、熱點key的重建優化

三個目標

  • 減小重緩存的次數
  • 數據儘量一致
  • 減小潛在危險

    兩個解決

  • 互斥鎖
  • 永遠不過時

緩存層面:沒有設置過時時間
功能層面:爲每一個value添加邏輯過時時間,但發現超過邏輯過時時間後,會使用單獨的線程去構建緩存

緩存收益:加速讀寫,下降後端存儲負載緩存成本 緩存和存儲數據不一致性 代碼維護成本 運維成本推薦結合剔除、超時、主動更新三種方案共同完成穿透問題:使用緩存空對象和布隆過濾器來解決,注意他們各自的使用場景和侷限性無底洞問題:分佈式緩存中,有更多的機器不保證有更高的性能雪崩問題:緩存層高可用,客戶端降級 提早演練熱點key問題 互斥鎖 永遠不過時 可以子啊必定程度上解決熱點key的問題

相關文章
相關標籤/搜索