Redis筆記(四)初識Redis Cluster & 深入Redis Cluster & 緩存設計與優化

初識Redis Cluster & 深入Redis Cluster & 緩存設計與優化

在這裏插入圖片描述
實驗部分對應 Redis筆記(四)實驗部分:redisCluster的原生安裝與官方工具安裝

第9章 初識Redis Cluster

Redis Cluster是Redis 3提供的分佈式解決方案,有效解決了Redis分佈式方面的需求,同時它也是學習分佈式存儲的絕佳案例。本章將針對Redis Cluster的數據分佈,搭建集羣進行分析說明。

9-1 本章目錄

  1. 呼喚集羣
  2. 數據分佈
  3. 搭建集羣
  4. 集羣伸縮
  5. 客戶端路由
  6. 集羣原理
  7. 開發運維常見問題

9-2 呼喚集羣

爲什麼呼喚

  1. 併發量
    在這裏插入圖片描述

  2. 數據量
    在這裏插入圖片描述

  3. 網絡流量

“解決方法"
配置“強悍”的機器:超大內存、牛xCPU等

正確的解決方法
分佈式:簡單的認爲加機器

9-3 數據分佈概論

在這裏插入圖片描述

兩種分區方式

在這裏插入圖片描述
兩種數據分佈對比
在這裏插入圖片描述

9-4 節點取餘分區

在這裏插入圖片描述

擴容

若添加一個節點在下面途中會有8成的遷移量
在這裏插入圖片描述
但如果採用翻倍擴容(比如下面 的六個 需要遷移的數據量將大大降低)
在這裏插入圖片描述

優缺點

優點: 客戶端分片,使用 哈希+取餘較爲簡單
缺點:節點伸縮時數據節點關係變化,會導致數據遷移,而遷移數量和添加節點數量有關所以建議翻倍擴容

9-5 一致性哈希分區

一個tocken環的長度設爲 0~2的32次方,放置四個節點,新添加的key則會順勢針的找到最近的node
在這裏插入圖片描述

擴容

若添加n5 則變動的數據僅爲n1和n2之間的 ,需要變動(回寫)的數據就會減少
在這裏插入圖片描述

優缺點

優點
客戶端分片:哈希+順時針(優化取餘)
節點伸縮:隻影響鄰近節點,但是還是有數據遷移
缺點
添加n5後,會使除 n2 n5外的節點的數據量相對更大 因此建議使用翻倍伸縮,保證最小遷移數據和負載均衡

9-6 虛擬槽哈希分佈

  1. 預設虛擬槽:每個槽映射一個數據子集,一般比節點數大
  2. 良好的哈希函數:例如CRC16
  3. 服務端管理節點、槽、數據:例如Redis Cluster
    在這裏插入圖片描述

9-7 基本架構

分佈式架構中每個節點都會負責讀和寫 並且彼此能夠相互通信
在這裏插入圖片描述
Redis Cluster架構

  1. 節點
# 節點集羣模式啓動該節點
cluster-enabled:yes
  1. meet 幾點之前要達到互通
    在這裏插入圖片描述

  2. 指派槽
    在這裏插入圖片描述

  3. 複製

9-8 原生安裝

#準備節點
節點握手
分配槽
分配主從

9-9 工具安裝

第10章 深入Redis Cluster

本章將針對Redis Cluster的集羣伸縮,請求路由,故障轉移等方面進行分析說明。

10-1 集羣伸縮目錄

主要分爲三個部分 集羣的擴容與縮容及其伸縮的原理

10-2 集羣伸縮原理

下圖代表節點的加入與下線
在這裏插入圖片描述
下圖是一個“伸”的過程,即將節點加入6385加入集羣,該過程需要meet操作 和槽的分配。
在這裏插入圖片描述
其實集羣伸縮就等於是槽和數據在節點之間的移動

10-3 集羣的擴展

10-3-1 擴展集羣-1.加入節點

準備新節點

新節點:

  • 集羣模式
  • 配置和其他節點統一·啓動後是孤兒節點。
redis-server conf/redis-6385.conf
redis-server conf/redis-6386.conf

啓動兩個孤立節點之後集羣結構如下:

在這裏插入圖片描述

加入集羣
127.0.0.1:6379>cluster meet 127.0.0.1 6385
127.0.0.1:6379>cluster meet 127.0.0.1 6386

加入之後如下
在這裏插入圖片描述
加入集羣有兩個作用

  • 爲它遷移槽和數據實現擴容
  • 作爲從節點負責故障轉移

當然也可以使用官方工具進行加入節點

redis-trib.rb add-node new_host:new port existing_host:existing port --slave --master-id <arg>
redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379

使用redis-trib.rb能夠避免新節點已經加入了其他集羣,造成故障。

遷移槽和數據

主要分爲三步

槽遷移計劃

分配給新節點一定的槽數:
在這裏插入圖片描述

遷移數據
  1. 對目標節點發送:cluster setslot {slot} importing {sourceNodeld}命令,讓目標節點準備導入槽的數據。
  2. 對源節點發送:cluster setslot {slot} migrating {targetNodeld}命令,讓源節點準備遷出槽的數據。
  3. 源節點循環執行cluster getkeysinslot {slot){count} 命令,每次獲取count個屬於槽的健。
  4. 在源節點上執行migrate {targetlp} {targetPort} key 0 {timeout} 命令把指定key遷移。
  5. 重複執行步驟3~4直到槽下所有的鍵數據遷移到目標節點。
  6. 向集羣內所有主節點發送cluster setslot {slot} node {targetNodeld}命令,通知槽分配給目標節點。

在這裏插入圖片描述

添加從節點

10-3-2 集羣擴容演示-1

10-3-3 集羣擴容演示-2

10-4 集羣的縮容

10-4-1 集羣縮容-說明

10-4-2 集羣縮容-操作

10-5客戶端路由

10-5-1 moved異常說明和操作

在這裏插入圖片描述
下圖是指向自身 之後槽命中的效果
在這裏插入圖片描述
槽不命中:moved異常
在這裏插入圖片描述
下面的實例演示中先 添加 -c 參數以集羣方式啓動 可以看到 鍵值爲hello是直接命中了節點 鍵值爲php時出現了moved異常 並且幫我們完成跳轉成7001客戶端。
而不使用 -c 參數時則會直接返回異常
在這裏插入圖片描述

10-5-2 ask重定向

由於槽遷移而客戶端中所保存的地址不變會造成訪問上的問題 這就有了ask重定向異常
在這裏插入圖片描述
在這裏插入圖片描述
moved和ask的比較

  1. 兩者都是客戶單重定向
  2. moved:槽已經確定遷移
  3. ask:槽還在遷移中

10-5-3 smart客戶端實現原理

smart客戶端原理主要就在於追求性能:

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

其中執行命令是smart客戶端的核心過程
JedisCluster中 存儲的是 key及其對應的槽的位置 和改槽所在的節點
若目標節點返回出錯則會隨機請求一個節點 這個過程大概率會發生 moved異常然後就會重置本地緩存 如果五次未成功則返回異常

大致流暢圖如下:
在這裏插入圖片描述

10-5-4 JedisCluster執行源碼分析

10-6 smart客戶端JedisCluster

10-6-1 JedisCluster基本使用

10-6-2 整合spring-1

10-6-3 整合spring-2

10-6-4 多節點操作命令

在這裏插入圖片描述

10-6-5 批量操作優化

批量操作怎麼實現?
mget mset必須在一個槽

四種批量優化的方法:

  1. 串行mget

在這裏插入圖片描述
2. 串行IO
其實就是對上面的改進 通過sunKeys按照所屬節點聚合分組 降低傳輸次數
在這裏插入圖片描述
3. 並行IO
使用多線程進行並行操作
在這裏插入圖片描述
4. hash_tag
使用tag進行包裝 效率更高 全部請求到一個節點上
在這裏插入圖片描述
四種方式比較
在這裏插入圖片描述

10-7 故障轉移

10-7-1 故障發現

◆通過ping/pong消息實現故障發現:不需要sentinel
◆主觀下線和客觀下線

主觀下線

定義:某個節點認爲另一個節點不可用,“偏見"
主管下線流程:
在這裏插入圖片描述
其中 pfail就代表是主管下線

客觀下線

定義:當半數以上持有槽的主節點都標記某節點主觀下線
客觀下線流程:一個主節點接收到其它節點的ping消息 並且該節點會維護每個節點及其對應的pfail信息的一個列表

在這裏插入圖片描述

嘗試客觀下線的流程
在這裏插入圖片描述
該節點的作用有兩個:

  1. 通知集羣內所有節點標記故障節
  2. 點爲客觀下線通知故障節點的從節點觸發故障
    轉移流程

10-7-2 故障恢復

故障恢復主要分爲四步:

資格檢查
  1. 每個從節點檢查與故障主節點的斷線時間。
  2. 超過cluster-node-timeout*cluster-slave-validity-factor取消資格。
  3. cluster-slave-validity-factor:默認是10
    cluster-node-timeout默認是15
    即可得知 時間超過150秒則取消資格
備選舉時間

在這裏插入圖片描述
上圖b-1節點偏移量 更大意味着丟失數據更小 所以要給予偏袒 讓其延遲一秒就參與選舉以獲得更多的票數。

選舉投票

獲得票數過半即可替換主節點
在這裏插入圖片描述

替換主節點
  1. 當前從節點取消複製變爲主節點。(slaveof no one)
  2. 執行clusterDelSlot撤銷故障主節點負責的槽,並執行clusterAddSlot把這些槽分配給自己。
  3. 向集羣廣播自己的pong消息,表明已經替換了故障從節點

10-7-3 故障模擬

10-8 Redis Cluster常見開發運維問題

10-8-1 集羣完整性

cluster-require-full-coverage默認爲yes(即所有節點和槽可用集羣才提提供服務)

  1. 集羣中16384個槽全部可用:保證集羣完整性
  2. 節點故障或者正在故障轉移:
    (error)CLUSTERDOWN The cluster is down

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

10-8-2 帶寬消耗

在這裏插入圖片描述

體現在三個方面:

  1. 消息發送頻率:節點發現與其它節點最後通信時間超過cluster-node-timeout/2時會直接發送ping消息
  2. 消息數據量:slots槽數組(2KB空間)和整個集羣1/10的狀態數據(10個節點狀態數據約1KB)
  3. 節點部署的機器規模:集羣分佈的機器越多且每臺機器劃分的節點數越均勻,則集羣內整體的可用帶寬越高。

舉例

  1. 規模:節點200個、20臺物理機(每臺10個節點)
  2. cluster-node-timeout=15000,ping/pong帶寬爲25Mb
  3. cluster-node-timeout=20000,ping/pong帶寬低於15Mb

優化

  1. 避免“大”集羣:避免多業務使用一個集羣,大業務可以多集羣。
  2. cluster-node-timeout:帶寬和故障轉移速度的均衡。
  3. 儘量均勻分配到多機器上:保證高可用和帶寬

10-8-3 Pub/Sub廣播

在這裏插入圖片描述
問題:publish在集羣每個節點廣播:加重帶寬
解決:單獨“走”一套Redis Sentinel

10-8-4 集羣傾斜-目錄

在這裏插入圖片描述

10-8-5 數據傾斜

  1. 節點和槽分配不均
redis-trib.rb info ip:port 查看節點、槽、鍵值分佈
redis-trib.rb rebalance ip:port 進行均衡(謹慎使用)
  • 不同槽對應鍵值數量差異較大
    CRC16正常情況下比較均勻。
    可能存在hash_tag ,可通過cluster countkeysinslot {slot}獲取槽對應鍵值個數

  • 包含bigkey
    bigkey:例如大字符串、幾百萬的元素的hash、set等
    可以在從節點執行:redis-cli --bigkeys查看bigkey
    優化:優化數據結構。

  • 內存相關配置不一致
    hash-max-ziplist-value、set-max-intset-entries等
    優化:定期“檢查”配置一致性

10-8-6 請求傾斜

熱點key:

  • 重要的key或者bigkey

優化:

  • 避免bigkey
  • 熱鍵不要用hash_tag
  • 當一致性不高時,可以用本地緩存+MQ

10-8-7 讀寫分離

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

  • 重定向到負責槽的主節點
  • readonly命令可以讀:連接級別命令

讀寫分離:更加複雜

  • 同樣的問題:複製延遲、讀取過期數據、從節點故障
  • 修改客戶端:cluster slaves{nodeld}

10-8-9 數據遷移

官方遷移工具:redis-trib.rb import

  • 只能從單機遷移到集羣
  • 不支持在線遷移:source需要停寫
  • 不支持斷點續傳
  • 單線程遷移:影響速度

在線遷移:

  • 唯品會redis-migrate-tool
  • 豌豆莢:redis-port

10-8-10 集羣vs單機

集羣的限制

  1. key批量操作支持有限:例如mget、mset必須在一個slot
  2. Key事務和Lua支持有限:操作的key必須在一個節點
  3. key是數據分區的最小粒度:不支持bigkey分區
  4. 不支持多個數據庫:集羣模式下只有一個db0
  5. 複製只支持一層:不支持樹形複製結構

分佈式redis不一定好用:
1.Redis Cluster:滿足容量和性能的擴展性,很多業務”不需要”。

 大多數時客戶端性能會”降低"。
 命令無法跨節點使用:mget、keys、scan、flush、sinter等。
 Lua和事務無法跨節點使用。
 客戶端維護更復雜:SDK和應用本身消耗(例如更多的連接池)。

2.很多場景Redis Sentinel已經足夠好。

第11章 緩存設計與優化

講解將緩存加入應用架構後帶來的一些問題,這些問題常常會成爲應用的致命點。

11-1 目錄

11-2 緩存的受益和成本

受益

1.加速讀寫
通過緩存加速讀寫速度:CPUL1/L2/L3 Cache、Linux page Cache加速硬盤讀寫、瀏覽器緩存、Ehcache緩存數據庫結果。
2.降低後端負載
後端服務器通過前端緩存降低負載:業務端使用Redis降低後端MySQL負載等

成本

1.數據不一致:緩存層和數據層有時間窗口不一致,和更新策略有關。
2.代碼維護成本:多了一層緩存邏輯。
3.運維成本:例如Redis Cluster

使用場景

1.降低後端負載:
對高消耗的SQL:join結果集/分組統計結果緩存。
2.加速請求響應:
利用Redis/Memcache優化IO響應時間
3.大量寫合併爲批量寫:
如計數器先Redis累加再批量寫DB

11-3 緩存的更新策略

1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy。
2.超時剔除:例如expire。
3.主動更新:開發控制生命週期

在這裏插入圖片描述
兩條建議
1.低一致性:最大內存和淘汰策略
2.高一致性:超時剔除和主動更新結合,最大內存和淘汰策略兜底。

11-4 緩存粒度問題

在這裏插入圖片描述
緩存粒度控制-三個角度
1.通用性:全量屬性更好。
2.佔用空間:部分屬性更好。
3.代碼維護:表面上全量屬性更好。

11-5 緩存穿透問題

在這裏插入圖片描述
原因
1.業務代碼自身問題
2.惡意攻擊、爬蟲等等

如何發現
1.業務的相應時間
2.業務本身問題
3.相關指標:總調用數、緩存層命中數、存儲層命中數

解決方法1-緩存空對象

在這裏插入圖片描述
兩個問題
1.需要更多的鍵。
2. 存儲層數據可能只是短期掛掉,緩存層數據置爲空會導致 二者“短期”不一致。
在這裏插入圖片描述
代碼中若 存儲層中的數據爲空 則設置在緩存中設爲空,並且設置過期時間

解決方法2-布隆過濾器攔截

在這裏插入圖片描述
該方法更適用於較爲固定的數據。

11-6 緩存雪崩優化

11-7 無底洞問題

問題描述:
2010年,Facebook有了3000個Memcache節點。
發現問題:“加”機器性能沒能提升,反而下降。
http://highscalability.com/blog/2009/10/26/facebooks-memcached-multiget-hole-more-machines-more-capacit.html

問題關鍵點:

  1. 更多的機器!=更高的性能
  2. 批量接口需求(mget,mset等)
  3. 數據增長與水平擴展需求
    在這裏插入圖片描述
    優化IO的幾種方法
    1.命令本身優化:例如慢查詢keys、hgetall bigkey
    2.減少網絡通信次數
    3.降低接入成本:例如客戶端長連接/連接池、NIO等

四種批量優化的方法
1.串行mget
2.串行I0
3.並行I0
4.hash_tag

11-8 熱點key的重建優化

在這裏插入圖片描述
三個目標和兩個解決
1.三個目標:
減少重緩存的次數
數據儘可能一致
減少潛在危險

2.兩個解決:
互斥鎖(mutex key)
在這裏插入圖片描述
實例代碼
在這裏插入圖片描述
永遠不過期
1.緩存層面:沒有設置過期時間(沒有用expire)。
2.功能層面:爲每個value添加邏輯過期時間,但發現超過邏輯過期時間後,會使用單獨的線程去構建緩存。
在這裏插入圖片描述
代碼示例:
在這裏插入圖片描述
兩種方案比較:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章