主頁 > 後端開發 > Redis 的 3 種集群方案對比,寫得非常好!

Redis 的 3 種集群方案對比,寫得非常好!

2021-06-15 06:07:31 後端開發

作者:Kaito

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

之前我們提到,為了保證Redis的高可用,主要需要以下幾個方面:

  • 資料持久化
  • 主從復制
  • 自動故障恢復
  • 集群化

我們簡單理一下這幾個方案的特點,以及它們之間的聯系,

資料持久化本質上是為了做資料備份,有了資料持久化,當Redis宕機時,我們可以把資料從磁盤上恢復回來,但在資料恢復之前,服務是不可用的,而且資料恢復的時間取決于實體的大小,資料量越大,恢復起來越慢,

而主從復制則是部署多個副本節點,多個副本節點實時復制主節點的資料,當主節點宕機時,我們有完整的副本節點可以使用,另一方面,如果我們業務的讀請求量很大,主節點無法承受所有的讀請求,多個副本節點可以分擔讀請求,實作讀寫分離,這樣可以提高Redis的訪問性能,

但有個問題是,當主節點宕機時,我們雖然有完整的副本節點,但需要手動操作把從節點提升為主節點繼續提供服務,如果每次主節點故障,都需要人工操作,這個程序既耗時耗力,也無法保證及時性,高可用的程度將大打折扣,如何優化呢?

有了資料持久化、主從復制、故障自動恢復這些功能,我們在使用Redis時是不是就可以高枕無憂了?

答案是否定的,如果我們的業務大部分都是讀請求,可以使用讀寫分離提升性能,但如果寫請求量也很大呢?現在是大資料時代,像阿里、騰訊這些大體量的公司,每時每刻都擁有非常大的寫入量,此時如果只有一個主節點是無法承受的,那如何處理呢?

這就需要集群化!簡單來說實作方式就是,多個主從節點構成一個集群,每個節點存盤一部分資料,這樣寫請求也可以分散到多個主節點上,解決寫壓力大的問題,同時,集群化可以在節點容量不足和性能不夠時,動態增加新的節點,對進群進行擴容,提升性能,

從這篇文章開始,我們就開始介紹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開發手冊(嵩山版)》最新發布,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/287288.html

標籤:其他

上一篇:PHP中的陣列分頁實作(非資料庫)

下一篇:C++數值型別與string、CString之間的轉換

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more