溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么用Redis保存更多的數(shù)據(jù)

發(fā)布時間:2021-10-28 16:08:26 來源:億速云 閱讀:252 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“怎么用Redis保存更多的數(shù)據(jù)”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

我曾遇到過這么一個需求:要用 Redis 保存 5000 萬個鍵值對,每個鍵值對大約是 512B,為了能快速部署并對外提供服務(wù),我們采用云主機來運行  Redis 實例,那么,該如何選擇云主機的內(nèi)存容量呢?

我粗略地計算了一下,這些鍵值對所占的內(nèi)存空間大約是 25GB(5000 萬 *512B)。所以,當(dāng)時,我想到的第一個方案就是:選擇一臺 32GB  內(nèi)存的云主機來部署 Redis。因為 32GB 的內(nèi)存能保存所有數(shù)據(jù),而且還留有 7GB,可以保證系統(tǒng)的正常運行。同時,我還采用 RDB 對數(shù)據(jù)做持久化,以確保  Redis 實例故障后,還能從 RDB 恢復(fù)數(shù)據(jù)。

但是,在使用的過程中,我發(fā)現(xiàn),Redis 的響應(yīng)有時會非常慢。后來,我們使用 INFO 命令查看 Redis 的 latest_fork_usec  指標值(表示最近一次 fork 的耗時),結(jié)果顯示這個指標值特別高,快到秒級別了。

這跟 Redis 的持久化機制有關(guān)系。在使用 RDB 進行持久化時,Redis 會 fork 子進程來完成,fork 操作的用時和 Redis  的數(shù)據(jù)量是正相關(guān)的,而 fork 在執(zhí)行時會阻塞主線程。數(shù)據(jù)量越大,fork 操作造成的主線程阻塞的時間越長。所以,在使用 RDB 對 25GB  的數(shù)據(jù)進行持久化時,數(shù)據(jù)量較大,后臺運行的子進程在 fork 創(chuàng)建時阻塞了主線程,于是就導(dǎo)致 Redis 響應(yīng)變慢了。

看來,第一個方案顯然是不可行的,我們必須要尋找其他的方案。這個時候,我們注意到了 Redis  的切片集群。雖然組建切片集群比較麻煩,但是它可以保存大量數(shù)據(jù),而且對 Redis 主線程的阻塞影響較小。

切片集群,也叫分片集群,就是指啟動多個 Redis  實例組成一個集群,然后按照一定的規(guī)則,把收到的數(shù)據(jù)劃分成多份,每一份用一個實例來保存?;氐轿覀儎倓偟膱鼍爸?,如果把 25GB 的數(shù)據(jù)平均分成 5  份(當(dāng)然,也可以不做均分),使用 5 個實例來保存,每個實例只需要保存 5GB 數(shù)據(jù)。如下圖所示:

怎么用Redis保存更多的數(shù)據(jù)

那么,在切片集群中,實例在為 5GB 數(shù)據(jù)生成 RDB 時,數(shù)據(jù)量就小了很多,fork  子進程一般不會給主線程帶來較長時間的阻塞。采用多個實例保存數(shù)據(jù)切片后,我們既能保存 25GB 數(shù)據(jù),又避免了 fork  子進程阻塞主線程而導(dǎo)致的響應(yīng)突然變慢。

在實際應(yīng)用 Redis  時,隨著用戶或業(yè)務(wù)規(guī)模的擴展,保存大量數(shù)據(jù)的情況通常是無法避免的。而切片集群,就是一個非常好的解決方案。這節(jié)課,我們就來學(xué)習(xí)一下。

如何保存更多數(shù)據(jù)?

在剛剛的案例里,為了保存大量數(shù)據(jù),我們使用了大內(nèi)存云主機和切片集群兩種方法。實際上,這兩種方法分別對應(yīng)著 Redis  應(yīng)對數(shù)據(jù)量增多的兩種方案:縱向擴展(scale up)和橫向擴展(scale out)。

  • 縱向擴展:升級單個 Redis 實例的資源配置,包括增加內(nèi)存容量、增加磁盤容量、使用更高配置的 CPU。就像下圖中,原來的實例內(nèi)存是 8GB,硬盤是  50GB,縱向擴展后,內(nèi)存增加到 24GB,磁盤增加到 150GB。

  • 橫向擴展:橫向增加當(dāng)前 Redis 實例的個數(shù),就像下圖中,原來使用 1 個 8GB 內(nèi)存、50GB 磁盤的實例,現(xiàn)在使用三個相同配置的實例。

怎么用Redis保存更多的數(shù)據(jù)

那么,這兩種方式的優(yōu)缺點分別是什么呢?

首先,縱向擴展的好處是,實施起來簡單、直接。不過,這個方案也面臨兩個潛在的問題。

第一個問題是,當(dāng)使用 RDB 對數(shù)據(jù)進行持久化時,如果數(shù)據(jù)量增加,需要的內(nèi)存也會增加,主線程 fork  子進程時就可能會阻塞(比如剛剛的例子中的情況)。不過,如果你不要求持久化保存 Redis 數(shù)據(jù),那么,縱向擴展會是一個不錯的選擇。

不過,這時,你還要面對第二個問題:縱向擴展會受到硬件和成本的限制。這很容易理解,畢竟,把內(nèi)存從 32GB 擴展到 64GB 還算容易,但是,要想擴充到  1TB,就會面臨硬件容量和成本上的限制了。

與縱向擴展相比,橫向擴展是一個擴展性更好的方案。這是因為,要想保存更多的數(shù)據(jù),采用這種方案的話,只用增加 Redis  的實例個數(shù)就行了,不用擔(dān)心單個實例的硬件和成本限制。在面向百萬、千萬級別的用戶規(guī)模時,橫向擴展的 Redis 切片集群會是一個非常好的選擇。

不過,在只使用單個實例的時候,數(shù)據(jù)存在哪兒,客戶端訪問哪兒,都是非常明確的,但是,切片集群不可避免地涉及到多個實例的分布式管理問題。要想把切片集群用起來,我們就需要解決兩大問題:

  • 數(shù)據(jù)切片后,在多個實例之間如何分布?

  • 客戶端怎么確定想要訪問的數(shù)據(jù)在哪個實例上?

接下來,我們就一個個地解決。

數(shù)據(jù)切片和實例的對應(yīng)分布關(guān)系

在切片集群中,數(shù)據(jù)需要分布在不同實例上,那么,數(shù)據(jù)和實例之間如何對應(yīng)呢?這就和接下來我要講的 Redis Cluster  方案有關(guān)了。不過,我們要先弄明白切片集群和 Redis Cluster 的聯(lián)系與區(qū)別。

實際上,切片集群是一種保存大量數(shù)據(jù)的通用機制,這個機制可以有不同的實現(xiàn)方案。在 Redis 3.0 之前,官方并沒有針對切片集群提供具體的方案。從 3.0  開始,官方提供了一個名為 Redis Cluster 的方案,用于實現(xiàn)切片集群。Redis Cluster 方案中就規(guī)定了數(shù)據(jù)和實例的對應(yīng)規(guī)則。

具體來說,Redis Cluster 方案采用哈希槽(Hash Slot,接下來我會直接稱之為 Slot),來處理數(shù)據(jù)和實例之間的映射關(guān)系。在 Redis  Cluster 方案中,一個切片集群共有 16384 個哈希槽,這些哈希槽類似于數(shù)據(jù)分區(qū),每個鍵值對都會根據(jù)它的 key,被映射到一個哈希槽中。

具體的映射過程分為兩大步:

  • 首先根據(jù)鍵值對的 key,按照CRC16 算法計算一個 16 bit 的值;

  • 然后,再用這個 16bit 值對 16384 取模,得到 0~16383 范圍內(nèi)的模數(shù),每個模數(shù)代表一個相應(yīng)編號的哈希槽。

關(guān)于CRC16 算法,如果感興趣!可以自行Googel查詢

那么,這些哈希槽又是如何被映射到具體的 Redis 實例上的呢?

我們在部署 Redis Cluster 方案時,可以使用 cluster create 命令創(chuàng)建集群,此時,Redis  會自動把這些槽平均分布在集群實例上。例如,如果集群中有 N 個實例,那么,每個實例上的槽個數(shù)為 16384/N 個。

當(dāng)然, 我們也可以使用 cluster meet 命令手動建立實例間的連接,形成集群,再使用 cluster addslots  命令,指定每個實例上的哈希槽個數(shù)。

客戶端如何定位數(shù)據(jù)?

在定位鍵值對數(shù)據(jù)時,它所處的哈希槽是可以通過計算得到的,這個計算可以在客戶端發(fā)送請求時來執(zhí)行。但是,要進一步定位到實例,還需要知道哈希槽分布在哪個實例上。

一般來說,客戶端和集群實例建立連接后,實例就會把哈希槽的分配信息發(fā)給客戶端。但是,在集群剛剛創(chuàng)建的時候,每個實例只知道自己被分配了哪些哈希槽,是不知道其他實例擁有的哈希槽信息的。

那么,客戶端為什么可以在訪問任何一個實例時,都能獲得所有的哈希槽信息呢?這是因為,Redis  實例會把自己的哈希槽信息發(fā)給和它相連接的其它實例,來完成哈希槽分配信息的擴散。當(dāng)實例之間相互連接后,每個實例就有所有哈希槽的映射關(guān)系了。

客戶端收到哈希槽信息后,會把哈希槽信息緩存在本地。當(dāng)客戶端請求鍵值對時,會先計算鍵所對應(yīng)的哈希槽,然后就可以給相應(yīng)的實例發(fā)送請求了。

“怎么用Redis保存更多的數(shù)據(jù)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI