Redis 的 3 種集羣方案對比,寫得很是好!

做者:Kaito

來源:kaito-kidd.com/2020/07/07/redis-cluster-codis-twemproxyjava

以前咱們提到,爲了保證Redis的高可用,主要須要如下幾個方面:面試

  • 數據持久化
  • 主從複製
  • 自動故障恢復
  • 集羣化

咱們簡單理一下這幾個方案的特色,以及它們之間的聯繫。redis

數據持久化本質上是爲了作數據備份,有了數據持久化,當Redis宕機時,咱們能夠把數據從磁盤上恢復回來,但在數據恢復以前,服務是不可用的,並且數據恢復的時間取決於實例的大小,數據量越大,恢復起來越慢。算法

而主從複製則是部署多個副本節點,多個副本節點實時複製主節點的數據,當主節點宕機時,咱們有完整的副本節點可使用。另外一方面,若是咱們業務的讀請求量很大,主節點沒法承受全部的讀請求,多個副本節點能夠分擔讀請求,實現讀寫分離,這樣能夠提升Redis的訪問性能。spring

但有個問題是,當主節點宕機時,咱們雖然有完整的副本節點,但須要手動操做把從節點提高爲主節點繼續提供服務,若是每次主節點故障,都須要人工操做,這個過程既耗時耗力,也沒法保證及時性,高可用的程度將大打折扣。如何優化呢?數據庫

有了數據持久化、主從複製、故障自動恢復這些功能,咱們在使用Redis時是否是就能夠高枕無憂了?架構

答案是否認的,若是咱們的業務大部分都是讀請求,可使用讀寫分離提高性能。但若是寫請求量也很大呢?如今是大數據時代,像阿里、騰訊這些大致量的公司,每時每刻都擁有很是大的寫入量,此時若是隻有一個主節點是沒法承受的,那如何處理呢?intellij-idea

這就須要集羣化!簡單來講實現方式就是,多個主從節點構成一個集羣,每一個節點存儲一部分數據,這樣寫請求也能夠分散到多個主節點上,解決寫壓力大的問題。同時,集羣化能夠在節點容量不足和性能不夠時,動態增長新的節點,對進羣進行擴容,提高性能。運維

從這篇文章開始,咱們就開始介紹Redis的集羣化方案。固然,集羣化也意味着Redis部署架構更復雜,管理和維護起來成本也更高。並且在使用過程當中,也會遇到不少問題,這也衍生出了不一樣的集羣化解決方案,它們的側重點各不相同。異步

集羣化方案

要想實現集羣化,就必須部署多個主節點,每一個主節點還有可能有多個從節點,以這樣的部署結構組成的集羣,才能更好地承擔更大的流量請求和存儲更多的數據。

能夠承擔更大的流量是集羣最基礎的功能,通常集羣化方案還包括了上面提到了數據持久化、數據複製、故障自動恢復功能,利用這些技術,來保證集羣的高性能和高可用。

另外,優秀的集羣化方案還實現了在線水平擴容功能,當節點數量不夠時,能夠動態增長新的節點來提高整個集羣的性能,並且這個過程是在線完成的,業務無感知。

業界主流的Redis集羣化方案主要包括如下幾個:

  • 客戶端分片
  • Codis
  • Twemproxy
  • Redis Cluster

它們還能夠用是否中心化來劃分,其中客戶端分片、Redis Cluster屬於無中心化的集羣方案,Codis、Tweproxy屬於中心化的集羣方案。

是否中心化是指客戶端訪問多個Redis節點時,是直接訪問仍是經過一個中間層Proxy來進行操做,直接訪問的就屬於無中心化的方案,經過中間層Proxy訪問的就屬於中心化的方案,它們有各自的優劣,下面分別來介紹。

客戶端分片

客戶端分片主要是說,咱們只須要部署多個Redis節點,具體如何使用這些節點,主要工做在客戶端。

客戶端經過固定的Hash算法,針對不一樣的key計算對應的Hash值,而後對不一樣的Redis節點進行讀寫。

客戶端分片集羣模式

客戶端分片須要業務開發人員事先評估業務的請求量和數據量,而後讓DBA部署足夠的節點交給開發人員使用便可。

這個方案的優勢是部署很是方便,業務須要多少個節點DBA直接部署交付便可,剩下的事情就須要業務開發人員根據節點數量來編寫key的請求路由邏輯,制定一個規則,通常採用固定的Hash算法,把不一樣的key寫入到不一樣的節點上,而後再根據這個規則進行數據讀取。

可見,它的缺點是業務開發人員使用Redis的成本較高,須要編寫路由規則的代碼來使用多個節點,並且若是事先對業務的數據量評估不許確,後期的擴容和遷移成本很是高,由於節點數量發生變動後,Hash算法對應的節點也就再也不是以前的節點了。

因此後來又衍生出了一致性哈希算法,就是爲了解決當節點數量變動時,儘可能減小數據的遷移和性能問題。

這種客戶端分片的方案通常用於業務數據量比較穩定,後期不會有大幅度增加的業務場景下使用,只須要前期評估好業務數據量便可。

Codis

隨着業務和技術的發展,人們愈加以爲,當我須要使用Redis時,咱們不想關心集羣后面有多少個節點,咱們但願咱們使用的Redis是一個大集羣,當咱們的業務量增長時,這個大集羣能夠增長新的節點來解決容量不夠用和性能問題

這種方式就是服務端分片方案,客戶端不須要關心集羣后面有多少個Redis節點,只須要像使用一個Redis的方式去操做這個集羣,這種方案將大大下降開發人員的使用成本,開發人員能夠只須要關注業務邏輯便可,不須要關心Redis的資源問題。

多個節點組成的集羣,如何讓開發人員像操做一個Redis時那樣來使用呢?這就涉及到多個節點是如何組織起來提供服務的,通常咱們會在客戶端和服務端中間增長一個代理層,客戶端只須要操做這個代理層,代理層實現了具體的請求轉發規則,而後轉發請求到後面的多個節點上,所以這種方式也叫作中心化方式的集羣方案,Codis就是以這種方式實現的集羣化方案。

Proxy集羣模式

Codis架構圖

Codis是由國人前豌豆莢大神開發的,採用中心化方式的集羣方案。由於須要代理層Proxy來進行全部請求的轉發,因此對Proxy的性能要求很高,Codis採用Go語言開發,兼容了開發效率和性能。

Codis包含了多個組件:

  • codis-proxy:主要負責對請求的讀寫進行轉發
  • codis-dashbaord:統一的控制中心,整合了數據轉發規則、故障自動恢復、數據在線遷移、節點擴容縮容、自動化運維API等功能
  • codis-group:基於Redis 3.2.8版本二次開發的Redis Server,增長了異步數據遷移功能
  • codis-fe:管理多個集羣的UI界面

可見Codis的組件仍是挺多的,它的功能很是全,除了請求轉發功能以外,還實現了在線數據遷移、節點擴容縮容、故障自動恢復等功能

Codis的Proxy就是負責請求轉發的組件,它內部維護了請求轉發的具體規則,Codis把整個集羣劃分爲1024個槽位,在處理讀寫請求時,採用crc32Hash算法計算key的Hash值,而後再根據Hash值對1024個槽位取模,最終找到具體的Redis節點。

Codis最大的特色就是能夠在線擴容,在擴容期間不影響客戶端的訪問,也就是不須要停機。這對業務使用方是極大的便利,當集羣性能不夠時,就能夠動態增長節點來提高集羣的性能。

爲了實如今線擴容,保證數據在遷移過程當中還有可靠的性能,Codis針對Redis進行了修改,增長了針對異步遷移數據相關命令,它基於Redis 3.2.8進行開發,上層配合Dashboard和Proxy組件,完成對業務無損的數據遷移和擴容功能。

所以,要想使用Codis,必須使用它內置的Redis,這也就意味着Codis中的Redis是否能跟上官方最新版的功能特性,可能沒法獲得保障,這取決於Codis的維護方,目前Codis已經再也不維護,因此使用Codis時只能使用3.2.8版的Redis,這是一個痛點。

另外,因爲集羣化都須要部署多個節點,所以操做集羣並不能徹底像操做單個Redis同樣實現全部功能,主要是對於操做多個節點可能產生問題的命令進行了禁用或限制,具體可參考Codis不支持的命令列表。

但這不影響它是一個優秀的集羣化方案,因爲我司使用Redis集羣方案較早,那時Redis Cluster還不夠成熟,因此我司使用的Redis集羣方案就是Codis。

目前個人工做主要是圍繞Codis展開的,咱們公司對Codis進行了定製開發,還對Redis進行了一些改造,讓Codis支持了跨多個數據中心的數據同步。

Twemproxy

Twemproxy是由Twitter開源的集羣化方案,它既能夠作Redis Proxy,還能夠作Memcached Proxy。

它的功能比較單一,只實現了請求路由轉發,沒有像Codis那麼全面有在線擴容的功能,它解決的重點就是把客戶端分片的邏輯統一放到了Proxy層而已,其餘功能沒有作任何處理。

Twemproxy架構圖

Tweproxy推出的時間最久,在早期沒有好的服務端分片集羣方案時,應用範圍很廣,並且性能也極其穩定。

但它的痛點就是沒法在線擴容、縮容,這就致使運維很是不方便,並且也沒有友好的運維UI可使用。Codis就是由於在這種背景下才衍生出來的。

Redis Cluster

採用中間加一層Proxy的中心化模式時,這就對Proxy的要求很高,由於它一旦出現故障,那麼操做這個Proxy的全部客戶端都沒法處理,要想實現Proxy的高可用,還須要另外的機制來實現,例如Keepalive。

並且增長一層Proxy進行轉發,必然會有必定的性能損耗,那麼除了客戶端分片和上面提到的中心化的方案以外,還有比較好的解決方案麼?

Redis官方推出的Redis Cluster另闢蹊徑,它沒有采用中心化模式的Proxy方案,而是把請求轉發邏輯一部分放在客戶端,一部分放在了服務端,它們之間互相配合完成請求的處理。

Redis Cluster是在Redis 3.0推出的,早起的Redis Cluster因爲沒有通過嚴格的測試和生產驗證,因此並無普遍推廣開來。也正是在這樣的背景下,業界衍生了出了上面所說的中心化集羣方案:Codis和Tweproxy。

但隨着Redis的版本迭代,Redis官方的Cluster也愈來愈穩定,更多人開始採用官方的集羣化方案。也正是由於它是官方推出的,因此它的持續維護性能夠獲得保障,這就比那些第三方的開源方案更有優點。

Redis Cluster沒有了中間的Proxy代理層,那麼是如何進行請求的轉發呢?

Redis把請求轉發的邏輯放在了Smart Client中,要想使用Redis Cluster,必須升級Client SDK,這個SDK中內置了請求轉發的邏輯,因此業務開發人員一樣不須要本身編寫轉發規則,Redis Cluster採用16384個槽位進行路由規則的轉發。

ClusterRedis

沒有了Proxy層進行轉發,客戶端能夠直接操做對應的Redis節點,這樣就少了Proxy層轉發的性能損耗。

Redis Cluster也提供了在線數據遷移、節點擴容縮容等功能,內部還內置了哨兵完成故障自動恢復功能,可見它是一個集成全部功能於一體的Cluster。所以它在部署時很是簡單,不須要部署過多的組件,對於運維極其友好。

Redis Cluster在節點數據遷移、擴容縮容時,對於客戶端的請求處理也作了相應的處理。當客戶端訪問的數據正好在遷移過程當中時,服務端與客戶端制定了一些協議,來告知客戶端去正確的節點上訪問,幫助客戶端訂正本身的路由規則。

雖然Redis Cluster提供了在線數據遷移的功能,但它的遷移性能並不高,遷移過程當中遇到大key時還有可能長時間阻塞遷移的兩個節點,這個功能相較於Codis來講,Codis數據遷移性能更好。

如今愈來愈多的公司開始採用Redis Cluster,有能力的公司還在它的基礎上進行了二次開發和定製,來解決Redis Cluster存在的一些問題,咱們期待Redis Cluster將來有更好的發展。

總結

比較完了這些集羣化方案,下面咱們來總結一下。

# 客戶端分片 Codis Tweproxy Redis Cluster
集羣模式 無中心化 中心化 中心化 無中心化
使用方式 客戶端編寫路由規則代碼,直連Redis 經過Proxy訪問 經過Proxy訪問 使用Smart Client直連Redis,Smart Client內置路由規則
性能 有性能損耗 有性能損耗
支持的數據庫數量 多個 多個 多個 一個
Pipeline 支持 支持 支持 僅支持單個節點Pipeline,不支持跨節點
需升級客戶端SDK?
支持在線水平擴容? 不支持 支持 不支持 支持
Redis版本 支持最新版 僅支持3.2.8,升級困難 支持最新版 支持最新版
可維護性 運維簡單,開發人員使用成本高 組件較多,部署複雜 只有Proxy組件,部署簡單 運維簡單,官方持續維護
故障自動恢復 需部署哨兵 需部署哨兵 需部署哨兵 內置哨兵邏輯,無需額外部署

業界主流的集羣化方案就是以上這些,並對它們的特色和區別作了簡單的介紹,咱們在開發過程當中選擇本身合適的集羣方案便可,但最好是理解它們的實現原理,在使用過程當中遇到問題才能夠更從容地去解決。

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2021最新版)

2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!

3.阿里 Mock 工具正式開源,幹掉市面上全部 Mock 工具!

4.Spring Cloud 2020.0.0 正式發佈,全新顛覆性版本!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

以爲不錯,別忘了隨手點贊+轉發哦!

相關文章
相關標籤/搜索