亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Redis中常見的幾種集群部署方案

 更新時(shí)間:2022年03月07日 09:22:46   作者:Zhan-LiZ  
本文主要介紹了Redis中常見的幾種集群部署方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

這里來(lái)了解一下,Redis 中常見的集群方案

幾種常用的集群方案

  • 主從集群模式
  • 哨兵機(jī)制
  • 切片集群(分片集群)

主從集群模式

主從集群,主從庫(kù)之間采用的是讀寫分離

  • 主庫(kù):所有的寫操作都在讀庫(kù)發(fā)生,然后主庫(kù)同步數(shù)據(jù)到從庫(kù),同時(shí)也可以進(jìn)行讀操作;
  • 從庫(kù):只負(fù)責(zé)讀操作;

主庫(kù)需要復(fù)制數(shù)據(jù)到從庫(kù),主從雙方的數(shù)據(jù)庫(kù)需要保存相同的數(shù)據(jù),將這種情況稱為"數(shù)據(jù)庫(kù)狀態(tài)一致"

來(lái)看下如何同步之前先來(lái)了解下幾個(gè)概念

1、服務(wù)器的運(yùn)行ID(run ID):每個(gè) Redis 服務(wù)器在運(yùn)行期間都有自己的run IDrun ID在服務(wù)器啟動(dòng)的時(shí)候自動(dòng)生成。

從服務(wù)器會(huì)記錄主服務(wù)器的run ID,這樣如果發(fā)生斷網(wǎng)重連,就能判斷新連接上的主服務(wù)器是不是上次的那一個(gè),這樣來(lái)決定是否進(jìn)行數(shù)據(jù)部分重傳還是完整重新同步。

2、復(fù)制偏移量 offset:主服務(wù)器和從服務(wù)器都會(huì)維護(hù)一個(gè)復(fù)制偏移量

主服務(wù)器每次向從服務(wù)器中傳遞 N 個(gè)字節(jié)的時(shí)候,會(huì)將自己的復(fù)制偏移量加上 N。

從服務(wù)器中收到主服務(wù)器的 N 個(gè)字節(jié)的數(shù)據(jù),就會(huì)將自己額復(fù)制偏移量加上 N。

通過(guò)主從服務(wù)器的偏移量對(duì)比可以很清楚的知道主從服務(wù)器的數(shù)據(jù)是否處于一致。

如果不一致就需要進(jìn)行增量同步了,具體參加下文的增量同步

全量同步

從服務(wù)器首次加入主服務(wù)器中發(fā)生的是全量同步

如何進(jìn)行第一次同步?

1、從服務(wù)器連接到主服務(wù)器,然后發(fā)送 psync 到主服務(wù)器,因?yàn)榈谝淮螐?fù)制,不知道主庫(kù)run ID,所以run ID為?;

2、主服務(wù)器接收到同步的響應(yīng),回復(fù)從服務(wù)器自己的run ID和復(fù)制進(jìn)行進(jìn)度 offset;

3、主服務(wù)器開始同步所有數(shù)據(jù)到從庫(kù)中,同步依賴 RDB 文件,主庫(kù)會(huì)通過(guò) bgsave 命令,生成 RDB 文件,然后將 RDB 文件傳送到從庫(kù)中;

4、從庫(kù)收到 RDB 文件,清除自己的數(shù)據(jù),然后載入 RDB 文件;

5、主庫(kù)在同步的過(guò)程中不會(huì)被阻塞,仍然能接收到命令,但是新的命令是不能同步到從庫(kù)的,所以主庫(kù)會(huì)在內(nèi)存中用專門的 replication buffer,記錄 RDB 文件生成后收到的所有寫操作,然后在 RDB 文件,同步完成之后,再將replication buffer中的命令發(fā)送到從庫(kù)中,這樣就保證了從庫(kù)的數(shù)據(jù)同步。

增量同步

如果主從服務(wù)器之間發(fā)生了網(wǎng)絡(luò)閃斷,從從服務(wù)將會(huì)丟失一部分同步的命令。

在舊版本,Redis 2.8之前,如果發(fā)生了網(wǎng)絡(luò)閃斷,就會(huì)進(jìn)行一次全量復(fù)制。

在 2.8 版本之后,引入了增量同步的技術(shù),這里主要是用到了 repl_backlog_buffer

Redis 主庫(kù)接收到寫操作的命令,首先會(huì)寫入replication buffer(主要用于主從數(shù)據(jù)傳輸?shù)臄?shù)據(jù)緩沖),同時(shí)也會(huì)把這些操作命令也寫入repl_backlog_buffer這個(gè)緩沖區(qū)。

這里可能有點(diǎn)疑惑,已經(jīng)有了replication buffer為什么還多余引入一個(gè)repl_backlog_buffer呢?

  • repl_backlog_buffer一個(gè)主庫(kù)對(duì)應(yīng)一個(gè)repl_backlog_buffer,也就是所有從庫(kù)對(duì)應(yīng)一個(gè)repl_backlog_buffer,從庫(kù)自己記錄自己的slave_repl_offset。
  • replication buffer用于主節(jié)點(diǎn)與各個(gè)從節(jié)點(diǎn)間,數(shù)據(jù)的批量交互。主節(jié)點(diǎn)為各個(gè)從節(jié)點(diǎn)分別創(chuàng)建一個(gè)緩沖區(qū),由于各個(gè)從節(jié)點(diǎn)的處理能力差異,各個(gè)緩沖區(qū)數(shù)據(jù)可能不同。

如何主從斷開了,當(dāng)然對(duì)應(yīng)的replication buffer也就沒(méi)有了。這時(shí)候就依賴repl_backlog_buffer進(jìn)行數(shù)據(jù)的增量同步了。

repl_backlog_buffer是一個(gè)環(huán)形緩沖區(qū),主庫(kù)會(huì)記錄自己寫到的位置,從庫(kù)則會(huì)記錄自己已經(jīng)讀到的位置。

這里借用Redis核心技術(shù)與實(shí)戰(zhàn)的一張圖片

剛開始主服務(wù)器的 master_repl_offset 和從服務(wù)器 slave_repl_offset 的位置是一樣的,在從庫(kù)因?yàn)榫W(wǎng)絡(luò)原因斷連之后,隨著主庫(kù)寫操作的進(jìn)行,主從偏移量會(huì)出現(xiàn)偏移距離。

當(dāng)從服務(wù)器連上主服務(wù)器之后,從服務(wù)把自己當(dāng)前的 slave_repl_offset 告訴主服務(wù)器,然后主服務(wù)器根據(jù)自己的 master_repl_offset 計(jì)算出和從服務(wù)器之間的差距,然后把兩者之間相差的命令操作同步給從服務(wù)器。

舉個(gè)栗子

比如這里從服務(wù)器1,剛剛由于網(wǎng)絡(luò)原因斷連了一會(huì),然后又恢復(fù)了連接,這時(shí)候,可能缺失了一段時(shí)間的命令同步,repl_backlog_buffer的增量同步機(jī)制就登場(chǎng)了。

repl_backlog_buffer會(huì)根據(jù)主服務(wù)器的master_repl_offset和從服務(wù)器slave_repl_offset,計(jì)算出兩者命令之間的差距,之后把差距同步給replication buffer,然后發(fā)送到從服務(wù)器中。

repl_backlog_buffer中的緩沖空間要設(shè)置的大一點(diǎn),如果從庫(kù)讀的過(guò)慢,因?yàn)槭黔h(huán)形緩沖區(qū),可能出現(xiàn)命令覆蓋的情況,如果出現(xiàn)命令被覆蓋了,從庫(kù)的增量同步就無(wú)法進(jìn)行了,這時(shí)候會(huì)進(jìn)行一次全量的復(fù)制。

緩沖空間的計(jì)算公式是:緩沖空間大小 = 主庫(kù)寫入命令速度 * 操作大小 - 主從庫(kù)間網(wǎng)絡(luò)傳輸命令速度 * 操作大小。在實(shí)際應(yīng)用中,考慮到可能存在一些突發(fā)的請(qǐng)求壓力,我們通常需要把這個(gè)緩沖空間擴(kuò)大一倍,即 repl_backlog_size = 緩沖空間大小 * 2,這也就是 repl_backlog_size 的最終值。

哨兵機(jī)制

對(duì)于主從集群模式,如果從庫(kù)發(fā)生了故障,還有主庫(kù)和其它的從庫(kù)可以接收請(qǐng)求,但是如果主庫(kù)掛了,就不能進(jìn)行正常的數(shù)據(jù)寫入,同時(shí)數(shù)據(jù)同步也不能正常的進(jìn)行了,當(dāng)然這種情況,我們需要想辦法避免,于是就引入了下面的哨兵機(jī)制。

什么是哨兵機(jī)制

sentinel(哨兵機(jī)制):是 Redis 中集群的高可用方式,哨兵節(jié)點(diǎn)是特殊的 Redis 服務(wù),不提供讀寫,主要來(lái)監(jiān)控 Redis 中的實(shí)例節(jié)點(diǎn),如果監(jiān)控服務(wù)的主服務(wù)器下線了,會(huì)從所屬的從服務(wù)器中重新選出一個(gè)主服務(wù)器,代替原來(lái)的主服務(wù)器提供服務(wù)。

核心功能就是:監(jiān)控,選主,通知。

監(jiān)控:哨兵機(jī)制,會(huì)周期性的給所有主服務(wù)器發(fā)出 PING 命令,檢測(cè)它們是否仍然在線運(yùn)行,如果在規(guī)定的時(shí)間內(nèi)響應(yīng)了 PING 通知?jiǎng)t認(rèn)為,仍在線運(yùn)行;如果沒(méi)有及時(shí)回復(fù),則認(rèn)為服務(wù)已經(jīng)下線了,就會(huì)進(jìn)行切換主庫(kù)的動(dòng)作。

選主:當(dāng)主庫(kù)掛掉的時(shí)候,會(huì)從從庫(kù)中按照既定的規(guī)則選出一個(gè)新的的主庫(kù),

通知:當(dāng)一個(gè)主庫(kù)被新選出來(lái),會(huì)通知其他從庫(kù),進(jìn)行連接,然后進(jìn)行數(shù)據(jù)的復(fù)制。當(dāng)客戶端試圖連接失效的主庫(kù)時(shí),集群也會(huì)向客戶端返回新主庫(kù)的地址,使得集群可以使用新的主庫(kù)。

如何保證選主的準(zhǔn)確性

哨兵會(huì)通過(guò) PING 命令檢測(cè)它和從庫(kù),主庫(kù)之間的連接情況,如果發(fā)現(xiàn)響應(yīng)超時(shí)就會(huì)認(rèn)為給服務(wù)已經(jīng)下線了。

當(dāng)然這會(huì)存在誤判的情況,如果集群的網(wǎng)絡(luò)壓力比較大,網(wǎng)路堵塞,這時(shí)候會(huì)存在誤判的情況。

如果誤判的節(jié)點(diǎn)是從節(jié)點(diǎn),影響不會(huì)很大,拿掉一個(gè)從節(jié)點(diǎn),對(duì)整體的服務(wù),影響不大,還是會(huì)不間斷的對(duì)外提供服務(wù)。

如果誤判的節(jié)點(diǎn)是主節(jié)點(diǎn),影響就很大了,主節(jié)點(diǎn)被標(biāo)注下線了,就會(huì)觸發(fā)后續(xù)的選主,數(shù)據(jù)同步,等一連串的動(dòng)作,這一連串的動(dòng)作很很消耗性能的。所以對(duì)于誤判,應(yīng)該去規(guī)避。

如何減少誤判呢?

引入哨兵集群,一個(gè)哨兵節(jié)點(diǎn)可能會(huì)進(jìn)行誤判,引入多個(gè)少哨兵節(jié)點(diǎn)一起做決策,就能減少誤判了。

當(dāng)有多個(gè)哨兵節(jié)點(diǎn)的時(shí)候,大多數(shù)哨兵節(jié)點(diǎn)認(rèn)為主庫(kù)下線了,主庫(kù)才會(huì)真正的被標(biāo)記為下線了,一般來(lái)講當(dāng)有 N 個(gè)哨兵實(shí)例時(shí),最好要有N/2 + 1個(gè)實(shí)例判斷主庫(kù)下線了,才能最終判定主庫(kù)的下線狀態(tài)。當(dāng)然這個(gè)數(shù)值在 Redis 中是可以配置的。

如何選主

選舉主節(jié)點(diǎn)的規(guī)則

1、過(guò)濾掉已經(jīng)下線的服務(wù)器;

2、過(guò)濾掉最近5秒鐘沒(méi)有回復(fù)過(guò)主節(jié)點(diǎn)的 INFO(用于觀察服務(wù)器的角色) 命令的服務(wù)器,保證選中的服務(wù)器都是最近成功通過(guò)信的;

3、過(guò)濾掉和下線主服務(wù)器連接超過(guò)down-after-milliseconds*10毫秒的從服務(wù)器,down-after-milliseconds是主服務(wù)器下線的時(shí)間,這一操作避免從服務(wù)器與主服務(wù)器過(guò)早的斷開,影響到從庫(kù)中數(shù)據(jù)同步,因?yàn)閿嚅_時(shí)間越久,從庫(kù)里面的數(shù)據(jù)就越老舊過(guò)時(shí)。

然后對(duì)這些服務(wù)器根據(jù)slave-priority優(yōu)先級(jí)(這個(gè)優(yōu)先級(jí)是手動(dòng)設(shè)置的,比如希望那個(gè)從服務(wù)器優(yōu)先變成主服務(wù)器,優(yōu)先級(jí)就設(shè)置的高一點(diǎn)) 進(jìn)行排序。

如果幾臺(tái)從服務(wù)器優(yōu)先級(jí)相同,然后根據(jù)復(fù)制偏移量從大到小進(jìn)行排序,如果還有相同偏移量的從服務(wù)器,然后按照 runID 從小到大進(jìn)行排序,直到選出一臺(tái)從服務(wù)器。

哨兵進(jìn)行主節(jié)點(diǎn)切換

當(dāng)根據(jù)選舉規(guī)則,選出了可以成為主節(jié)點(diǎn)的從節(jié)點(diǎn),如何進(jìn)行切換呢?

在哨兵中也是有一個(gè) Leader 節(jié)點(diǎn)的,當(dāng)一個(gè)從庫(kù)被選舉出來(lái),從庫(kù)的切換是由 Leader 節(jié)點(diǎn)完成的。

Leader 節(jié)點(diǎn)的選舉用的是 Raft 算法,關(guān)于什么是 Raft 算法可參考Raft一致性算法原理

在raft算法中,在任何時(shí)刻,每一個(gè)服務(wù)器節(jié)點(diǎn)都處于這三個(gè)狀態(tài)之一:

  • Follower:追隨者,跟隨者都是被動(dòng)的:他們不會(huì)發(fā)送任何請(qǐng)求,只是簡(jiǎn)單的響應(yīng)來(lái)自領(lǐng)導(dǎo)者或者候選人的請(qǐng)求;
  • Candidate:候選人,如果跟隨者接收不到消息,那么他就會(huì)變成候選人并發(fā)起一次選舉,獲得集群中大多數(shù)選票的候選人將成為領(lǐng)導(dǎo)者。
  • Leader:領(lǐng)導(dǎo)者,系統(tǒng)中只有一個(gè)領(lǐng)導(dǎo)人并且其他的節(jié)點(diǎn)全部都是跟隨者,領(lǐng)導(dǎo)人處理所有的客戶端請(qǐng)求(如果一個(gè)客戶端和跟隨者聯(lián)系,那么跟隨者會(huì)把請(qǐng)求重定向給領(lǐng)導(dǎo)人)

哨兵節(jié)點(diǎn)的選舉總結(jié)起來(lái)就是:

1、每個(gè)做主觀下線的sentinel節(jié)點(diǎn)向其他sentinel節(jié)點(diǎn)發(fā)送命令,要求將自己設(shè)置為領(lǐng)導(dǎo)者;

2、接收到的sentinel可以同意或者拒絕;

3、如果該sentinel節(jié)點(diǎn)發(fā)現(xiàn)自己的票數(shù)已經(jīng)超過(guò)半數(shù)并且超過(guò)了 quorum,quorum 用來(lái)配置判斷主節(jié)點(diǎn)宕機(jī)的哨兵節(jié)點(diǎn)數(shù)。簡(jiǎn)單點(diǎn)講就是:如果 Sentinel 集群有 quorum 個(gè)哨兵認(rèn)為 master 宕機(jī)了,就「客觀」的認(rèn)為 master 宕機(jī)了;

4、如果此過(guò)程選舉出了多個(gè)領(lǐng)導(dǎo)者,那么將等待一段時(shí)重新進(jìn)行選舉;

故障轉(zhuǎn)移

  • sentinel的領(lǐng)導(dǎo)者從從機(jī)中選舉出合適的叢機(jī)進(jìn)行故障轉(zhuǎn)移;
  • 對(duì)選取的從節(jié)點(diǎn)進(jìn)行slave of no one命令,(這個(gè)命令用來(lái)讓從機(jī)關(guān)閉復(fù)制功能,并從從機(jī)變?yōu)橹鳈C(jī));
  • 更新應(yīng)用程序端的鏈接到新的主節(jié)點(diǎn);
  • 對(duì)其他從節(jié)點(diǎn)變更 master 為新的節(jié)點(diǎn);
  • 修復(fù)原來(lái)的 master 并將其設(shè)置為新的 master 的從機(jī)。

消息通知

哨兵和哨兵之前,哨兵和從庫(kù)之間,哨兵和客戶端是如何相互發(fā)現(xiàn),進(jìn)行消息傳遞?

哨兵和哨兵之間的相互發(fā)現(xiàn),通過(guò) Redis 提供的pub/sub機(jī)制實(shí)現(xiàn),因?yàn)槊總€(gè)哨兵節(jié)點(diǎn)都會(huì)和主庫(kù)進(jìn)行連接,通過(guò)在主庫(kù)中發(fā)布信息,訂閱信息,就能找到其他實(shí)例的連接信息。

哨兵節(jié)點(diǎn)和從庫(kù),通過(guò)哨兵向主庫(kù)發(fā)送 INFO 命令來(lái)完成,哨兵給主庫(kù)發(fā)送 INFO 命令,主庫(kù)接受到這個(gè)命令后,就會(huì)把從庫(kù)列表返回給哨兵。接著,哨兵就可以根據(jù)從庫(kù)列表中的連接信息,和每個(gè)從庫(kù)建立連接,并在這個(gè)連接上持續(xù)地對(duì)從庫(kù)進(jìn)行監(jiān)控。

哨兵和客戶端之間:每個(gè)哨兵實(shí)例也提供pub/sub機(jī)制,客戶端可以從哨兵訂閱消息,來(lái)獲知主從庫(kù)切換過(guò)程中的不同關(guān)鍵事件。

哨兵提升一個(gè)從庫(kù)為新主庫(kù)后,哨兵會(huì)把新主庫(kù)的地址寫入自己實(shí)例的 pubsub(switch-master) 中??蛻舳诵枰嗛嗊@ 個(gè)pubsub,當(dāng)這個(gè) pubsub 有數(shù)據(jù)時(shí),客戶端就能感知到主庫(kù)發(fā)生變更,同時(shí)可以拿到最新的主庫(kù)地址,然后把寫請(qǐng)求寫到這個(gè)新主庫(kù)即可,這種機(jī)制屬于哨兵主動(dòng)通知客戶端。

如果客戶端因?yàn)槟承┰蝈e(cuò)過(guò)了哨兵的通知,或者哨兵通知后客戶端處理失敗了,安全起見,客戶端也需要支持主動(dòng)去獲取最新主從的地址進(jìn)行訪問(wèn)。

切片集群

對(duì)于數(shù)據(jù)庫(kù)我們知道,如果數(shù)據(jù)量大會(huì)進(jìn)行分庫(kù)分表,一般有兩種方案縱向拆分和橫向拆分。這在 Redis 中,同樣適用。

Redis 中的擴(kuò)展

  • 縱向擴(kuò)展:更改節(jié)點(diǎn)類型以調(diào)整集群大小,升級(jí)單個(gè)Redis實(shí)例的資源配置,包括增加內(nèi)存容量、增加磁盤容量、使用更高配置的CPU。
  • 橫向擴(kuò)展:通過(guò)添加或刪除節(jié)點(diǎn)組(分片)來(lái)更改復(fù)制組中的節(jié)點(diǎn)組(分片)數(shù)量。

簡(jiǎn)單點(diǎn)講就是:垂直擴(kuò)容就是增加自身的容量,橫向擴(kuò)容就是加機(jī)器。

缺點(diǎn)對(duì)比

縱向擴(kuò)容:

1、如果一味的增加自身的容量,意味著自身存儲(chǔ)的數(shù)據(jù)將會(huì)越來(lái)越大,過(guò)大的數(shù)據(jù),持久化時(shí)間將會(huì)變得很長(zhǎng),影響自身的響應(yīng)速度;

2、同樣堆硬件總歸是有上線,達(dá)到一定量之后,還是要考慮進(jìn)行橫向擴(kuò)容;

橫向擴(kuò)容:

橫向擴(kuò)容要面臨的問(wèn)題,如果發(fā)生了分片的擴(kuò)容,就需要考慮數(shù)據(jù)的遷移,同時(shí)數(shù)據(jù)切片后,在多個(gè)實(shí)例之間如何分布?,客戶端如何知道訪問(wèn)的數(shù)據(jù)在哪個(gè)實(shí)例中。。。

雖然有這些問(wèn)題的存在,好在已經(jīng)有一些成熟的方案來(lái)處理橫向擴(kuò)容所遇到的問(wèn)題了

官方的集群解決方案就是Redis Cluster;社區(qū)的解決方案有 Codis 和 Twemproxy,Codis 是由我國(guó)的豌豆莢團(tuán)隊(duì)開源的,Twemproxy 是 Twitter 團(tuán)隊(duì)的開源的。

這里主要看下Redis Cluster是如何進(jìn)行處理的

Redis Cluster方案

1、Redis Cluster方案采用哈希槽來(lái)處理 KEY 在不同實(shí)例中的分布,一個(gè)切片集群共有16384個(gè)哈希槽,這些哈希槽類似于數(shù)據(jù)分區(qū),每個(gè)鍵值對(duì)都會(huì)根據(jù)它的key,被映射到一個(gè)哈希槽中。

2、一個(gè) KEY ,首先會(huì)根據(jù)CRC16算法計(jì)算一個(gè)16 bit的值;然后,再用這個(gè) 16bit 值對(duì) 16384 取模,得到0~16383范圍內(nèi)的模數(shù),每個(gè)模數(shù)代表一個(gè)相應(yīng)編號(hào)的哈希槽。

3、然后把哈希槽分配到所有的實(shí)例中,例如,如果集群中有N個(gè)實(shí)例,那么,每個(gè)實(shí)例上的槽個(gè)數(shù)為16384/N個(gè)。

當(dāng)然這是平均分配的,如果平均分配額哈希槽中,某一個(gè)實(shí)例中 KEY,存儲(chǔ)的數(shù)據(jù)比較大,造成某一個(gè)實(shí)例的內(nèi)存過(guò)大,這時(shí)候可以通過(guò)cluster addslots手動(dòng)調(diào)節(jié)哈希槽的分配。

當(dāng)手動(dòng)分配哈希槽時(shí),需要把16384個(gè)槽都分配完,否則Redis集群無(wú)法正常工作。

客戶端中的 KEY 如何找到對(duì)應(yīng)的實(shí)例

在集群剛剛創(chuàng)建的時(shí)候,每個(gè)實(shí)例只知道自己被分配了哪些哈希槽,是不知道其他實(shí)例擁有的哈希槽信息的。但是,Redis 實(shí)例會(huì)把自己的哈希槽信息發(fā)給和它相連接的其它實(shí)例,來(lái)完成哈希槽分配信息的擴(kuò)散。

所以當(dāng)客戶端和集群實(shí)例連接后,就可以知道所有的哈希槽的映射,客戶端會(huì)把哈希槽的映射保存在本地,這樣如果客戶端響應(yīng)一個(gè) KEY ,計(jì)算出哈希槽,然后就可以向?qū)?yīng)的實(shí)例發(fā)送請(qǐng)求了。

哈希槽重新分配

數(shù)據(jù)在可能發(fā)生遷移,這時(shí)候哈希槽就會(huì)重新分配了

栗如:

1、集群中的實(shí)例,有增加或減少;

2、引入了負(fù)載均衡,需要重新分配哈希槽;

因?yàn)橹匦路峙淞斯2?,所以原?lái)的映射關(guān)系可能發(fā)生了改變,實(shí)例之間可以通過(guò)相互通知,快速的感知到映射關(guān)系的變化。但是,客戶端無(wú)法主動(dòng)感知這些變化,客戶端對(duì) KEY 的響應(yīng),可能依舊映射到了之前的實(shí)例節(jié)點(diǎn),面對(duì)這種情況,如何處理呢?

1、如果數(shù)據(jù)已經(jīng)遷移完了

Redis Cluster中提供重定向機(jī)制,如果一個(gè)實(shí)例接收到客戶端的請(qǐng)求,但是對(duì)應(yīng)的 KEY 已經(jīng)轉(zhuǎn)移到別的實(shí)例節(jié)點(diǎn)中了,這時(shí)候會(huì)計(jì)算出 KEY 當(dāng)前所處實(shí)例的地址,然后返回給客戶端,客戶端拿到最新的實(shí)例地址,重新發(fā)送請(qǐng)求就可以了。

$ GET hello
(error) MOVED 12320 172.168.56.111:6379

2、數(shù)據(jù)遷移了一半

如果在遷移的過(guò)程中,只遷移了一半的數(shù)據(jù),這時(shí)候服務(wù)器端就會(huì)返回 ASK 告知客戶端

GET hello
(error) ASK 1332 012320 172.168.56.111:6379

ASK 就表示當(dāng)前正在遷移中,客戶端需要訪問(wèn)數(shù)據(jù),就還需要向返回的地址信息,發(fā)送一條 ASKING 命令,讓這個(gè)實(shí)例允許客戶端的訪問(wèn)請(qǐng)求,然后客戶端再發(fā)送具體的業(yè)務(wù)操作命令。

避免 Hot Key

Hot Key就是采用切片集群部署的 Redis ,出現(xiàn)的集群訪問(wèn)傾斜。

切片集群中的 Key 最終會(huì)存儲(chǔ)到集群中的一個(gè)固定的 Redis 實(shí)例中。某一個(gè) Key 在一段時(shí)間內(nèi)訪問(wèn)遠(yuǎn)高于其它的 Key,也就是該 Key 對(duì)應(yīng)的 Redis 實(shí)例,會(huì)收到過(guò)大的流量請(qǐng)求,該實(shí)例容易出現(xiàn)過(guò)載和卡頓現(xiàn)象,甚至還會(huì)被打掛掉。

常見引發(fā)熱點(diǎn) Key 的情況:

1、新聞中的熱點(diǎn)事件;

2、秒殺活動(dòng)中的,性價(jià)比高的商品;

如何發(fā)現(xiàn) Hot Key

1、提現(xiàn)預(yù)判;

根據(jù)業(yè)務(wù)經(jīng)驗(yàn)進(jìn)行提前預(yù)判;

2、在客戶端進(jìn)行收集;

通過(guò)在客戶端增加命令的采集,來(lái)統(tǒng)計(jì)發(fā)現(xiàn)熱點(diǎn) Key;

3、使用 Redis 自帶的命令排查;

使用monitor命令統(tǒng)計(jì)熱點(diǎn)key(不推薦,高并發(fā)條件下會(huì)有造成redis 內(nèi)存爆掉的隱患);

hotkeys參數(shù),redis 4.0.3提供了redis-cli的熱點(diǎn)key發(fā)現(xiàn)功能,執(zhí)行redis-cli時(shí)加上–hotkeys選項(xiàng)即可。但是該參數(shù)在執(zhí)行的時(shí)候,如果key比較多,執(zhí)行起來(lái)比較慢。

4、在Proxy層做收集

如果集群架構(gòu)引入了 proxy,可以在 proxy 中做統(tǒng)計(jì)

5、自己抓包評(píng)估

Redis客戶端使用TCP協(xié)議與服務(wù)端進(jìn)行交互,通信協(xié)議采用的是RESP。自己寫程序監(jiān)聽端口,按照RESP協(xié)議規(guī)則解析數(shù)據(jù),進(jìn)行分析。缺點(diǎn)就是開發(fā)成本高,維護(hù)困難,有丟包可能性。

Hot Key 如何解決

知道了Hot Key如何來(lái)應(yīng)對(duì)呢

1、對(duì) Key 進(jìn)行分散處理;

舉個(gè)栗子

有一個(gè)熱 Key 名字為Hot-key-test,可以將其分散為Hot-key-test1Hot-key-test2...然后將這些 Key 分散到多個(gè)實(shí)例節(jié)點(diǎn)中,當(dāng)客戶端進(jìn)行訪問(wèn)的時(shí)候,隨機(jī)一個(gè)下標(biāo)的 Key 進(jìn)行訪問(wèn),這樣就能將流量分散到不同的實(shí)例中了,避免了一個(gè)緩存節(jié)點(diǎn)的過(guò)載。

一般來(lái)講,可以通過(guò)添加后綴或者前綴,把一個(gè) hotkey 的數(shù)量變成 redis 實(shí)例個(gè)數(shù) N 的倍數(shù) M,從而由訪問(wèn)一個(gè)redis key變成訪問(wèn)N * M個(gè)redis key。 N*M個(gè)redis key經(jīng)過(guò)分片分布到不同的實(shí)例上,將訪問(wèn)量均攤到所有實(shí)例。

const M = N * 2
//生成隨機(jī)數(shù)
random = GenRandom(0, M)
//構(gòu)造備份新key
bakHotKey = hotKey + “_” + random
data = redis.GET(bakHotKey)
if data == NULL {
    data = GetFromDB()
    redis.SET(bakHotKey, expireTime + GenRandom(0,5))
}

2、使用本地緩存;

業(yè)務(wù)端還可以使用本地緩存,將這些熱 key 記錄在本地緩存,來(lái)減少對(duì)遠(yuǎn)程緩存的沖擊。

避免 Big Key

什么是 Big Key:我們將含有較大數(shù)據(jù)或含有大量成員、列表數(shù)的Key稱之為大Key。

  • 一個(gè)STRING類型的Key,它的值為5MB(數(shù)據(jù)過(guò)大)
  • 一個(gè)LIST類型的Key,它的列表數(shù)量為20000個(gè)(列表數(shù)量過(guò)多)
  • 一個(gè)ZSET類型的Key,它的成員數(shù)量為10000個(gè)(成員數(shù)量過(guò)多)
  • 一個(gè)HASH格式的Key,它的成員數(shù)量雖然只有1000個(gè)但這些成員的value總大小為100MB(成員體積過(guò)大)

Big Key 存在問(wèn)題

  • 內(nèi)存空間不均勻:如果采用切片集群的部署方案,容易造成某些實(shí)例節(jié)點(diǎn)的內(nèi)存分配不均勻;
  • 造成網(wǎng)絡(luò)擁塞:讀取 bigkey 意味著需要消耗更多的網(wǎng)絡(luò)流量,可能會(huì)對(duì) Redis 服務(wù)器造成影響;
  • 過(guò)期刪除:big key 不單讀寫慢,刪除也慢,刪除過(guò)期 big key 也比較耗時(shí);
  • 遷移困難:由于數(shù)據(jù)龐大,備份和還原也容易造成阻塞,操作失敗;

如何發(fā)現(xiàn) Big Key

  • 使用 redis-cli 客戶端的命令 --bigkeys;
  • 生成 rdb 文件,離線分析 rdb 文件。比如:redis-rdb-cli,rdbtools;
  • 通過(guò) scan 命令,對(duì)掃描出來(lái)的key進(jìn)行類型判斷,例如:string長(zhǎng)度大于10K,list長(zhǎng)度大于10240認(rèn)為是big bigkeys;

Big Key 如何避免

對(duì)于Big Key可以從以下兩個(gè)方面進(jìn)行處理

合理優(yōu)化數(shù)據(jù)結(jié)構(gòu):

1、對(duì)較大的數(shù)據(jù)進(jìn)行壓縮處理;

2、拆分集合:將大的集合拆分成小集合(如以時(shí)間進(jìn)行分片)或者單個(gè)的數(shù)據(jù)。

選擇其他的技術(shù)來(lái)存儲(chǔ) big key:

使用其他的存儲(chǔ)形式,考慮使用 cdn 或者文檔性數(shù)據(jù)庫(kù) MongoDB。

Big Key 如何刪除

直接使用 DEL 命令會(huì)發(fā)生什么?危險(xiǎn):同步刪除 bigkey 會(huì)阻塞 Redis 其他命令,造成 Redis 阻塞。

推薦使用 UNLINK 命令,異步刪除 bigkey,不影響主線程執(zhí)行其他命令。

在業(yè)務(wù)的低峰期使用 scan 命令查找 big key,對(duì)于類型為集合的key,可以使用腳本逐一刪除里面的元素。

參考

【Redis核心技術(shù)與實(shí)戰(zhàn)】https://time.geekbang.org/column/intro/100056701
【Redis設(shè)計(jì)與實(shí)現(xiàn)】https://book.douban.com/subject/25900156/
【估算兩臺(tái)服務(wù)器同時(shí)故障的概率】https://disksing.com/failure-probability-analysis/
【Redis中哨兵選舉算法】https://blog.csdn.net/weixin_44324174/article/details/108939199
【如何處理redis集群中hot key和big key】https://juejin.cn/post/6844903743083773959
【談?wù)剅edis的熱key問(wèn)題如何解決】https://www.cnblogs.com/rjzheng/p/10874537.html
【Redis 中常見的集群部署方案】https://boilingfrog.github.io/2022/02/20/redis中常見的集群部署方案/#主從集群模式
【Redis學(xué)習(xí)筆記】https://github.com/boilingfrog/Go-POINT/tree/master/redis

到此這篇關(guān)于Redis中常見的幾種集群部署方案的文章就介紹到這了,更多相關(guān)Redis 集群部署內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis底層數(shù)據(jù)結(jié)構(gòu)之skiplist實(shí)現(xiàn)示例

    redis底層數(shù)據(jù)結(jié)構(gòu)之skiplist實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了redis底層數(shù)據(jù)結(jié)構(gòu)之skiplist實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Redis RDB與AOF持久化方式詳細(xì)講解

    Redis RDB與AOF持久化方式詳細(xì)講解

    Redis是基于內(nèi)存的數(shù)據(jù)結(jié)構(gòu)服務(wù)器,保存了大量的鍵值對(duì)數(shù)據(jù),所以持久化到磁盤是非常必要的,Redis提供了兩種持久化的方式,分別是RDB和AOF。下面我們看下這兩種持久化方式的具體實(shí)現(xiàn)原理
    2022-11-11
  • Redis從單點(diǎn)到集群部署模式(單機(jī)模式?主從模式?哨兵模式)

    Redis從單點(diǎn)到集群部署模式(單機(jī)模式?主從模式?哨兵模式)

    這篇文章主要為大家介紹了Redis從單點(diǎn)集群部署模式(單機(jī)模式?主從模式?哨兵模式)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Redis如何解決BigKey

    Redis如何解決BigKey

    在Redis的使用過(guò)程中,我們經(jīng)常會(huì)遇到BigKey, BigKey的大值會(huì)導(dǎo)致Redis內(nèi)存中產(chǎn)生大量不連續(xù)的碎片,降低內(nèi)存利用效率,本文主要介紹了Redis如何解決BigKey,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • 超強(qiáng)、超詳細(xì)Redis數(shù)據(jù)庫(kù)入門教程

    超強(qiáng)、超詳細(xì)Redis數(shù)據(jù)庫(kù)入門教程

    這篇文章主要介紹了超強(qiáng)、超詳細(xì)Redis入門教程,本文詳細(xì)介紹了Redis數(shù)據(jù)庫(kù)各個(gè)方面的知識(shí),需要的朋友可以參考下
    2014-10-10
  • 最新評(píng)論