redis 解析信息圖
什么是 Redis?
Redis("REmote DIctionary Service" 的縮寫)是一個開源的鍵值數據庫服務器。
對 Redis 最準確的描述是它是一個數據結構服務器。Redis 的這種特定性質使其在開發人員中非常受歡迎和廣泛采用。
與其對行進行迭代、排序和排列,不如從頭開始使用數據結構來存儲數據?早期,Redis 像 Memcached 一樣使用,但隨著 Redis 的改進,它變得可行于許多其他用例,包括發布-訂閱機制、流處理和隊列。
用于存儲的 Redis 數據類型
主要地,Redis 是一個內存中的數據庫,用作其他“真實”數據庫(如 MySQL 或 PostgreSQL)前面的緩存,以幫助提高應用程序的性能。它充分利用了內存的速度,并減輕了中央應用程序數據庫的負載,用于以下情況:
•很少更改但經常請求的數據•較不關鍵但經常演化的數據。
上述數據的示例可以包括會話或數據緩存以及儀表板的排行榜或匯總分析。
Redis 如何用于緩存
然而,對于許多用例,Redis 提供了足夠的保證,可以用作一個功能齊全的主數據庫。結合 Redis 插件和各種高可用性(HA)設置,Redis 作為數據庫對于某些場景和工作負載變得非常有用。
另一個重要的方面是,Redis 模糊了緩存和數據存儲之間的界限。在內存中讀取和操作數據比在傳統數據存儲中使用 SSD 或 HDD 更快,這一點非常重要。
每位軟件工程師都應該了解的重要延遲和帶寬數據。
最初,Redis 最常與 Memcached 進行比較,后者在當時沒有任何非易失性持久性。
Memcached
Memcached 由 Brad Fitzpatrick 于 2003 年創建,比 Redis 提前了六年。它最初是一個 Perl 項目,后來被重寫為 C 語言。它是當時的事實上的緩存工具。它與 Redis 的主要區別在于它缺乏數據類型和僅支持 LRU(最近最少使用)的有限驅逐策略。
另一個區別是,Redis 是單線程的,而 Memcached 是多線程的。在嚴格的緩存環境中,Memcached 可能性能不錯,但在分布式集群中需要進行一些設置,而 Redis 則可以立即支持此功能。
下面是這兩個緩存之間功能的當前比較。
表格
Memcached | Redis | |
亞毫秒延遲 | 是 | 是 |
開發者易用性 | 是 | 是 |
數據分區 | 是 | 是 |
廣泛支持的編程語言 | 是 | 是 |
高級數據結構 | - | 是 |
多線程架構 | 是 | - |
快照 | - | 是 |
復制 | - | 是 |
事務 | - | 是 |
發布/訂閱 | - | 是 |
Lua 腳本 | - | 是 |
地理空間支持 | - | 是 |
盡管現在可以配置它如何將數據持久化到磁盤,但在首次引入時,Redis 使用了快照,其中內存中數據的異步副本被持久化到磁盤以進行長期存儲。不幸的是,這種機制的缺點是在快照之間有可能丟失數據。
自 2009 年以來,Redis 已經成熟。我們將涵蓋大部分 Redis 的架構和拓撲,以便您可以將 Redis 添加到您的數據存儲系統工具庫中。
Redis 架構
在我們開始討論 Redis 內部之前,讓我們討論各種 Redis 部署及其權衡。
我們將主要關注以下配置:
1.單一 Redis 實例2.Redis 高可用性(HA)3.Redis Sentinel4.Redis 集群
根據您的用例和規模,您可以決定使用哪種設置。
單一 Redis 實例
簡單的 Redis 部署。
單一 Redis 實例是 Redis 最簡單的部署方式。它允許用戶設置和運行小型實例,以幫助它們增長并加速其服務。然而,這種部署方式并不沒有缺點。例如,如果此實例失敗或不可用,所有對 Redis 的客戶端調用都將失敗,從而降低系統的整體性
能和速度。
在具有足夠內存和服務器資源的情況下,此實例可能非常強大。主要用于緩存的情況可能會在最少的設置中顯著提高性能。在足夠的系統資源的情況下,您可以在運行應用程序的同一臺服務器上部署此 Redis 服務。
了解在系統內部管理數據的一些 Redis 概念至關重要。發送到 Redis 的命令首先在內存中處理。然后,如果這些實例上設置了持久性,就會在某個間隔上有一個分叉進程來促進數據持久性 RDB(Redis 數據的非常緊湊的瞬態表示)快照或 AOF(追加日志文件)。
這兩個流程允許 Redis 具有長期存儲、支持各種復制策略,并啟用更復雜的拓撲。如果 Redis 沒有設置持久性來持久化數據,那么在重新啟動或故障切換的情況下數據會丟失。如果在重新啟動時啟用了持久性,它會將 RDB 快照或 AOF 中的所有數據加載到內存中,然后實例可以支持新的客戶端請求。
說到這里,讓我們看看您可能想要使用的更多分布式 Redis 設置。
Redis 高可用性(HA)
具有次級故障切換的 Redis。
Redis 另一個常見的設置是主要部署與次要部署的結合,次要部署與主要部署保持同步。當數據寫入主要實例時,它會將這些命令的副本發送到輔助實例的客戶端輸出緩沖區,從而促進復制。輔助實例可以是部署中的一個或多個實例。這些實例可以幫助擴展對 Redis 的讀取,或者在主要實例丟失時提供故障切換。
高可用性
高可用性(HA)是系統的一個特性,旨在確保在較長的平均時間內獲得一定級別的運行性能,通常是可用性。
在這些 HA 系統中,不應該有單一故障點,因此系統可以迅速且優雅地恢復。這會導致可靠的交叉備份,因此在從主要到次要的過渡期間不會丟失數據,并且能夠自動檢測故障并從中恢復。
在這個拓撲中有一些需要考慮的新事物,因為我們現在已經進入一個具有許多需要考慮的謬論[1]的分布式系統。以前很簡單的事情現在變得更加復雜。
Redis 復制
Redis 的每個主要實例都有一個復制 ID 和一個偏移量。這兩個數據對于確定復制實例何時可以繼續其復制過程或確定是否需要執行完全同步非常關鍵。這個偏移量會為發生在主要 Redis 部署上的每個操作遞增。
復制 ID,偏移量
更明確地說,當 Redis 復制實例的偏移量僅落后于主要實例的幾個偏移量時,它會接收主要 Redis 部署上的其余命令,并在其數據集上重新播放,直到同步為止。如果這兩個實例不能就復制 ID 達成一致,或者偏移量對于主要實例來說是未知的,則復制實例將請求完全同步。這涉及到主要實例創建一個新的 RDB 快照,并將其發送到復制實例。在進行此傳輸時,主要實例會在快照截止和當前偏移之間的所有中間更新上進行緩沖,以在次要實例與快照同步后將其發送給次要實例。復制完成后,復制過程可以正常繼續。
如果一個實例具有相同的復制 ID 和偏移量,它們具有完全相同的數據。現在您可能會想知道為什么需要復制 ID。當 Redis 實例升級為主要實例或從頭開始作為主要實例重新啟動時,它將獲得新的復制 ID。這用于推斷新升級的次要實例是從哪個以前的主要實例復制而來的。這允許能夠執行部分同步(與其他次要實例一起)的能力,因為新
的主要實例會記住其舊的復制 ID。
例如,兩個實例,主要和次要,具有相同的復制 ID,但偏移量相差幾百個命令,這意味著如果這些命令在偏移量稍微落后的實例上重新播放,它們將具有相同的數據集。現在,如果復制 ID 完全不同,當我們不知道新的復制 ID(重新連接并重新加入)的先前復制 ID(沒有共同的祖先)時。我們需要執行昂貴的完全同步。
或者,如果我們知道以前的復制 ID,那么我們可以推理出如何使數據同步,因為我們可以推理出它們都共享的公共祖先以及偏移量對于部分同步是有意義的。
Redis Sentinel
Redis Sentinel 部署(為了清晰起見,省略了來自其他 Sentinel 節點的額外監視/虛線)。
Sentinel 是一個分布式系統。與所有分布式系統一樣,Sentinel 具有一些優點和缺點。Sentinel 的設計是這樣的,多個 Sentinel 進程一起協同工作,以協調狀態,以提供 Redis 的高可用性。畢竟,您不希望系統保護您免受故障的情況下有其自己的單一故障點。
Sentinel 負責幾個方面。首先,它確保當前的主要和次要實例正常運行并響應。這是必要的,因為 Sentinel(與其他 Sentinel 進程一起)可以在主要和/或次要節點丟失的情況下發出警報并采取行動。其次,它在服務發現中發揮了類似于其他系統中的 Zookeeper 和 Consul 的作用。因此,當新的客戶端嘗試將某些內容寫入 Redis 時,Sentinel 將告訴客戶端當前的主要實例是什么。
因此,Sentinel不斷監視可用性,并將這些信息發送給客戶端,以便如果它們確實出現故障轉移,客戶端可以對其做出反應。
以下是其職責:
1.監控 - 確保主要和次要實例按預期工作。2.通知 - 通知系統管理員有關 Redis 實例中發生的情況。3.故障轉移管理 - Sentinel 節點可以在主要實例不可用并且足夠多的(法定人數)節點同意此情況為真時啟動故障轉移流程。4.配置管理 - Sentinel 節點還用作當前主要 Redis 實例的發現點。
使用 Redis Sentinel 可以實現故障檢測。這種檢測涉及到多個 Sentinel 進程達成一致,即當前的主要實例不再可用。這個一致性過程稱為法定人數。這允許提高魯棒性并保護不良機器無法到達主要 Redis 節點的情況。
法定人數
法定人數是分布式系統必須獲得的最低選票數,以便允許執行操作,如故障切換。這個數字是可配置的,但應該反映分布式系統中的節點數量。大多數分布式系統的大小為三個或五個,法定人數分別為兩個或三個。在需要打破關系的情況下,奇數個節點是首選的。
這種設置不是沒有缺點的,因此我們將運行一些在使用 Redis Sentinel 時的推薦和最佳實踐。
您可以以多種方式部署 Redis Sentinel。老實說,為了做出任何明智的建議,我需要比我現在擁有的更多的系統上下文。作為一般指導,我建議在每個應用程序服務器旁邊運行一個 Sentinel 節點(如果可能的話),這樣您也不需要考慮 Sentinel 節點和實際使用 Redis 的客戶端之間的網絡可達性差異。
您可以將 Sentinel 與 Redis 實例一起運行,甚至可以在獨立節點上運行,但這會以不同的方式復雜化事情。我建議至少運行三個節點,法定人數至少為兩個。下面是一個簡單的圖表,詳細說明了集群中服務器數量以及關聯的法定人數和可容忍的故障數量。
Redis 集群
Redis 集群架構
我相信許多人都想知道當您無法在一臺機器上存儲所有數據時會發生什么。目前,在 AWS 上在線列出的單個服務器上可用的最大 RAM 為 24TB,盡管這很多,但對于某些系統來說,這還不夠,即使對于緩存層也是如此。
Redis 集群允許 Redis 進行水平擴展。
垂直和水平擴展
隨著系統的增長,您有三種選擇。
1.做得更少(沒有人完全這樣做,因為我們是貪婪的怪物)。2.增加規模。3.擴展出去。
認真對待后兩種情況,垂直擴展和水平擴展分別稱為
更大的機器或更多的機器。垂直擴展(更大的機器)并不是永遠有效的策略,因為即使是大機器,RAM 也是有限的。
為了使系統能夠水平擴展,系統需要能夠擴展到多個節點,以便在不同節點之間均勻分布負載。Redis 集群允許用戶對多個節點進行組合,以實現這種擴展。盡管 Redis 集群提供了一種方式來實現這一點,但分布式系統非常困難,不應該在不充分理解其優點和缺點的情況下使用。
首先,考慮以下問題:
•數據的一致性 - 當您寫入一個節點時,它如何確保在所有其他節點上都有相同的數據?•數據如何分區 - 將數據劃分到多個節點時,如何處理數據?•故障如何被處理 - 如果節點失敗,Redis 如何確保不會丟失數據并繼續運行?
Redis 集群是 Redis 提供的官方分布式解決方案。它提供了一種在多個節點之間水平分區數據的方法,并具有自動重新分配和數據復制等內置功能,以處理節點故障。不過,需要注意,Redis 集群也需要更多的配置和維護工作,因為它引入了更多的復雜性。
Redis 集群配置
Redis 集群使用一種分片機制將數據劃分為多個槽(slot)。每個槽都可以包含一個鍵值對。在 Redis 集群中,有 16384 個槽可供使用。當您寫入或讀取數據時,Redis 集群會根據鍵的哈希值將其映射到一個槽中,然后確定該槽所在的節點。這樣,數據可以均勻地分布在不同的節點上。
在 Redis 集群中,鍵被映射到槽,并分布在不同的節點上。
要配置 Redis 集群,您需要運行多個 Redis 實例,每個實例都配置為具有不同的端口號和節點標識。這些實例將一起組成 Redis 集群。您還需要一個或多個 Sentinel 進程來監視和管理集群的健康狀態。
以下是配置 Redis 集群的一般步驟:
1.啟動多個 Redis 實例,每個實例都使用不同的配置文件和端口號,并配置它們為集群節點。2.創建一個集群配置文件,指定每個節點的主機和端口號,以及槽的分配情況。您可以使用 redis-trib.rb
工具來生成此配置文件。3.使用 redis-trib.rb
工具創建 Redis 集群。該工具會自動將槽分配給節點,并設置集群中的主節點和從節點。4.啟動 Sentinel 進程以監視集群的健康狀態。Sentinel 進程可以配置為自動執行故障切換操作。5.確保客戶端應用程序知道如何連接到 Redis 集群,并使用集群模式來進行讀取和寫入操作。客戶端庫通常提供了支持 Redis 集群的功能。
需要注意的是,配置和維護 Redis 集群需要一些復雜性和額外的工作,因此在考慮使用 Redis 集群時,建議仔細研究 Redis 官方文檔和最佳實踐。
Redis 集群架構示例
以下是一個簡單的 Redis 集群架構示例,其中包含 6 個節點(3 個主節點和 3 個從節點)以及 3 個 Sentinel 進程。每個節點都配置為監聽不同的端口,并且通過 Redis 集群協議進行通信。
示例 Redis 集群架構
在這個示例中,有三個主節點(M1、M2 和 M3)和三個從節點(S1、S2 和 S3)。每個主節點都有一個或多個從節點,用于復制數據。Sentinel 進程(Sentinel1、Sentinel2 和 Sentinel3)用于監視集群的狀態并執行故障切換操作。
Redis 集群的優點包括水平擴展能力、高可用性和自動數據分片。然而,它也需要更復雜的配置和管理,以確保集群的穩定性和性能。
Redis 數據模型
Redis 是一個鍵值存儲系統,其中數據以鍵值對的形式存儲在內存中。每個鍵都是唯一的,用于檢索相關聯的值。Redis 支持多種不同的數據類型,使其適用于各種用例。
以下是 Redis 支持的主要數據類型:
1.字符串(String):最簡單的數據類型,可以包含文本、數字或二進制數據。字符串類型的值最大可以存儲 512MB 的數據。2.哈希表(Hash):類似于關聯數組或字典,用于存儲字段和與字段相關聯的值。每個哈希表可以存儲數百萬個字段-值對。3.列表(List):有序的字符串元素列表。列表支持從兩端添加、刪除和訪問元素。它們
適用于隊列和棧等數據結構。
1.集合(Set):無序的字符串元素集合,不允許重復元素。集合支持添加、刪除和檢查成員的操作。2.有序集合(Sorted Set):類似于集合,但每個成員都關聯一個分數,用于排序。有序集合適用于排行榜和范圍查詢等情況。3.位圖(Bitmap):存儲二進制位的數據結構,支持位級別的操作。位圖適用于跟蹤用戶在線狀態等應用。4.超級日志(HyperLogLog):用于估計基數(不同元素的數量)的數據結構,支持基數估計和交集、并集等操作。5.地理空間索引(Geospatial Index):用于存儲地理位置數據和執行地理空間查詢的數據結構。
Redis 還支持其他一些數據類型,如流(Stream)和發布-訂閱(Pub/Sub),這些類型適用于特定的使用情況。您可以根據您的應用程序需求選擇合適的數據類型,并將它們組合使用以滿足不同的用例。
總結
Redis 是一個強大的內存數據庫,可用于多種用例,包括緩存、數據存儲和實時應用程序。您可以根據應用程序的需求選擇不同的 Redis 配置,包括單機部署、Redis Sentinel 高可用性配置和 Redis 集群分布式部署。
了解 Redis 的數據模型和支持的數據類型對于有效使用 Redis 非常重要。Redis 提供了多種數據類型,如字符串、哈希表、列表、集合和有序集合,使其適用于各種用例。
最終,Redis 的成功使用取決于正確配置和管理,并且需要根據負載和可用性需求進行擴展和調整。不同的應用程序需要不同的 Redis 部署策略,因此深入了解 Redis 的功能和最佳實踐是非常重要的。希望這些信息對您有所幫助,有助于更好地理解 Redis 及其在分布式系統中的作用。
引用鏈接
[1]
redis: https://architecturenotes.co/redis/