三、redis叢集方案-codis
之前我們討論的話題,無論是主從複製,還是哨兵模式,都是單個redis例項在工作。在大資料高併發的場景下,這種部署方案會顯得力不從心。
首先單個例項的記憶體不宜過大,過大的記憶體,會導致rdb檔案過大,從而導致主從同步時全量同步時間過長,重啟時也需要消耗很長的時間載入資料。
其次體現在cpu的利用率上,單個redis例項只能利用單個核心,處理海量資料時,壓力很大。
Codis是redis叢集解決方案之一,它將眾多小記憶體的reids例項整合起來,將分佈在多臺機器上的眾多cpu的計算能力聚集到一起,完成海量資料的儲存與高併發的讀寫。
Codis是豌豆莢中介軟體團隊發明的,在redis cluster未廣泛使用時,codis起到了至關重要的作用。
Codis是Go語言開發的代理中介軟體,如下圖所示:

圖1.代理結構圖
Codis也採用redis的協議,對外提供服務,但是由於代理的機制,導致其有些命令是無法支援的。
Codis是無狀態的,這意味著我們可以啟用多個codis例項提供給client,每個codis例項是對等的,這樣可以提高codis叢集的qps,也可以起到容災的作用。
Codis分片機制
Codis預設所有的key劃分為1024個slot,對客戶端傳入的key做crc32運算計算hash值,再將hash後的整數值對1024取模獲取key的slot。codis會在記憶體中維護slot與redis例項的對應關係。根據對映關係將資料轉發到對應的例項。
slot數量是可以設定的。
不同的codis例項之間slot關係是如何同步的?
codis叢集通過對zk與etcd的支援來保證資料的一致性,如果是依賴zk,那麼codisProxy的slot關係資訊會儲存在zk節點上,通過zk的監聽機制來共享slot資訊。
如下圖:

圖2.codis叢集同步slot資訊
管理員可以通過dashboard維護slot相關資訊,然後再同步到各個codisProxy。
如何擴容?
進行擴容,意味著叢集中增加新的redis例項,這時slot與例項的對映關係需要調整,意味著一部分資料需要進行遷移。
首先第一個問題是,我們需要找到槽位對應的所有key。codis增加了slotsscan命令,可以遍歷指定slot下所有的key。然後挨個將每個key遷移到新的redis節點。遷移過程中,codis收到新請求,如果是查詢key,那麼會強制先完成遷移工作,然後再提供對外服務。
最後一點,遷移操作是一個move操作,即遷移完成後,舊例項中就不存在key了。
自動均衡機制
redis新增例項,手動均衡slot比較麻煩,所以codis提供了自動均衡機制。自動均衡機制會在系統空閒時觀察每個例項對應的slot數量,不平衡會自動進行遷移。
Codis的劣勢
1.使用codis擴容的機器,redis不再支援事務。
2.rename這種危險的命令也不支援。官方文件中提供了不支援的命令列表。
3.為了支援遷移,單個key對應的value不宜過大。過大會導致遷移卡頓,官方建議小於1M,所以不適合存放社交關係資料等等。
4.網路開銷比單個例項要大,效能略微下降。可以通過增加代理數量來彌補效能不足。
5.如果依賴zk,那麼會增加zk運維成本。
Codis的優勢
1.設計上比官方的redis cluster方案要簡單。
2.託管給zk或者etcd,省去了分散式一致性邏輯。
問題 :mget查詢多個key的場景,codis會將key按照對映關係分組,然後對涉及的redis執行mget,最後由codis彙總返回。