做者:Kaito
來源:kaito-kidd.com/2020/07/07/redis-cluster-codis-twemproxyjava
以前咱們提到,爲了保證Redis的高可用,主要須要如下幾個方面:面試
咱們簡單理一下這幾個方案的特色,以及它們之間的聯繫。redis
數據持久化本質上是爲了作數據備份,有了數據持久化,當Redis宕機時,咱們能夠把數據從磁盤上恢復回來,但在數據恢復以前,服務是不可用的,並且數據恢復的時間取決於實例的大小,數據量越大,恢復起來越慢。算法
而主從複製則是部署多個副本節點,多個副本節點實時複製主節點的數據,當主節點宕機時,咱們有完整的副本節點可使用。另外一方面,若是咱們業務的讀請求量很大,主節點沒法承受全部的讀請求,多個副本節點能夠分擔讀請求,實現讀寫分離,這樣能夠提升Redis的訪問性能。spring
但有個問題是,當主節點宕機時,咱們雖然有完整的副本節點,但須要手動操做把從節點提高爲主節點繼續提供服務,若是每次主節點故障,都須要人工操做,這個過程既耗時耗力,也沒法保證及時性,高可用的程度將大打折扣。如何優化呢?數據庫
有了數據持久化、主從複製、故障自動恢復這些功能,咱們在使用Redis時是否是就能夠高枕無憂了?架構
答案是否認的,若是咱們的業務大部分都是讀請求,可使用讀寫分離提高性能。但若是寫請求量也很大呢?如今是大數據時代,像阿里、騰訊這些大致量的公司,每時每刻都擁有很是大的寫入量,此時若是隻有一個主節點是沒法承受的,那如何處理呢?intellij-idea
這就須要集羣化!簡單來講實現方式就是,多個主從節點構成一個集羣,每一個節點存儲一部分數據,這樣寫請求也能夠分散到多個主節點上,解決寫壓力大的問題。同時,集羣化能夠在節點容量不足和性能不夠時,動態增長新的節點,對進羣進行擴容,提高性能。運維
從這篇文章開始,咱們就開始介紹Redis的集羣化方案。固然,集羣化也意味着Redis部署架構更復雜,管理和維護起來成本也更高。並且在使用過程當中,也會遇到不少問題,這也衍生出了不一樣的集羣化解決方案,它們的側重點各不相同。異步
要想實現集羣化,就必須部署多個主節點,每一個主節點還有可能有多個從節點,以這樣的部署結構組成的集羣,才能更好地承擔更大的流量請求和存儲更多的數據。
能夠承擔更大的流量是集羣最基礎的功能,通常集羣化方案還包括了上面提到了數據持久化、數據複製、故障自動恢復功能,利用這些技術,來保證集羣的高性能和高可用。
另外,優秀的集羣化方案還實現了在線水平擴容功能,當節點數量不夠時,能夠動態增長新的節點來提高整個集羣的性能,並且這個過程是在線完成的,業務無感知。
業界主流的Redis集羣化方案主要包括如下幾個:
它們還能夠用是否中心化來劃分,其中客戶端分片、Redis Cluster屬於無中心化的集羣方案,Codis、Tweproxy屬於中心化的集羣方案。
是否中心化是指客戶端訪問多個Redis節點時,是直接訪問仍是經過一個中間層Proxy來進行操做,直接訪問的就屬於無中心化的方案,經過中間層Proxy訪問的就屬於中心化的方案,它們有各自的優劣,下面分別來介紹。
客戶端分片主要是說,咱們只須要部署多個Redis節點,具體如何使用這些節點,主要工做在客戶端。
客戶端經過固定的Hash算法,針對不一樣的key計算對應的Hash值,而後對不一樣的Redis節點進行讀寫。
客戶端分片集羣模式
客戶端分片須要業務開發人員事先評估業務的請求量和數據量,而後讓DBA部署足夠的節點交給開發人員使用便可。
這個方案的優勢是部署很是方便,業務須要多少個節點DBA直接部署交付便可,剩下的事情就須要業務開發人員根據節點數量來編寫key的請求路由邏輯,制定一個規則,通常採用固定的Hash算法,把不一樣的key寫入到不一樣的節點上,而後再根據這個規則進行數據讀取。
可見,它的缺點是業務開發人員使用Redis的成本較高,須要編寫路由規則的代碼來使用多個節點,並且若是事先對業務的數據量評估不許確,後期的擴容和遷移成本很是高,由於節點數量發生變動後,Hash算法對應的節點也就再也不是以前的節點了。
因此後來又衍生出了一致性哈希算法,就是爲了解決當節點數量變動時,儘可能減小數據的遷移和性能問題。
這種客戶端分片的方案通常用於業務數據量比較穩定,後期不會有大幅度增加的業務場景下使用,只須要前期評估好業務數據量便可。
隨着業務和技術的發展,人們愈加以爲,當我須要使用Redis時,咱們不想關心集羣后面有多少個節點,咱們但願咱們使用的Redis是一個大集羣,當咱們的業務量增長時,這個大集羣能夠增長新的節點來解決容量不夠用和性能問題。
這種方式就是服務端分片方案,客戶端不須要關心集羣后面有多少個Redis節點,只須要像使用一個Redis的方式去操做這個集羣,這種方案將大大下降開發人員的使用成本,開發人員能夠只須要關注業務邏輯便可,不須要關心Redis的資源問題。
多個節點組成的集羣,如何讓開發人員像操做一個Redis時那樣來使用呢?這就涉及到多個節點是如何組織起來提供服務的,通常咱們會在客戶端和服務端中間增長一個代理層,客戶端只須要操做這個代理層,代理層實現了具體的請求轉發規則,而後轉發請求到後面的多個節點上,所以這種方式也叫作中心化方式的集羣方案,Codis就是以這種方式實現的集羣化方案。
Codis是由國人前豌豆莢大神開發的,採用中心化方式的集羣方案。由於須要代理層Proxy來進行全部請求的轉發,因此對Proxy的性能要求很高,Codis採用Go語言開發,兼容了開發效率和性能。
Codis包含了多個組件:
可見Codis的組件仍是挺多的,它的功能很是全,除了請求轉發功能以外,還實現了在線數據遷移、節點擴容縮容、故障自動恢復等功能。
Codis的Proxy就是負責請求轉發的組件,它內部維護了請求轉發的具體規則,Codis把整個集羣劃分爲1024個槽位,在處理讀寫請求時,採用crc32
Hash算法計算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是由Twitter開源的集羣化方案,它既能夠作Redis Proxy,還能夠作Memcached Proxy。
它的功能比較單一,只實現了請求路由轉發,沒有像Codis那麼全面有在線擴容的功能,它解決的重點就是把客戶端分片的邏輯統一放到了Proxy層而已,其餘功能沒有作任何處理。
Tweproxy推出的時間最久,在早期沒有好的服務端分片集羣方案時,應用範圍很廣,並且性能也極其穩定。
但它的痛點就是沒法在線擴容、縮容,這就致使運維很是不方便,並且也沒有友好的運維UI可使用。Codis就是由於在這種背景下才衍生出來的。
採用中間加一層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個槽位進行路由規則的轉發。
Redis
沒有了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 正式發佈,全新顛覆性版本!
以爲不錯,別忘了隨手點贊+轉發哦!