一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Redis架構(gòu)演化之路

jf_ro2CN3Fa ? 來(lái)源:芋道源碼 ? 2023-08-03 16:54 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

b2b3f398-31a0-11ee-9e74-dac502259ad0.gif

國(guó)產(chǎn) Star 破 10w+ 的開(kāi)源項(xiàng)目,前端包括管理后臺(tái) + 微信小程序,后端支持單體和微服務(wù)架構(gòu)。

功能涵蓋 RBAC 權(quán)限、SaaS 多租戶(hù)、數(shù)據(jù)權(quán)限、商城、支付、工作流、大屏報(bào)表、微信公眾號(hào)等等功能:

  • Boot 項(xiàng)目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 項(xiàng)目地址:https://gitee.com/zhijiantianya/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn
來(lái)源:水滴與銀彈
  • 從最簡(jiǎn)單的開(kāi)始:?jiǎn)螜C(jī)版 Redis
  • 數(shù)據(jù)持久化:有備無(wú)患
  • 主從復(fù)制:多副本
  • 哨兵:故障自動(dòng)切換
  • 分片集群:橫向擴(kuò)展
  • 總結(jié)

這篇文章我想和你聊一聊 Redis 的架構(gòu)演化之路。

現(xiàn)如今 Redis 變得越來(lái)越流行,幾乎在很多項(xiàng)目中都要被用到,不知道你在使用 Redis 時(shí),有沒(méi)有思考過(guò),Redis 到底是如何穩(wěn)定、高性能地提供服務(wù)的?

  • 我使用 Redis 的場(chǎng)景很簡(jiǎn)單,只使用單機(jī)版 Redis 會(huì)有什么問(wèn)題嗎?
  • 我的 Redis 故障宕機(jī)了,數(shù)據(jù)丟失了怎么辦?如何能保證我的業(yè)務(wù)應(yīng)用不受影響?
  • 為什么需要主從集群?它有什么優(yōu)勢(shì)?
  • 什么是分片集群?我真的需要分片集群?jiǎn)幔?/li>
  • ...

如果你對(duì) Redis 已經(jīng)有些了解,肯定也聽(tīng)說(shuō)過(guò)「數(shù)據(jù)持久化、主從復(fù)制、哨兵、分片集群 」這些概念,它們之間又有什么區(qū)別和聯(lián)系呢?

如果你存在這樣的疑惑,這篇文章,我會(huì)從 0 到 1,再?gòu)?1 到 N,帶你一步步構(gòu)建出一個(gè)穩(wěn)定、高性能的 Redis 集群。

在這個(gè)過(guò)程中,你可以了解到 Redis 為了做到穩(wěn)定、高性能,都采取了哪些優(yōu)化方案,以及為什么要這么做?

掌握了這些原理,這樣平時(shí)你在使用 Redis 時(shí),就能夠做到「游刃有余」。

從最簡(jiǎn)單的開(kāi)始:?jiǎn)螜C(jī)版 Redis

首先,我們從最簡(jiǎn)單的場(chǎng)景開(kāi)始。

假設(shè)現(xiàn)在你有一個(gè)業(yè)務(wù)應(yīng)用,需要引入 Redis 來(lái)提高應(yīng)用的性能,此時(shí)你可以選擇部署一個(gè)單機(jī)版的 Redis 來(lái)使用,就像這樣:

b320542a-31a0-11ee-9e74-dac502259ad0.jpg

這個(gè)架構(gòu)非常簡(jiǎn)單,你的業(yè)務(wù)應(yīng)用可以把 Redis 當(dāng)做緩存來(lái)使用,從 MySQL 中查詢(xún)數(shù)據(jù),然后寫(xiě)入到 Redis 中,之后業(yè)務(wù)應(yīng)用再?gòu)?Redis 中讀取這些數(shù)據(jù),由于 Redis 的數(shù)據(jù)都存儲(chǔ)在內(nèi)存中,所以這個(gè)速度飛快。

如果你的業(yè)務(wù)體量并不大,那這樣的架構(gòu)模型基本可以滿(mǎn)足你的需求。是不是很簡(jiǎn)單?

隨著時(shí)間的推移,你的業(yè)務(wù)體量逐漸發(fā)展起來(lái)了,Redis 中存儲(chǔ)的數(shù)據(jù)也越來(lái)越多,此時(shí)你的業(yè)務(wù)應(yīng)用對(duì) Redis 的依賴(lài)也越來(lái)越重。

突然有一天,你的 Redis 因?yàn)槟承┰蝈礄C(jī)了,這時(shí)你的所有業(yè)務(wù)流量,都會(huì)打到后端 MySQL 上,MySQL 壓力劇增,嚴(yán)重的話甚至?xí)嚎?MySQL。

b3304844-31a0-11ee-9e74-dac502259ad0.jpg

這時(shí)你應(yīng)該怎么辦?

我猜你的方案肯定是,趕緊重啟 Redis,讓它可以繼續(xù)提供服務(wù)。

但是,因?yàn)橹?Redis 中的數(shù)據(jù)都在內(nèi)存中,盡管你現(xiàn)在把 Redis 重啟了,之前的數(shù)據(jù)也都丟失了(假設(shè)沒(méi)開(kāi)持久化)。重啟后的 Redis 雖然可以正常工作,但是由于 Redis 中沒(méi)有任何數(shù)據(jù),業(yè)務(wù)流量還是都會(huì)打到后端 MySQL 上,MySQL 的壓力還是很大。

有沒(méi)有什么好的辦法解決這個(gè)問(wèn)題?

既然 Redis 只把數(shù)據(jù)存儲(chǔ)在內(nèi)存中,那是否可以把這些數(shù)據(jù)也寫(xiě)一份到磁盤(pán)上呢?

如果采用這種方式,當(dāng) Redis 重啟時(shí),我們把磁盤(pán)中的數(shù)據(jù)快速「恢復(fù) 」到內(nèi)存中,這樣它就可以繼續(xù)正常提供服務(wù)了。

是的,這是一個(gè)很好的解決方案,這個(gè)把內(nèi)存數(shù)據(jù)寫(xiě)到磁盤(pán)上的過(guò)程,就是「數(shù)據(jù)持久化」。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

數(shù)據(jù)持久化:有備無(wú)患

現(xiàn)在,你設(shè)想的 Redis 數(shù)據(jù)持久化是這樣的:

b3496982-31a0-11ee-9e74-dac502259ad0.jpg3

但是,數(shù)據(jù)持久化具體應(yīng)該怎么做呢?

我猜你最容易想到的一個(gè)方案是,Redis 每一次執(zhí)行寫(xiě)操作,除了寫(xiě)內(nèi)存之外,同時(shí)也寫(xiě)一份到磁盤(pán)上,就像這樣:

b35e4c30-31a0-11ee-9e74-dac502259ad0.jpg

沒(méi)錯(cuò),這是最簡(jiǎn)單直接的方案。

但仔細(xì)想一下,這個(gè)方案有個(gè)問(wèn)題:客戶(hù)端的每次寫(xiě)操作,既需要寫(xiě)內(nèi)存,又需要寫(xiě)磁盤(pán),而寫(xiě)磁盤(pán)的耗時(shí)相比于寫(xiě)內(nèi)存來(lái)說(shuō),肯定要慢很多!這勢(shì)必會(huì)影響到 Redis 的性能。

如何規(guī)避這個(gè)問(wèn)題?

這時(shí)我們需要分析寫(xiě)磁盤(pán)的細(xì)節(jié)問(wèn)題了。

我們都知道,要把內(nèi)存數(shù)據(jù)寫(xiě)到磁盤(pán),其實(shí)是分 2 步的:

  1. 程序?qū)懳募?PageCache(write)
  2. 把 PageCache 刷到磁盤(pán)(fsync)

具體就是下圖這樣:

b37998a0-31a0-11ee-9e74-dac502259ad0.png

數(shù)據(jù)持久化最粗暴的思路就是上面提到的那樣,寫(xiě)完 Redis 內(nèi)存后,同步寫(xiě) PageCache + fsync 磁盤(pán),當(dāng)然,這樣肯定因?yàn)榇疟P(pán)拖慢整個(gè)寫(xiě)入速度。

如何優(yōu)化?也很簡(jiǎn)單,我們可以這樣做:Redis 寫(xiě)內(nèi)存由主線程來(lái)做,寫(xiě)內(nèi)存完成后就給客戶(hù)端返回結(jié)果,然后 Redis 用「另一個(gè)線程」去寫(xiě)磁盤(pán),這樣就可以避免主線程寫(xiě)磁盤(pán)對(duì)性能的影響。

b393ea16-31a0-11ee-9e74-dac502259ad0.jpg

這種持久化方案,其實(shí)就是我們經(jīng)常聽(tīng)到的 Redis AOF(Append Only File)。

Redis AOF 持久化提供了 3 種刷盤(pán)機(jī)制:

  1. appendfsync always:主線程同步 fsync
  2. appendfsync no:由 OS fsync
  3. appendfsync everysec:后臺(tái)線程每間隔1秒 fsync

解決了數(shù)據(jù)實(shí)時(shí)持久化,我們還會(huì)面臨另一個(gè)問(wèn)題,數(shù)據(jù)實(shí)時(shí)寫(xiě)入 AOF,隨著時(shí)間的推移,AOF 文件會(huì)越來(lái)越大,那使用 AOF 恢復(fù)時(shí)變得非常慢,這該怎么辦?

Redis 很貼心地提供了 AOF rewrite 方案,俗稱(chēng) AOF 「瘦身」,顧名思義,就是壓縮 AOF 的體積。

因?yàn)?AOF 里記錄的都是每一次寫(xiě)命令,例如執(zhí)行 set k1 v1,set k1 v2,其實(shí)我們只關(guān)心數(shù)據(jù)的最終版本 v2 就可以了。AOF rewrite 正是利用了這個(gè)特點(diǎn),在 AOF 體積越來(lái)越大時(shí)(超過(guò)設(shè)定閾值),Redis 就會(huì)定期重寫(xiě)一份新的 AOF,這個(gè)新的 AOF 只記錄數(shù)據(jù)的最終版本就可以了。

b3a770f4-31a0-11ee-9e74-dac502259ad0.png

這樣就可以壓縮 AOF 體積。

除此之外,我們可以換個(gè)角度,思考一下還有什么方式可以持久化數(shù)據(jù)?

這時(shí)你就要結(jié)合 Redis 的使用場(chǎng)景來(lái)考慮了。

回憶一下,我們?cè)谑褂?Redis 時(shí),通常把它用作什么場(chǎng)景?

是的,緩存。

把 Redis 當(dāng)做緩存來(lái)用,意味著盡管 Redis 中沒(méi)有保存全量數(shù)據(jù),對(duì)于不在緩存中的數(shù)據(jù),我們的業(yè)務(wù)應(yīng)用依舊可以通過(guò)查詢(xún)后端數(shù)據(jù)庫(kù)得到結(jié)果,只不過(guò)查詢(xún)后端數(shù)據(jù)的速度會(huì)慢一點(diǎn)而已,但對(duì)業(yè)務(wù)結(jié)果其實(shí)是沒(méi)有影響的。

基于這個(gè)特點(diǎn),我們的 Redis 數(shù)據(jù)持久化還可以用「數(shù)據(jù)快照 」的方式來(lái)做。

那什么是數(shù)據(jù)快照呢?

簡(jiǎn)單來(lái)講,你可以這么理解:

  1. 你把 Redis 想象成一個(gè)水杯,向 Redis 寫(xiě)入數(shù)據(jù),就相當(dāng)于往這個(gè)杯子里倒水
  2. 此時(shí)你拿一個(gè)相機(jī)給這個(gè)水杯拍一張照片,拍照的這一瞬間,照片中記錄到這個(gè)水杯中水的容量,就是水杯的數(shù)據(jù)快照
b3d27a92-31a0-11ee-9e74-dac502259ad0.jpg

也就是說(shuō),Redis 的數(shù)據(jù)快照,是記錄某一時(shí)刻下 Redis 中的數(shù)據(jù),然后只需要把這個(gè)數(shù)據(jù)快照寫(xiě)到磁盤(pán)上就可以了。

它的優(yōu)勢(shì)在于,只在需要持久化時(shí),把數(shù)據(jù)「一次性 」寫(xiě)入磁盤(pán),其它時(shí)間都不需要操作磁盤(pán)。

基于這個(gè)方案,我們可以「定時(shí) 」給 Redis 做數(shù)據(jù)快照,把數(shù)據(jù)持久化到磁盤(pán)上。

b3f001ac-31a0-11ee-9e74-dac502259ad0.jpg

這種方案就是我們經(jīng)常聽(tīng)到的 Redis RDB,RDB 采用「定時(shí)快照 」的方式進(jìn)行數(shù)據(jù)持久化,它的優(yōu)點(diǎn)是:

  1. 持久化文件體積?。ǘM(jìn)制 + 壓縮)
  2. 寫(xiě)盤(pán)頻率低(定時(shí)寫(xiě)入)

缺點(diǎn)也很明顯,因?yàn)槭嵌〞r(shí)持久化,數(shù)據(jù)肯定沒(méi)有 AOF 實(shí)時(shí)持久化完整,如果你的 Redis 只當(dāng)做緩存,對(duì)于丟失數(shù)據(jù)不敏感(可從后端的數(shù)據(jù)庫(kù)查詢(xún)),那這種持久化方式是非常合適的。

如果讓你來(lái)選擇持久化方案,你可以這樣選擇:

  1. 業(yè)務(wù)對(duì)于數(shù)據(jù)丟失不敏感,選 RDB
  2. 業(yè)務(wù)對(duì)數(shù)據(jù)完整性要求比較高,選 AOF

理解了 RDB 和 AOF,我們?cè)龠M(jìn)一步思考一下,有沒(méi)有什么辦法,既可以保證數(shù)據(jù)完整性,還能讓持久化文件體積更小,恢復(fù)更快呢?

回顧一下我們前面講到的,RDB 和 AOF 各自的特點(diǎn):

  1. RDB 以二進(jìn)制 + 數(shù)據(jù)壓縮方式存儲(chǔ),文件體積小
  2. AOF 記錄每一次寫(xiě)命令,數(shù)據(jù)最全

我們可否利用它們各自的優(yōu)勢(shì)呢?

當(dāng)然可以,這就是 Redis 的「混合持久化 」。

要想數(shù)據(jù)完整性更高,肯定就不能只用 RDB 了,重點(diǎn)還是要放在 AOF 優(yōu)化上。

具體來(lái)說(shuō),當(dāng) AOF 在做 rewrite 時(shí),Redis 先以 RDB 格式在 AOF 文件中寫(xiě)入一個(gè)數(shù)據(jù)快照,再把在這期間產(chǎn)生的每一個(gè)寫(xiě)命令,追加到 AOF 文件中。

因?yàn)?RDB 是二進(jìn)制壓縮寫(xiě)入的,這樣 AOF 文件體積就變得更小了。

b40f5b56-31a0-11ee-9e74-dac502259ad0.png

因?yàn)?AOF 體積進(jìn)一步壓縮,你在使用 AOF 恢復(fù)數(shù)據(jù)時(shí),這個(gè)恢復(fù)時(shí)間就會(huì)更短了!

Redis 4.0 以上版本才支持混合持久化。

注意:混合持久化是對(duì) AOF rewrite 的優(yōu)化,這意味著使用它必須基于 AOF + AOF rewrite。

這么一番優(yōu)化,你的 Redis 再也不用擔(dān)心實(shí)例宕機(jī)了,當(dāng)發(fā)生宕機(jī)時(shí),你就可以用持久化文件快速恢復(fù) Redis 中的數(shù)據(jù)。

但這樣就沒(méi)問(wèn)題了嗎?

仔細(xì)想一下,雖然我們已經(jīng)把持久化的文件優(yōu)化到最小了,但在恢復(fù)數(shù)據(jù)時(shí)依舊是需要時(shí)間 的,在這期間你的業(yè)務(wù)應(yīng)用無(wú)法提供服務(wù),這怎么辦?

一個(gè)實(shí)例宕機(jī),只能用恢復(fù)數(shù)據(jù)來(lái)解決,那我們是否可以部署多個(gè) Redis 實(shí)例,然后讓這些實(shí)例數(shù)據(jù)保持實(shí)時(shí)同步,這樣當(dāng)一個(gè)實(shí)例宕機(jī)時(shí),我們?cè)谑O碌膶?shí)例中選擇一個(gè)繼續(xù)提供服務(wù)就好了。

沒(méi)錯(cuò),這個(gè)方案就是接下來(lái)要講的「主從復(fù)制:多副本」。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

主從復(fù)制:多副本

你可以部署多個(gè) Redis 實(shí)例,架構(gòu)模型就變成了這樣:

b43ac174-31a0-11ee-9e74-dac502259ad0.jpg

我們這里把實(shí)時(shí)讀寫(xiě)的節(jié)點(diǎn)叫做 master,另一個(gè)實(shí)時(shí)同步數(shù)據(jù)的節(jié)點(diǎn)叫做 slave。

采用多副本的方案,它的優(yōu)勢(shì)是:

  1. 縮短不可用時(shí)間 :master 發(fā)生宕機(jī),我們可以手動(dòng)把 slave 提升為 master 繼續(xù)提供服務(wù)
  2. 提升讀性能 :讓 slave 分擔(dān)一部分讀請(qǐng)求,提升應(yīng)用的整體性能
b4529c54-31a0-11ee-9e74-dac502259ad0.jpg

這個(gè)方案不錯(cuò),不僅節(jié)省了數(shù)據(jù)恢復(fù)的時(shí)間,還能提升性能。

但它的問(wèn)題在于:當(dāng) master 宕機(jī)時(shí),我們需要「手動(dòng)」把 slave 提升為 master,這個(gè)過(guò)程也是需要花費(fèi)時(shí)間的。

雖然比恢復(fù)數(shù)據(jù)要快得多,但還是需要人工介入處理。一旦需要人工介入,就必須要算上人的反應(yīng)時(shí)間、操作時(shí)間,所以,在這期間你的業(yè)務(wù)應(yīng)用依舊會(huì)受到影響。

我們是否可以把這個(gè)切換的過(guò)程,變成自動(dòng)化?

哨兵:故障自動(dòng)切換

要想自動(dòng)切換,肯定不能依賴(lài)人了。

現(xiàn)在,我們可以引入一個(gè)「觀察者」,讓這個(gè)觀察者去實(shí)時(shí)監(jiān)測(cè) master 的健康狀態(tài),這個(gè)觀察者就是「哨兵」。

具體如何做?

  1. 哨兵每間隔一段時(shí)間,詢(xún)問(wèn) master 是否正常
  2. master 正?;貜?fù),表示狀態(tài)正常,回復(fù)超時(shí)表示異常
  3. 哨兵發(fā)現(xiàn)異常,發(fā)起主從切換
b463cb82-31a0-11ee-9e74-dac502259ad0.jpg

有了這個(gè)方案,就不需要人去介入處理了,一切就變得自動(dòng)化了,是不是很爽?

但這里還有一個(gè)問(wèn)題,如果 master 狀態(tài)正常,但這個(gè)哨兵在詢(xún)問(wèn) master 時(shí),它們之間的網(wǎng)絡(luò)發(fā)生了問(wèn)題,那這個(gè)哨兵可能會(huì)「誤判 」。

b486d14a-31a0-11ee-9e74-dac502259ad0.jpg

這個(gè)問(wèn)題怎么解決?

既然一個(gè)哨兵會(huì)誤判,那我們可以部署多個(gè)哨兵,讓它們分布在不同的機(jī)器上,讓它們一起監(jiān)測(cè) master 的狀態(tài),流程就變成了這樣:

b49ea270-31a0-11ee-9e74-dac502259ad0.jpg
  1. 多個(gè)哨兵每間隔一段時(shí)間,詢(xún)問(wèn) master 是否正常
  2. master 正?;貜?fù),表示狀態(tài)正常,回復(fù)超時(shí)表示異常
  3. 一旦有一個(gè)哨兵判定 master 異常(不管是否是網(wǎng)絡(luò)問(wèn)題),就詢(xún)問(wèn)其它哨兵,如果多個(gè)哨兵(設(shè)置一個(gè)閾值)都認(rèn)為 master 異常了,這才判定 master 確實(shí)發(fā)生了故障
  4. 多個(gè)哨兵經(jīng)過(guò)協(xié)商后,判定 master 故障,則發(fā)起主從切換

所以,我們用多個(gè)哨兵互相協(xié)商來(lái)判定 master 的狀態(tài),這樣,就可以大大降低誤判的概率。

哨兵協(xié)商判定 master 異常后,這里還有一個(gè)問(wèn)題:由哪個(gè)哨兵來(lái)發(fā)起主從切換呢?

答案是,選出一個(gè)哨兵「領(lǐng)導(dǎo)者」,由這個(gè)領(lǐng)導(dǎo)者進(jìn)行主從切換。

問(wèn)題又來(lái)了,這個(gè)領(lǐng)導(dǎo)者怎么選?

想象一下,在現(xiàn)實(shí)生活中,選舉是怎么做的?

是的,投票。

在選舉哨兵領(lǐng)導(dǎo)者時(shí),我們可以制定這樣一個(gè)選舉規(guī)則:

  1. 每個(gè)哨兵都詢(xún)問(wèn)其它哨兵,請(qǐng)求對(duì)方為自己投票
  2. 每個(gè)哨兵只投票給第一個(gè)請(qǐng)求投票的哨兵,且只能投票一次
  3. 首先拿到超過(guò)半數(shù)投票的哨兵,當(dāng)選為領(lǐng)導(dǎo)者,發(fā)起主從切換

這個(gè)選舉的過(guò)程就是我們經(jīng)常聽(tīng)到的:分布式系統(tǒng)領(lǐng)域中的「共識(shí)算法 」。

什么是共識(shí)算法?

我們?cè)诙鄠€(gè)機(jī)器部署哨兵,它們需要共同協(xié)作完成一項(xiàng)任務(wù),所以它們就組成了一個(gè)「分布式系統(tǒng)」。

在分布式系統(tǒng)領(lǐng)域,多個(gè)節(jié)點(diǎn)如何就一個(gè)問(wèn)題達(dá)成共識(shí)的算法,就叫共識(shí)算法。

在這個(gè)場(chǎng)景下,多個(gè)哨兵共同協(xié)商,選舉出一個(gè)都認(rèn)可的領(lǐng)導(dǎo)者,就是使用共識(shí)算法完成的。

這個(gè)算法還規(guī)定節(jié)點(diǎn)的數(shù)量必須是奇數(shù)個(gè),這樣可以保證系統(tǒng)中即使有節(jié)點(diǎn)發(fā)生了故障,剩余超過(guò)「半數(shù)」的節(jié)點(diǎn)狀態(tài)正常,依舊可以提供正確的結(jié)果,也就是說(shuō),這個(gè)算法還兼容了存在故障節(jié)點(diǎn)的情況。

共識(shí)算法在分布式系統(tǒng)領(lǐng)域有很多,例如 Paxos、Raft,哨兵選舉領(lǐng)導(dǎo)者這個(gè)場(chǎng)景,使用的是 Raft 共識(shí)算法,因?yàn)樗銐蚝?jiǎn)單,且易于實(shí)現(xiàn)。

好,到這里我們先小結(jié)一下。

你的 Redis 從最簡(jiǎn)單的單機(jī)版,經(jīng)過(guò)數(shù)據(jù)持久化、主從多副本、哨兵集群,這一路優(yōu)化下來(lái),你的 Redis 不管是性能還是穩(wěn)定性,都越來(lái)越高,就算節(jié)點(diǎn)發(fā)生故障,也不用擔(dān)心了。

Redis 以這樣的架構(gòu)模式部署,基本上就可以穩(wěn)定運(yùn)行很長(zhǎng)時(shí)間了。

...

隨著時(shí)間的發(fā)展,你的業(yè)務(wù)體量開(kāi)始迎來(lái)了爆炸性增長(zhǎng),此時(shí)你的架構(gòu)模型,還能夠承擔(dān)這么大的流量嗎?

我們一起來(lái)分析一下:

  1. 數(shù)據(jù)怕丟失 :持久化(RDB/AOF)
  2. 恢復(fù)時(shí)間久 :主從副本(副本隨時(shí)可切)
  3. 手動(dòng)切換時(shí)間長(zhǎng) :哨兵集群(自動(dòng)切換)
  4. 讀存在壓力 :擴(kuò)容副本(讀寫(xiě)分離)
  5. 寫(xiě)存在壓力一個(gè) mater 扛不住怎么辦?

可見(jiàn),現(xiàn)在剩下的問(wèn)題是,當(dāng)寫(xiě)請(qǐng)求量越來(lái)越大時(shí),一個(gè) master 實(shí)例可能就無(wú)法承擔(dān)這么大的寫(xiě)流量了。

要想完美解決這個(gè)問(wèn)題,此時(shí)你就需要考慮使用「分片集群」了。

分片集群:橫向擴(kuò)展

什么是「分片集群」?

簡(jiǎn)單來(lái)講,一個(gè)實(shí)例扛不住寫(xiě)壓力,那我們是否可以部署多個(gè)實(shí)例,然后把這些實(shí)例按照一定規(guī)則組織起來(lái),把它們當(dāng)成一個(gè)整體,對(duì)外提供服務(wù),這樣不就可以解決集中寫(xiě)一個(gè)實(shí)例的瓶頸問(wèn)題嗎?

所以,現(xiàn)在的架構(gòu)模型就變成了這樣:

b4c47e96-31a0-11ee-9e74-dac502259ad0.jpg

現(xiàn)在問(wèn)題又來(lái)了,這么多實(shí)例如何組織呢?

我們制定規(guī)則如下:

  1. 每個(gè)節(jié)點(diǎn)各自存儲(chǔ)一部分?jǐn)?shù)據(jù),所有節(jié)點(diǎn)數(shù)據(jù)之和才是全量數(shù)據(jù)
  2. 制定一個(gè)路由規(guī)則,對(duì)于不同的 key,把它路由到固定一個(gè)實(shí)例上進(jìn)行讀寫(xiě)

數(shù)據(jù)分多個(gè)實(shí)例存儲(chǔ),那尋找 key 的路由規(guī)則需要放在客戶(hù)端來(lái)做,具體就是下面這樣:

b4cec5d6-31a0-11ee-9e74-dac502259ad0.jpg

這種方案也叫做「客戶(hù)端分片」,這個(gè)方案的缺點(diǎn)是,客戶(hù)端需要維護(hù)這個(gè)路由規(guī)則,也就是說(shuō),你需要把路由規(guī)則寫(xiě)到你的業(yè)務(wù)代碼中。

如何做到不把路由規(guī)則耦合在客戶(hù)端業(yè)務(wù)代碼中呢?

繼續(xù)優(yōu)化,我們可以在客戶(hù)端和服務(wù)端之間增加一個(gè)「中間代理層」,這個(gè)代理就是我們經(jīng)常聽(tīng)到的 Proxy,路由轉(zhuǎn)發(fā)規(guī)則,放在這個(gè) Proxy 層來(lái)維護(hù)。

這樣,客戶(hù)端就無(wú)需關(guān)心服務(wù)端有多少個(gè) Redis 節(jié)點(diǎn)了,只需要和這個(gè) Proxy 交互即可。

Proxy 會(huì)把你的請(qǐng)求根據(jù)路由規(guī)則,轉(zhuǎn)發(fā)到對(duì)應(yīng)的 Redis 節(jié)點(diǎn)上,而且,當(dāng)集群實(shí)例不足以支撐更大的流量請(qǐng)求時(shí),還可以橫向擴(kuò)容,添加新的 Redis 實(shí)例提升性能,這一切對(duì)于你的客戶(hù)端來(lái)說(shuō),都是透明無(wú)感知的。

業(yè)界開(kāi)源的 Redis 分片集群方案,例如 Twemproxy、Codis 就是采用的這種方案。

b4f7ef4c-31a0-11ee-9e74-dac502259ad0.jpg

這種方案的優(yōu)點(diǎn)在于,客戶(hù)端無(wú)需關(guān)心數(shù)據(jù)轉(zhuǎn)發(fā)規(guī)則,只需要和 Proxy 打交道,客戶(hù)端像操作單機(jī) Redis 那樣去操作后面的集群,簡(jiǎn)單易用。

架構(gòu)演進(jìn)到目前為止,路由規(guī)則無(wú)論是客戶(hù)端來(lái)做,還是 Proxy 來(lái)做,都是「社區(qū)」演進(jìn)出來(lái)的分片解決方案,它們的特點(diǎn)是集群中的 Redis 節(jié)點(diǎn),都不知道對(duì)方的存在,只有客戶(hù)端或 Proxy 才會(huì)統(tǒng)籌數(shù)據(jù)寫(xiě)到哪里,從哪里讀取,而且它們都依賴(lài)哨兵集群負(fù)責(zé)故障自動(dòng)切換。

也就是說(shuō)我們其實(shí)就是把多個(gè)孤立的 Redis 節(jié)點(diǎn),自己組合起來(lái)使用。

Redis 在 3.0 其實(shí)就推出了「官方」的 Redis Cluster 分片方案,但由于推出初期不穩(wěn)定,所以用的人很少,也因此業(yè)界涌現(xiàn)出了各種開(kāi)源方案,上面講到的 Twemproxy、Codis 分片方案就是在這種背景下誕生的。

但隨著 Redis Cluster 方案的逐漸成熟,業(yè)界越來(lái)越多的公司開(kāi)始采用官方方案(畢竟官方保證持續(xù)維護(hù),Twemproxy、Codis 目前都逐漸放棄維護(hù)了),Redis Cluster 方案比上面講到的分片方案更簡(jiǎn)單,它的架構(gòu)如下。

b51105d6-31a0-11ee-9e74-dac502259ad0.jpg

Redis Cluster 無(wú)需部署哨兵集群,集群內(nèi) Redis 節(jié)點(diǎn)通過(guò) Gossip 協(xié)議互相探測(cè)健康狀態(tài),在故障時(shí)可發(fā)起自動(dòng)切換。

另外,關(guān)于路由轉(zhuǎn)發(fā)規(guī)則,也不需要客戶(hù)端自己編寫(xiě)了,Redis Cluster 提供了「配套」的 SDK,只要客戶(hù)端升級(jí) SDK,就可以和 Redis Cluster 集成,SDK 會(huì)幫你找到 key 對(duì)應(yīng)的 Redis 節(jié)點(diǎn)進(jìn)行讀寫(xiě),還能自動(dòng)適配 Redis 節(jié)點(diǎn)的增加和刪除,業(yè)務(wù)側(cè)無(wú)感知。

雖然省去了哨兵集群的部署,維護(hù)成本降低了不少,但對(duì)于客戶(hù)端升級(jí) SDK,對(duì)于新業(yè)務(wù)應(yīng)用來(lái)說(shuō),可能成本不高,但對(duì)于老業(yè)務(wù)來(lái)講,「升級(jí)成本」還是比較高的,這對(duì)于切換官方 Redis Cluster 方案有不少阻力。

于是,各個(gè)公司有開(kāi)始自研針對(duì) Redis Cluster 的 Proxy,降低客戶(hù)端的升級(jí)成本,架構(gòu)就變成了這樣:

b52c4472-31a0-11ee-9e74-dac502259ad0.png

這樣,客戶(hù)端無(wú)需做任何變更,只需把連接地址切到 Proxy 上即可,由 Proxy 負(fù)責(zé)轉(zhuǎn)發(fā)數(shù)據(jù),以及應(yīng)對(duì)后面集群增刪節(jié)點(diǎn)帶來(lái)的路由變更。

至此,業(yè)界主流的 Redis 分片架構(gòu)已經(jīng)成型,當(dāng)你使用分片集群后,對(duì)于未來(lái)更大的流量壓力,也都可以從容面對(duì)了!

總結(jié)

總結(jié)一下,我們是如何從 0 到 1,再?gòu)?1 到 N 構(gòu)建一個(gè)穩(wěn)定、高性能的 Redis 集群的,從這之中你可以清晰地看到 Redis 架構(gòu)演進(jìn)的整個(gè)過(guò)程。

  1. 數(shù)據(jù)怕丟失 :持久化(RDB/AOF)
  2. 恢復(fù)時(shí)間久: 主從副本(副本隨時(shí)可切)
  3. 故障手動(dòng)切換慢 :哨兵集群(自動(dòng)切換)
  4. 讀存在壓力 :擴(kuò)容副本(讀寫(xiě)分離)
  5. 寫(xiě)存在壓力/容量瓶頸 :分片集群
  6. 分片集群社區(qū)方案 :Twemproxy、Codis(Redis 節(jié)點(diǎn)之間無(wú)通信,需要部署哨兵,可橫向擴(kuò)容)
  7. 分片集群官方方案 :Redis Cluster (Redis 節(jié)點(diǎn)之間 Gossip 協(xié)議,無(wú)需部署哨兵,可橫向擴(kuò)容)
  8. 業(yè)務(wù)側(cè)升級(jí)困難 :Proxy + Redis Cluster(不侵入業(yè)務(wù)側(cè))

至此,我們的 Redis 集群才得以長(zhǎng)期穩(wěn)定、高性能的為我們的業(yè)務(wù)提供服務(wù)。

希望這篇文章可以幫你更好的理解 Redis 架構(gòu)的演進(jìn)之路。


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 架構(gòu)
    +關(guān)注

    關(guān)注

    1

    文章

    528

    瀏覽量

    25987
  • 高性能
    +關(guān)注

    關(guān)注

    0

    文章

    220

    瀏覽量

    20940
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    387

    瀏覽量

    11448

原文標(biāo)題:Redis 架構(gòu)演化之路

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何使用Rust連接Redis

    Redis是一款快速、開(kāi)源、鍵值存儲(chǔ)數(shù)據(jù)庫(kù),被廣泛應(yīng)用于緩存、發(fā)布/訂閱系統(tǒng)、定時(shí)任務(wù)等場(chǎng)景中。Rust提供了很多Redis的客戶(hù)端庫(kù),本教程將會(huì)介紹如何使用Rust連接Redis,以及如何通過(guò)
    的頭像 發(fā)表于 09-19 16:22 ?2940次閱讀

    Redis Stream應(yīng)用案例

    互聯(lián)網(wǎng)服務(wù)中作為Cache和KV存儲(chǔ)廣泛應(yīng)用,Redis下一個(gè)大放異彩的領(lǐng)域也許就在物聯(lián)網(wǎng)。上面這個(gè)圖,就是一個(gè)典型的物聯(lián)網(wǎng)設(shè)備信息采集,分析,展示的架構(gòu)。Redis作為一個(gè)嵌入式的存儲(chǔ)系統(tǒng)跑在各個(gè)
    發(fā)表于 06-26 17:15

    redis概述

    REmote DIctionary Server(Redis)是一個(gè)基于key-value鍵值對(duì)的持久化數(shù)據(jù)庫(kù)存儲(chǔ)系統(tǒng)。redis和大名鼎鼎的Memcached緩存服務(wù)軟件很像,但是redis支持
    發(fā)表于 07-17 07:38

    Redis Cluster的基本原理及實(shí)現(xiàn)細(xì)節(jié)

    Redis Cluster的基本原理和架構(gòu) Redis Cluster是分布式Redis的實(shí)現(xiàn)。隨著Redis版本的更替,以及各種已知bug
    發(fā)表于 09-28 19:09 ?0次下載
    <b class='flag-5'>Redis</b> Cluster的基本原理及實(shí)現(xiàn)細(xì)節(jié)

    Redis混合存儲(chǔ)產(chǎn)品與架構(gòu)介紹

    左右,相比業(yè)界同類(lèi)引擎性能有80%提升。整體架構(gòu)存儲(chǔ)模型在Redis混合存儲(chǔ)實(shí)例中,我們將所有的Key和經(jīng)常訪問(wèn)的Value保留在內(nèi)存中,將不經(jīng)常訪問(wèn)的Value保存在磁盤(pán)上。之所以在內(nèi)存中保留所有
    發(fā)表于 08-30 16:09 ?250次閱讀

    如何構(gòu)建一個(gè)穩(wěn)定、高性能的Redis集群?

    這篇文章我想和你聊一聊 Redis架構(gòu)演化之路。 現(xiàn)如今 Redis 變得越來(lái)越流行,幾乎在很多項(xiàng)目中都要被用到,不知道你在使用
    的頭像 發(fā)表于 03-03 15:05 ?1822次閱讀
    如何構(gòu)建一個(gè)穩(wěn)定、高性能的<b class='flag-5'>Redis</b>集群?

    華為云推出云原生分布式數(shù)據(jù)庫(kù)GaussDB(for Redis)

    華為云開(kāi)發(fā)者社區(qū)聯(lián)合華為云數(shù)據(jù)庫(kù)架構(gòu)與規(guī)劃團(tuán)隊(duì)聯(lián)合出品,與開(kāi)發(fā)者分享華為云GaussDB(for Redis)十年自研內(nèi)核修煉之路。包括GaussDB(for Redis)
    的頭像 發(fā)表于 04-20 09:51 ?1868次閱讀

    Redis基礎(chǔ)架構(gòu)設(shè)計(jì)及核心網(wǎng)絡(luò)模型架構(gòu)演進(jìn)

    性能優(yōu)異的服務(wù)離不開(kāi)好的架構(gòu)設(shè)計(jì),Redis使用 I/O multiplexing 實(shí)現(xiàn)了單線程接收海量客戶(hù)端請(qǐng)求;通過(guò)單線程Reactor模型實(shí)現(xiàn)了高性能的事件處理
    發(fā)表于 10-11 15:08 ?584次閱讀

    什么是電子電氣架構(gòu)?電氣架構(gòu)指導(dǎo)系統(tǒng)設(shè)計(jì)和演化的原理

    總結(jié)來(lái)說(shuō),電氣架構(gòu)是整車(chē)電氣系統(tǒng)的基本結(jié)構(gòu),它包括功能,系統(tǒng),組成系統(tǒng)的零件,零件與零件之間的相互關(guān)系,零件與環(huán)境之間的關(guān)系,以及指導(dǎo)系統(tǒng)設(shè)計(jì)和演化的原理。
    發(fā)表于 04-06 11:05 ?2468次閱讀

    什么是 Redis

    ? — ? 1 ?— 什么是 Redis? Redis(REmote DIctionary Service)是一個(gè)開(kāi)源的鍵值對(duì)數(shù)據(jù)庫(kù)服務(wù)器。 Redis 更準(zhǔn)確的描述是一個(gè)數(shù)據(jù)結(jié)構(gòu)服務(wù)器。Re
    的頭像 發(fā)表于 05-22 15:32 ?1417次閱讀
    什么是 <b class='flag-5'>Redis</b>

    Redis的主從、哨兵、Redis Cluster集群

    ? 前言 今天跟小伙伴們一起學(xué)習(xí)Redis的主從、哨兵、Redis Cluster集群。 Redis主從 Redis哨兵 Redis Clu
    的頭像 發(fā)表于 06-12 14:58 ?1097次閱讀
    <b class='flag-5'>Redis</b>的主從、哨兵、<b class='flag-5'>Redis</b> Cluster集群

    如何用Springboot整合Redis

    本篇文件我們來(lái)介紹如何用Springboot整合Redis。 1、Docker 安裝 Redis 1.1 下載鏡像 docker pull redis: 6 . 2 . 6 1.2 創(chuàng)建配置文件
    的頭像 發(fā)表于 10-08 14:56 ?837次閱讀
    如何用Springboot整合<b class='flag-5'>Redis</b>

    redis容器內(nèi)怎么查看redis日志

    redis是一款流行的開(kāi)源內(nèi)存數(shù)據(jù)庫(kù),常用于緩存、消息隊(duì)列、任務(wù)管理等場(chǎng)景。在使用redis時(shí),了解如何查看redis日志對(duì)于排查問(wèn)題、監(jiān)控性能和分析應(yīng)用程序行為非常重要。在本文中,我們將介紹在
    的頭像 發(fā)表于 12-05 10:10 ?4765次閱讀

    Redis開(kāi)源版與Redis企業(yè)版,怎么選用?

    Redis開(kāi)源版,二者有何不同?該如何選擇?一、Redis企業(yè)版Redis企業(yè)版基于開(kāi)源Redis構(gòu)建,企業(yè)版將開(kāi)發(fā)人員、架構(gòu)師和DevO
    的頭像 發(fā)表于 04-04 08:04 ?1580次閱讀
    <b class='flag-5'>Redis</b>開(kāi)源版與<b class='flag-5'>Redis</b>企業(yè)版,怎么選用?

    Redis是怎么從單體架構(gòu)發(fā)展到分布式緩存的?

    Redis 架構(gòu)是如何一步一步發(fā)展到今天的樣子的?
    的頭像 發(fā)表于 04-20 15:37 ?1058次閱讀
    <b class='flag-5'>Redis</b>是怎么從單體<b class='flag-5'>架構(gòu)</b>發(fā)展到分布式緩存的?