Redis 中常見的集群部署方案


Redis 的高可用集群

前言

這里來了解一下,Redis 中常見的集群方案

幾種常用的集群方案

  • 主從集群模式

  • 哨兵機制

  • 切片集群(分片集群)

主從集群模式

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

  • 主庫:所有的寫操作都在主庫發生,然后主庫同步數據到從庫,同時也可以進行讀操作;

  • 從庫:只負責讀操作;

redis

主庫需要復制數據到從庫,主從雙方的數據庫需要保存相同的數據,將這種情況稱為"數據庫狀態一致"

來看下如何同步之前先來了解下幾個概念

  • 1、服務器的運行ID(run ID):每個 Redis 服務器在運行期間都有自己的run IDrun ID在服務器啟動的時候自動生成。

從服務器會記錄主服務器的run ID,這樣如果發生斷網重連,就能判斷新連接上的主服務器是不是上次的那一個,這樣來決定是否進行數據部分重傳還是完整重新同步。

  • 2、復制偏移量 offset:主服務器和從服務器都會維護一個復制偏移量

主服務器每次向從服務器中傳遞 N 個字節的時候,會將自己的復制偏移量加上 N。

從服務器中收到主服務器的 N 個字節的數據,就會將自己額復制偏移量加上 N。

通過主從服務器的偏移量對比可以很清楚的知道主從服務器的數據是否處於一致。

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

全量同步

從服務器首次加入主服務器中發生的是全量同步

如何進行第一次同步?

redis

1、從服務器連接到主服務器,然后發送 psync 到主服務器,因為第一次復制,不知道主庫run ID,所以run ID為?;

2、主服務器接收到同步的響應,回復從服務器自己的run ID和復制進行進度 offset;

3、主服務器開始同步所有數據到從庫中,同步依賴 RDB 文件,主庫會通過 bgsave 命令,生成 RDB 文件,然后將 RDB 文件傳送到從庫中;

4、從庫收到 RDB 文件,清除自己的數據,然后載入 RDB 文件;

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

增量同步

如果主從服務器之間發生了網絡閃斷,從從服務將會丟失一部分同步的命令。

在舊版本,Redis 2.8之前,如果發生了網絡閃斷,就會進行一次全量復制。

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

Redis 主庫接收到寫操作的命令,首先會寫入replication buffer(主要用於主從數據傳輸的數據緩沖),同時也會把這些操作命令也寫入repl_backlog_buffer這個緩沖區。

redis

這里可能有點疑惑,已經有了replication buffer為什么還多余引入一個repl_backlog_buffer呢?

  • repl_backlog_buffer一個主庫對應一個repl_backlog_buffer,也就是所有從庫對應一個repl_backlog_buffer,從庫自己記錄自己的slave_repl_offset

  • replication buffer用於主節點與各個從節點間,數據的批量交互。主節點為各個從節點分別創建一個緩沖區,由於各個從節點的處理能力差異,各個緩沖區數據可能不同。

如何主從斷開了,當然對應的replication buffer也就沒有了。這時候就依賴repl_backlog_buffer進行數據的增量同步了。

repl_backlog_buffer是一個環形緩沖區,主庫會記錄自己寫到的位置,從庫則會記錄自己已經讀到的位置。

這里借用Redis核心技術與實戰的一張圖片

redis

剛開始主服務器的 master_repl_offset 和從服務器 slave_repl_offset 的位置是一樣的,在從庫因為網絡原因斷連之后,隨着主庫寫操作的進行,主從偏移量會出現偏移距離。

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

舉個栗子

比如這里從服務器1,剛剛由於網絡原因斷連了一會,然后又恢復了連接,這時候,可能缺失了一段時間的命令同步,repl_backlog_buffer的增量同步機制就登場了。

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

redis

repl_backlog_buffer中的緩沖空間要設置的大一點,如果從庫讀的過慢,因為是環形緩沖區,可能出現命令覆蓋的情況,如果出現命令被覆蓋了,從庫的增量同步就無法進行了,這時候會進行一次全量的復制。

緩沖空間的計算公式是:緩沖空間大小 = 主庫寫入命令速度 * 操作大小 - 主從庫間網絡傳輸命令速度 * 操作大小。在實際應用中,考慮到可能存在一些突發的請求壓力,我們通常需要把這個緩沖空間擴大一倍,即 repl_backlog_size = 緩沖空間大小 * 2,這也就是 repl_backlog_size 的最終值。

哨兵機制

對於主從集群模式,如果從庫發生了故障,還有主庫和其它的從庫可以接收請求,但是如果主庫掛了,就不能進行正常的數據寫入,同時數據同步也不能正常的進行了,當然這種情況,我們需要想辦法避免,於是就引入了下面的哨兵機制。

什么是哨兵機制

sentinel(哨兵機制):是 Redis 中集群的高可用方式,哨兵節點是特殊的 Redis 服務,不提供讀寫,主要來監控 Redis 中的實例節點,如果監控服務的主服務器下線了,會從所屬的從服務器中重新選出一個主服務器,代替原來的主服務器提供服務。

redis

核心功能就是:監控,選主,通知。

監控:哨兵機制,會周期性的給所有主服務器發出 PING 命令,檢測它們是否仍然在線運行,如果在規定的時間內響應了 PING 通知則認為,仍在線運行;如果沒有及時回復,則認為服務已經下線了,就會進行切換主庫的動作。

選主:當主庫掛掉的時候,會從從庫中按照既定的規則選出一個新的的主庫,

通知:當一個主庫被新選出來,會通知其他從庫,進行連接,然后進行數據的復制。當客戶端試圖連接失效的主庫時,集群也會向客戶端返回新主庫的地址,使得集群可以使用新的主庫。

如何保證選主的准確性

哨兵會通過 PING 命令檢測它和從庫,主庫之間的連接情況,如果發現響應超時就會認為給服務已經下線了。

當然這會存在誤判的情況,如果集群的網絡壓力比較大,網路堵塞,這時候會存在誤判的情況。

如果誤判的節點是從節點,影響不會很大,拿掉一個從節點,對整體的服務,影響不大,還是會不間斷的對外提供服務。

如果誤判的節點是主節點,影響就很大了,主節點被標注下線了,就會觸發后續的選主,數據同步,等一連串的動作,這一連串的動作很很消耗性能的。所以對於誤判,應該去規避。

如何減少誤判呢?

引入哨兵集群,一個哨兵節點可能會進行誤判,引入多個少哨兵節點一起做決策,就能減少誤判了。

當有多個哨兵節點的時候,大多數哨兵節點認為主庫下線了,主庫才會真正的被標記為下線了,一般來講當有 N 個哨兵實例時,最好要有N/2 + 1個實例判斷主庫下線了,才能最終判定主庫的下線狀態。當然這個數值在 Redis 中是可以配置的。

如何選主

選舉主節點的規則

1、過濾掉已經下線的服務器;

2、過濾掉最近5秒鍾沒有回復過主節點的 INFO(用於觀察服務器的角色) 命令的服務器,保證選中的服務器都是最近成功通過信的;

3、過濾掉和下線主服務器連接超過down-after-milliseconds*10毫秒的從服務器,down-after-milliseconds是主服務器下線的時間,這一操作避免從服務器與主服務器過早的斷開,影響到從庫中數據同步,因為斷開時間越久,從庫里面的數據就越老舊過時。

然后對這些服務器根據slave-priority優先級(這個優先級是手動設置的,比如希望那個從服務器優先變成主服務器,優先級就設置的高一點) 進行排序。

如果幾台從服務器優先級相同,然后根據復制偏移量從大到小進行排序,如果還有相同偏移量的從服務器,然后按照 runID 從小到大進行排序,直到選出一台從服務器。

哨兵進行主節點切換

當根據選舉規則,選出了可以成為主節點的從節點,如何進行切換呢?

在哨兵中也是有一個 Leader 節點的,當一個從庫被選舉出來,從庫的切換是由 Leader 節點完成的。

Leader 節點的選舉用的是 Raft 算法,關於什么是 Raft 算法可參考Raft一致性算法原理

在raft算法中,在任何時刻,每一個服務器節點都處於這三個狀態之一:

  • Follower:追隨者,跟隨者都是被動的:他們不會發送任何請求,只是簡單的響應來自領導者或者候選人的請求;

  • Candidate:候選人,如果跟隨者接收不到消息,那么他就會變成候選人並發起一次選舉,獲得集群中大多數選票的候選人將成為領導者。

  • Leader:領導者,系統中只有一個領導人並且其他的節點全部都是跟隨者,領導人處理所有的客戶端請求(如果一個客戶端和跟隨者聯系,那么跟隨者會把請求重定向給領導人)

哨兵節點的選舉總結起來就是:

1、每個做主觀下線的sentinel節點向其他sentinel節點發送命令,要求將自己設置為領導者;

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

3、如果該sentinel節點發現自己的票數已經超過半數並且超過了 quorum,quorum 用來配置判斷主節點宕機的哨兵節點數。簡單點講就是:如果 Sentinel 集群有 quorum 個哨兵認為 master 宕機了,就「客觀」的認為 master 宕機了;

4、如果此過程選舉出了多個領導者,那么將等待一段時重新進行選舉;

故障轉移

  • sentinel的領導者從從機中選舉出合適的叢機進行故障轉移;

  • 對選取的從節點進行slave of no one命令,(這個命令用來讓從機關閉復制功能,並從從機變為主機);

  • 更新應用程序端的鏈接到新的主節點;

  • 對其他從節點變更 master 為新的節點;

  • 修復原來的 master 並將其設置為新的 master 的從機。

消息通知

哨兵和哨兵之前,哨兵和從庫之間,哨兵和客戶端是如何相互發現,進行消息傳遞?

哨兵和哨兵之間的相互發現,通過 Redis 提供的pub/sub機制實現,因為每個哨兵節點都會和主庫進行連接,通過在主庫中發布信息,訂閱信息,就能找到其他實例的連接信息。

哨兵節點和從庫,通過哨兵向主庫發送 INFO 命令來完成,哨兵給主庫發送 INFO 命令,主庫接受到這個命令后,就會把從庫列表返回給哨兵。接着,哨兵就可以根據從庫列表中的連接信息,和每個從庫建立連接,並在這個連接上持續地對從庫進行監控。

哨兵和客戶端之間:每個哨兵實例也提供pub/sub機制,客戶端可以從哨兵訂閱消息,來獲知主從庫切換過程中的不同關鍵事件。

哨兵提升一個從庫為新主庫后,哨兵會把新主庫的地址寫入自己實例的 pubsub(switch-master) 中。客戶端需要訂閱這 個pubsub,當這個 pubsub 有數據時,客戶端就能感知到主庫發生變更,同時可以拿到最新的主庫地址,然后把寫請求寫到這個新主庫即可,這種機制屬於哨兵主動通知客戶端。

如果客戶端因為某些原因錯過了哨兵的通知,或者哨兵通知后客戶端處理失敗了,安全起見,客戶端也需要支持主動去獲取最新主從的地址進行訪問。

切片集群

對於數據庫我們知道,如果數據量大會進行分庫分表,一般有兩種方案縱向拆分和橫向拆分。這在 Redis 中,同樣適用。

Redis 中的擴展

  • 縱向擴展:更改節點類型以調整集群大小,升級單個Redis實例的資源配置,包括增加內存容量、增加磁盤容量、使用更高配置的CPU。

  • 橫向擴展:通過添加或刪除節點組(分片)來更改復制組中的節點組(分片)數量。

redis

簡單點講就是:垂直擴容就是增加自身的容量,橫向擴容就是加機器。

缺點對比

縱向擴容:

1、如果一味的增加自身的容量,意味着自身存儲的數據將會越來越大,過大的數據,持久化時間將會變得很長,影響自身的響應速度;

2、同樣堆硬件總歸是有上線,達到一定量之后,還是要考慮進行橫向擴容;

橫向擴容:

橫向擴容要面臨的問題,如果發生了分片的擴容,就需要考慮數據的遷移,同時數據切片后,在多個實例之間如何分布?,客戶端如何知道訪問的數據在哪個實例中。。。

雖然有這些問題的存在,好在已經有一些成熟的方案來處理橫向擴容所遇到的問題了

官方的集群解決方案就是Redis Cluster;社區的解決方案有 Codis 和 Twemproxy,Codis 是由我國的豌豆莢團隊開源的,Twemproxy 是 Twitter 團隊的開源的。

這里主要看下Redis Cluster是如何進行處理的

Redis Cluster方案

1、Redis Cluster方案采用哈希槽來處理 KEY 在不同實例中的分布,一個切片集群共有16384個哈希槽,這些哈希槽類似於數據分區,每個鍵值對都會根據它的key,被映射到一個哈希槽中。

2、一個 KEY ,首先會根據CRC16算法計算一個16 bit的值;然后,再用這個 16bit 值對 16384 取模,得到0~16383范圍內的模數,每個模數代表一個相應編號的哈希槽。

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

當然這是平均分配的,如果平均分配額哈希槽中,某一個實例中 KEY,存儲的數據比較大,造成某一個實例的內存過大,這時候可以通過cluster addslots手動調節哈希槽的分配。

當手動分配哈希槽時,需要把16384個槽都分配完,否則Redis集群無法正常工作。

客戶端中的 KEY 如何找到對應的實例

在集群剛剛創建的時候,每個實例只知道自己被分配了哪些哈希槽,是不知道其他實例擁有的哈希槽信息的。但是,Redis 實例會把自己的哈希槽信息發給和它相連接的其它實例,來完成哈希槽分配信息的擴散。

所以當客戶端和集群實例連接后,就可以知道所有的哈希槽的映射,客戶端會把哈希槽的映射保存在本地,這樣如果客戶端響應一個 KEY ,計算出哈希槽,然后就可以向對應的實例發送請求了。

哈希槽重新分配

數據在可能發生遷移,這時候哈希槽就會重新分配了

栗如:

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

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

因為重新分配了哈希槽,所以原來的映射關系可能發生了改變,實例之間可以通過相互通知,快速的感知到映射關系的變化。但是,客戶端無法主動感知這些變化,客戶端對 KEY 的響應,可能依舊映射到了之前的實例節點,面對這種情況,如何處理呢?

1、如果數據已經遷移完了

Redis Cluster中提供重定向機制,如果一個實例接收到客戶端的請求,但是對應的 KEY 已經轉移到別的實例節點中了,這時候會計算出 KEY 當前所處實例的地址,然后返回給客戶端,客戶端拿到最新的實例地址,重新發送請求就可以了。

$ GET hello
(error) MOVED 12320 172.168.56.111:6379
2、數據遷移了一半

如果在遷移的過程中,只遷移了一半的數據,這時候服務器端就會返回 ASK 告知客戶端

GET hello
(error) ASK 1332 012320 172.168.56.111:6379

ASK 就表示當前正在遷移中,客戶端需要訪問數據,就還需要向返回的地址信息,發送一條 ASKING 命令,讓這個實例允許客戶端的訪問請求,然后客戶端再發送具體的業務操作命令。

Redis Cluster 的規模是越大越好嗎

Redis Cluster 能保存的數據量以及支撐的吞吐量,跟集群的實例規模密切相關,原則上如果實例越多,能夠承擔的吞吐量和就越大,不過真的是這樣嗎?

Redis 官方給出了 Redis Cluster 規模上限,就是一個集群運行1000個實例。那么為什么要來限制集群的規模呢,這里分析下:

Redis Cluster 在運行時,每個實例上都會保存 Slot 和實例的對應關系(也就是Slot映射表),以及自身的狀態信息。

為了讓集群中的每個實例都知道其它所有實例的狀態信息,實例之間會按照一定的規則進行通信。這個規則就是 Gossip 協議。

Gossip 協議的工作原理可以概括成兩點。

1、每個實例之間會按照一定的頻率,從集群中隨機挑選一些實例,把 PING 消息發送給挑選出來的實例,用來檢測這些實例是否在線,並交換彼此的狀態信息。PING消息中封裝了發送消息的實例自身的狀態信息、部分其它實例的狀態信息,以及 Slot 映射表。

2、一個實例在接收到 PING 消息后,會給發送PING消息的實例,發送一個 PONG 消息。PONG 消息包含的內容和 PING 消息一樣。

通信的開銷受通信消息大小和通信頻率的影響

Gossip消息大小

Redis實例發送的PING消息的消息體是由clusterMsgDataGossip結構體組成的,這個結構體的定義如下所示:

typedef struct {
    char nodename[CLUSTER_NAMELEN];  //40字節
    uint32_t ping_sent; //4字節
    uint32_t pong_received; //4字節
    char ip[NET_IP_STR_LEN]; //46字節
    uint16_t port;  //2字節
    uint16_t cport;  //2字節
    uint16_t flags;  //2字節
    uint32_t notused1; //4字節
} clusterMsgDataGossip;

這樣看下來一個 Gossip 消息大小在 104 字節。

每個實例在發送一個Gossip消息時,除了會傳遞自身的狀態信息,默認還會傳遞集群十分之一實例的狀態信息。

所以,對於一個包含了1000個實例的集群來說,每個實例發送一個PING消息時,會包含100個實例的狀態信息,總的數據量是 10400字節,再加上發送實例自身的信息,一個Gossip消息大約是10KB。

此外,為了讓Slot映射表能夠在不同實例間傳播,PING消息中還帶有一個長度為 16,384 bit 的 Bitmap,這個Bitmap的每一位對應了一個Slot,如果某一位為1,就表示這個Slot屬於當前實例。這個Bitmap大小換算成字節后,是2KB。我們把實例狀態信息和Slot分配信息相加,就可以得到一個PING消息的大小了,大約是12KB。

PONG消息和PING消息的內容一樣,所以,它的大小大約是12KB。每個實例發送了PING消息后,還會收到返回的PONG消息,兩個消息加起來有24KB。

這樣看下來如果集群數量的增加,消息的大小就會增加。越大的消息傳輸,對性能影響就越大。

消息傳遞的頻率

Redis Cluster的實例啟動后,默認會每秒從本地的實例列表中隨機選出5個實例,再從這5個實例中找出一個最久沒有通信的實例,把 PING 消息發送給該實例。這是實例周期性發送 PING 消息的基本做法。

但是,這里有一個問題:實例選出來的這個最久沒有通信的實例,畢竟是從隨機選出的5個實例中挑選的,這並不能保證這個實例就一定是整個集群中最久沒有通信的實例。

所以 Redis Cluster 的實例會按照每 100ms 一次的頻率,掃描本地的實例列表,如果發現有實例最近一次接收 PONG消息的時間,已經大於配置項 cluster-node-timeout 的一半了(cluster-node-timeout/2),就會立刻給該實例發送 PING 消息,更新這個實例上的集群狀態信息。

所以每秒單實例發送的 PING 數量就是

PING消息發送數量 = 1 + 10 * 實例數(最近一次接收PONG消息的時間超出cluster-node-timeout/2)

1 是指單實例常規按照每 1 秒發送一個PING消息,10 是指每 1 秒內實例會執行 10 次檢查。

假設單個實例檢測發現,每100毫秒有10個實例的PONG消息接收超時,那么,這個實例每秒就會發送101個PING消息,約占1.2MB/s帶寬。如果集群中有30個實例按照這種頻率發送消息,就會占用36MB/s帶寬,這就會擠占集群中用於服務正常請求的帶寬。

所以整體看下來如果 Redis Cluster 集群的規模越大,網絡擁塞的概率就越高,相應的,PONG消息超時的發生概率就越高,這就會導致集群中有大量的心跳消息,影響集群服務正常請求。

雖然我們可以通過調整cluster-node-timeout配置項減少心跳消息的占用帶寬情況,但是,在實際應用中,如果不是特別需要大容量集群,一般建議 Redis Cluster 的規模控制在400~500個實例。

避免 Hot Key

Hot Key就是采用切片集群部署的 Redis ,出現的集群訪問傾斜。

切片集群中的 Key 最終會存儲到集群中的一個固定的 Redis 實例中。某一個 Key 在一段時間內訪問遠高於其它的 Key,也就是該 Key 對應的 Redis 實例,會收到過大的流量請求,該實例容易出現過載和卡頓現象,甚至還會被打掛掉。

常見引發熱點 Key 的情況:

1、新聞中的熱點事件;

2、秒殺活動中的,性價比高的商品;

如何發現 Hot Key
  • 1、提現預判;

根據業務經驗進行提前預判;

  • 2、在客戶端進行收集;

通過在客戶端增加命令的采集,來統計發現熱點 Key;

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

使用monitor命令統計熱點key(不推薦,高並發條件下會有造成redis 內存爆掉的隱患);

hotkeys參數,redis 4.0.3提供了redis-cli的熱點key發現功能,執行redis-cli時加上–hotkeys選項即可。但是該參數在執行的時候,如果key比較多,執行起來比較慢。

  • 4、在Proxy層做收集

如果集群架構引入了 proxy,可以在 proxy 中做統計

  • 5、自己抓包評估

Redis客戶端使用TCP協議與服務端進行交互,通信協議采用的是RESP。自己寫程序監聽端口,按照RESP協議規則解析數據,進行分析。缺點就是開發成本高,維護困難,有丟包可能性。

Hot Key 如何解決

知道了Hot Key如何來應對呢

  • 1、對 Key 進行分散處理;

舉個栗子

有一個熱 Key 名字為Hot-key-test,可以將其分散為Hot-key-test1Hot-key-test2...然后將這些 Key 分散到多個實例節點中,當客戶端進行訪問的時候,隨機一個下標的 Key 進行訪問,這樣就能將流量分散到不同的實例中了,避免了一個緩存節點的過載。

一般來講,可以通過添加后綴或者前綴,把一個 hotkey 的數量變成 redis 實例個數 N 的倍數 M,從而由訪問一個redis key變成訪問N * M個redis key。 N*Mredis key經過分片分布到不同的實例上,將訪問量均攤到所有實例。

const M = N * 2
//生成隨機數
random = GenRandom(0, M)
//構造備份新key
bakHotKey = hotKey + “_” + random
data = redis.GET(bakHotKey)
if data == NULL {
    data = GetFromDB()
    redis.SET(bakHotKey, expireTime + GenRandom(0,5))
}
  • 2、使用本地緩存;

業務端還可以使用本地緩存,將這些熱 key 記錄在本地緩存,來減少對遠程緩存的沖擊。

避免 Big Key

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

  • 一個STRING類型的Key,它的值為5MB(數據過大)

  • 一個LIST類型的Key,它的列表數量為20000個(列表數量過多)

  • 一個ZSET類型的Key,它的成員數量為10000個(成員數量過多)

  • 一個HASH格式的Key,它的成員數量雖然只有1000個但這些成員的value總大小為100MB(成員體積過大)

Big Key 存在問題

  • 內存空間不均勻:如果采用切片集群的部署方案,容易造成某些實例節點的內存分配不均勻;

  • 造成網絡擁塞:讀取 bigkey 意味着需要消耗更多的網絡流量,可能會對 Redis 服務器造成影響;

  • 過期刪除:big key 不單讀寫慢,刪除也慢,刪除過期 big key 也比較耗時;

  • 遷移困難:由於數據龐大,備份和還原也容易造成阻塞,操作失敗;

如何發現 Big Key

  • 使用 redis-cli 客戶端的命令 --bigkeys;

  • 生成 rdb 文件,離線分析 rdb 文件。比如:redis-rdb-cli,rdbtools;

  • 通過 scan 命令,對掃描出來的key進行類型判斷,例如:string長度大於10K,list長度大於10240認為是big bigkeys;

Big Key 如何避免

對於Big Key可以從以下兩個方面進行處理

1、合理優化數據結構:

  • 1、對較大的數據進行壓縮處理;

  • 2、拆分集合:將大的集合拆分成小集合(如以時間進行分片)或者單個的數據;

2、選擇其他的技術來存儲 big key:

  • 使用其他的存儲形式,考慮使用 cdn 或者文檔性數據庫 MongoDB。

Big Key 如何刪除

直接使用 DEL 命令會發生什么?危險:同步刪除 bigkey 會阻塞 Redis 其他命令,造成 Redis 阻塞。

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

在業務的低峰期使用 scan 命令查找 big key,對於類型為集合的key,可以使用腳本逐一刪除里面的元素。

參考

【Redis核心技術與實戰】https://time.geekbang.org/column/intro/100056701
【Redis設計與實現】https://book.douban.com/subject/25900156/
【估算兩台服務器同時故障的概率】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
【談談redis的熱key問題如何解決】https://www.cnblogs.com/rjzheng/p/10874537.html
【Redis 中常見的集群部署方案】https://boilingfrog.github.io/2022/02/20/redis中常見的集群部署方案/#主從集群模式
【Redis學習筆記】https://github.com/boilingfrog/Go-POINT/tree/master/redis


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM