深入分布式缓存之EVCache探秘开局篇(文末赠书)
深入分布式緩存
讀完需要
15
分鐘速讀僅需 5 分鐘
云服務不僅為軟件系統的開發和部署帶來了更多的敏捷性,而且提供了更多創新的可能性。當分布式緩存技術遇到云服務會是怎樣的情形呢?EVCache 就是這樣的一種技術。
EVCache 是一個開源、快速的分布式緩存,是基于 Memcached 的內存存儲和 Spymem-cached 客戶端實現的解決方案,主要用在亞馬遜彈性計算云服務(AWS EC2)的基礎設施上,為云計算做了優化,能夠順暢而高效地提供數據層服務。圖 10-1 所示是 EVCache 開源項目在 Github 上的表現。
圖 10-1 EVCache 開源項目的 Star 趨勢
EVCache 是一個縮寫,包括:
Ephemeral:數據存儲是短暫的,有自身的存活時間。
Volatile:數據可以在任何時候消失。
Cache:一個內存型的鍵值對存儲系統。
EVCache 實現的主要功能包括分布式鍵值對存儲,亞馬遜云服務的跨區域數據復制以及注冊和自動發現新節點或者新服務。EVCache 典型的應用是對上下文一致性要求不高的場景,其可擴展性已經可以處理非常大的流量,同時提供了健壯的應用編程接口。
1
? ?
EVCache 項目介紹
EVCache 是 Netflix 開源軟件項目(Open Source Software,OSS)中的一部分,是 Netflix 多個關于數據存儲的開源項目中的一個重要成員。在 Netflix 架構中有兩個基本元素,一個是控制平面,運行在亞馬遜云服務(AWS)之上,用于用戶登錄,瀏覽和播放以及一般性服務。另一個是數據平面,叫做 Open Connect,這是一個全球性的視頻分發網絡。
EVCache 是位于控制平面的。
Netflix 是微服務架構領域的實踐者,在系統中部署了上百個微服務,每一個微服務只專注做一件事情。這使得 Netflix 所提供的軟件系統能夠做到高度均衡和松耦合。由于狀態都存儲在緩存或持久存儲中,所以這些微服務大多數是無狀態的,易于自動擴展。
EVCache 在 Netflix 內部是一個被廣泛使用的數據緩存服務,所提供的低延遲且高可用的緩存方案可以很好地滿足 Netflix 微服務架構需要,也用來做一般數據的存儲。EVCache 能夠使面向終端用戶的應用,個性化算法和各種微服務都具備優良的性能。
EVCache 具有如下的特性:
分布式的鍵值對存儲,緩存可以跨越多個實例。
數據可以跨越亞馬遜云服務的可用區進行復制。
通過 Netflix 內部的命名服務進行注冊,自動發現新節點和服務。
為了存儲數據,鍵是非空字符串,值可以是非空的字節數組,基本類型,或者序列化對象,且小于 1 MB。
作為通用的緩存集群被各種應用使用,支持可選的緩存名稱,通過命名空間避免主鍵沖突。
一般的緩存命中率在 99%以上。
與 Netfix 駐留數據框架能夠良好協作,典型的訪問次序:內存→ EVCache → Cassandre/SimpleDB/S3。
使用緩存技術所帶來的最大影響可能是數據的不一致性。出于性能優先的考慮,具體的應用會依賴于 EVCache 來處理數據的不一致性。對于存活時間很短的數據,用 TTL 設置數據的失效時間,對于長時間保留的數據,通過構建一致性檢查來修復它們。
EVCache 是使用了 Memeached 操作接口(如 get、set、touch 等),基于數據大小和網絡容量可以線性擴展,支持任意數量的數據備份(有的集群支持 2 個,有的支持 9 個)。所有操作都擁有對拓撲結構的感知、重試、回退,以及其他機制來保障操作的完整性,同時優化了亞馬遜云服務的架構。每個主鍵中的數據通過數據分塊技術處理后可以是任意大小的。
簡而言之,Memcached 是一個單進程應用,在單臺主機上工作的很好,而 EVCache 使用它作為一個基礎模塊,Memcached 是 EVCache 的一個子集。
1.1
? ?
EVCache 的由來
對于一個流媒體服務來說,提供一個以客戶為中心的用戶體驗意味著要做很多事情,要包括優秀的內容庫,直觀的用戶界面,個性化內容推薦,可以讓用戶獲取所喜愛的內容并可高質量播放的快速服務,等等。
Netflix 期待用戶和系統服務交互時能有一個極致的用戶體驗,對云服務而言,所考慮的目標是:
與 Netflix 數據中心相對應的快速響應時間。
從面向會話的應用到云服務中的無會話狀態應用。
使用 NoSQL 的數據駐留,如 Cassandra/SimpleDB/S3。
從數據存儲(如 Cassandra,或其他的亞馬遜云服務如 S3 或 SimpleDB)中計算或提取數據,這樣的數據存儲操作大多需要花費數百毫秒,因此會影響用戶體驗。通過 EVCache 作為數據前端緩存,訪問時間更加快速而且是線性的,同時削減了這些數據存儲的負載,還能夠更有效的分擔用戶請求。此外,數據加載服務經常是先于緩存響應,這保證了用戶可以得到個性化的數據響應而不是通用響應。另外,使用 EVCache 緩存可以有效地削減操作的總體成本。
EVCache 是典型的客戶端/服務器結構。服務器端包括一個 Memcached 進程,這是一個流行的且久經考驗的內存型鍵值對存儲,還包括一個叫 Prana 的 Java 進程用于與發現服務(基于 Eureka 的實現)通信并托管本地管理,以及監控服務健康狀態和統計狀態的各種應用,并將統計信息發送給 Netfix 平臺的統計服務。具體結構如圖 10-2 所示。
圖 10-2 EVCache Server 的基本結構
其中,面向微服務的 Java 應用提供了一個集成應用程序到微服務生態系統的 HTTP 接口,主要功能如下:
注冊到發現系統。
其他服務的發現。
健康檢查服務。
HTTP API 和負載均衡要求。
動態屬性加載。
EVCache 客戶端是一個 Java 的客戶端,用于發現 EVCache 服務器并管理所有的增刪改查(CRUD)操作,由客戶端處理在集群中添加/刪除服務器。基于亞馬遜云服務可用區,客戶端在執行創建、更新和刪除操作的時候復制數據。另一方面,客戶端的讀操作直接從同一可用區的服務器讀取數據。圖 10-3 展示了 EVCache 的典型部署結構和單節點客戶端實例與服務器的關系。
圖 10-3 EVCache 單節點客戶端實例與服務器的關系
一個 EVCache 客戶端連接了多個 EVCache 的服務器集群。在一個區域內,Netflix 有多個全數據集的拷貝,由亞馬遜云服務的可用區隔離開來。虛線框描述了區域內的副本,每個都擁有數據的全量鏡像,作為隔離亞馬遜云服務的自動伸縮組來管理這些鏡像。某些緩存在一個區域內有兩個鏡像,有的擁有更多。這種高層架構長期來看是有效的,不會改變。每個客戶端連接自己區域內所有可用區的所有服務器。寫操作被發往所有實例,讀操作優先選擇離讀請求近的服務器。
1.2
? ?
EVCache 的發展
Netflix 的服務在全球 130 個多個國家上線了,很多國家都可以使用。為了應對用戶和服務日益增長的需求,Netflix 在全球建立了 EVCache 分布式系統。
Netflix 的全球云服務遍布亞馬遜各個服務區域,例如北弗吉尼亞、俄勒岡州和愛爾蘭,為這些地區的會員提供就近服務,但是網絡流量會因為各種原因改變,比如關鍵基礎設施出了問題故障,或者地區之間進行失敗恢復等,因此,Netflix 采用無態應用服務器服務于來自任何地區的會員。
這些數據如果從持久層存儲獲得將會非常昂貴(造成頻繁的數據庫訪問),Netflix 需要將這種數據寫入到本地緩存,而且必須復制到所有地區的緩存中,以便服務于各個地區的用戶請求。微服務是依賴于緩存的,必須快速可靠地訪問多種類型的數據,比如會員的觀影歷史,排行榜和個性化推薦等,這些數據的更新與改變都必須復制到全世界各個地區,以便這些地區的用戶能夠快速可靠地訪問。
EVCache 是專門為這些情況而設計的緩存產品,這是建立在于全局復制基礎上的,同時也考慮了強一致性。例如,如果愛爾蘭和弗吉尼亞的推薦內容有輕微差別,這些差別不會傷害到用戶瀏覽和觀看體驗,對于非重要的數據,會嚴重依賴最終一致性模型進行復制,
本地和全局兩個緩存的差別保持在一個可以容忍的很短的時間內,這就大大簡化了數據的復制。EVCache 并不需要處理全局鎖、事務更新、部分提交回滾或其他分布式一致性有關的復雜問題。即使在跨區域復制變慢的情況下,也不會影響性能和本地緩存的可靠性,所有復制都是異步的,復制系統能夠在不影響本地緩存操作的情況下悄悄地進行。復制延遲是另外一個問題,快得足夠嗎?在兩個地區之間切換的會員流量有多頻繁?什么情況會沖擊導致不一致性?寧愿不從完美主義去設計一個復制系統,EVcache 只要能最低限度滿足應用和會員用戶的要求即可。
圖 10-4 介紹了 EVCache 跨地域的復制
圖 10-4 EVCache 跨地域的數據復制
這張圖說明復制操作是在 SET 操作以后實現,應用程序調用 EVCache 客戶端庫的 set 方法,之后的復制路徑對于調用者是透明的:
1)EVCache 客戶端庫發送 SET 到緩存系統的本地地區的一個實例服務器中。
2)EVCache 客戶端庫同時也將寫人元數據(包括 key,但是不包括要緩存的數據本身)到復制消息隊列(Kafka)。
3)本地區的復制中繼服務將會從這個消息隊列中讀取消息。
4)中繼服務會從本地緩存中抓取符合 key 的數據。
5)中繼服務會發送一個 SET 請求到另一個地域的復制中繼服務。
6)在另一個區域中,復制中繼服務會接受請求,然后執行 SET 操作到它的本地緩存,
完成復制。
7)在接受地區的本地應用當通過 GET 操作以后會在本地緩存上看到這個已經更新的數據值。
這是一個簡單描述,需要注意的是,它只會對 SET 操作有效,對于其他 DELETE TOUCH 或批 mutation 等操作不會復制,DELETE 和 TOUCH 是非常類的,只有一點不同:它們不從本地緩存中讀取已經存在的值。
跨區域復制主要是通過消息隊列進行,一個地區的 EVCache 客戶端不會注意到其他地區的復制情況,讀寫都是只使用本區域緩存,不會和其他地區緩存耦合,通過消息系統來解耦合。
1.3
? ?
EVCache 的演進
EVCache 作為 Nethix 系統中最大的子系統之一,在系統優化中占有相當的比例,地位獨一無二。所有數據存儲在內存的成本隨著用戶基數的增長而上揚,單日個性化批處理輸出將加載超過 5 TB 的數據到 EVCache 集群。數據存儲成本是存儲數據與全局副本個數的乘積。如前所述,不同的 A/B 測試和其他內部數據也增加了更多的數據。對于用戶的工作集,如今已經有數十億的鍵值,而且在持續增加,成本的壓力逐漸顯現了出來。
面向數據和時延的優化
在一般情況下,在 Netflix 的某個服務區域內可以看到同一個用戶的反復區域切換對用戶而言并不是常態。盡管數據在三個區域的內存中,只有一個區域中的數據被所在的用戶正常使用。由此推斷,在每個區域有著這些緩存的不同工作集,一個小的子集是熱數據,其他是冷數據。
除了冷熱數據的分類之外,所有在內存中的這些數據存儲成本隨著用戶的基數在增加。
Netflix 使用 EVCache 在內存中存儲了若干 TB 的數據,包括了用于彈性的多個數據拷貝。
隨著成本面臨的壓力。Netflix 開始使用 RocksDB 來降低 EVCache 的存儲成本,同時保持了相對低的請求延遲。Netflix 引人了多級緩存機制,即同時使用 RAM 和 SSD。
根據不同區域不同數據訪問的情況,Netflix 構建了一個系統將熱數據存儲在 RAM,冷數據存儲在硬盤。這是典型的兩級緩存架構(L1 代表 RAM,L2 代表硬盤),依賴于 EVCache 的強一致性和低時延性能。面對盡量低的時延需求,要使用更多的昂貴內存,使用低成本的 SSD 也要滿足客戶端對低時延的預期。
內存型 EVCache 集群運行在 AWS r3 系列的實例類型上,對大規模內存的使用進行了優化。通過轉移到 i2 系列的實例上,在相同的 RAM 和 CPU 的條件下,可以獲得比 SSD 存儲(r3 系)擴大十倍的增益(80 → 800GB,從 r3.xlarge 到 i2.xlarge)。Netflix 也降級了實例的大小到小型內存實例上。結合這兩點,就可以在數千臺服務器上做優先的成本優化了。
基于 EVCache,這種充分利用全局化請求發布和成本優化的項目叫做 Moneta,源自拉丁記憶女神的名字,也是羅馬神話中財富守護神——Juno Moneta。
Moneta 架構
Moneta 項目在 EVCahce 服務器中引入了 2 個新的進程:Rend 和 Mnemonic。Rend 是用 Go 語言寫的一個高性能代理,Mnemonic 是一個基于 RocksDB 的硬盤型鍵值對存儲。
Mnemnonic 重用了 Rend 服務器組件來處理協議解析(如 Memcached 協議),連接管理和并行鎖。這三種服務器都使用 Memeached 的文本和二進制協議,所以客戶端與它們的交互有著相同的語法,給調試和一致性檢查帶來了便捷性。Moneta 的系統結構如圖 10-5 所示。
圖 10-5 Moneta 的結構組成
Rend 代理服務
Rend 作為另外兩個真正存儲數據進程的代理,是一個高性能服務器,使用二進制和文本 Memcached 協議進行通信。它是 Go 語言寫的,具有對并發處理的高性能。這個項目已經在 Github 上開源了。使用 Go 是不錯的選擇,因為需要比 Java 更好的低時延(垃圾回收時的暫停是個問題),以及比 C 更好的生產效率,同時能處理成千上萬的客戶端連接,Go 非常適合這樣的場景。
Rend 的職責是管理 L1 和 L2 緩存的關系,根據不同的內部使用場景采用不同的策略,還具有裁剪數據的特性,能夠將數據分割成固定的大小插入到 Memcached 中以避免內存分配時的病態行為。這種服務器側的分片代替了客戶端分片,已經證明是可行的。
Rend 的設計是模塊化的,并且可配置。在內部,有這樣一些分層:連接管理,服務器循環,通信協議,請求編排和后臺處理器。Rend 也有著獨立用來測試的客戶端代碼庫,能夠集中發現協議中的 bug 或者其他錯誤,例如錯誤對齊,未清除的緩存以及未完成的響應等。Rend 的基本結構如圖 10-6 所示。
圖 10-6 Rend 的結構組成
作為 Moneta 服務的那些緩存,一個服務器就可以服務多種不同的客戶端。一類是熱路徑上的在線分析流量,用戶請求的個性化數據。其他是離線分析的流量和近期系統所產生的數據。這些典型的服務是整夜運行的巨量批處理和結束時幾個小時的持續寫操作。
模塊化允許使用默認的實現來優化 Netflix 夜間的批處理計算,直接在 L2 中插入數據并且在 L1 中更換熱數據,避免了在夜間預計算時引起 L1 緩存的寫風暴。來自其他區域的副本數據通常不是熱數據,所以也直接插人 L2。
圖 10-7 展示了一個 Rend 進程有多個端口連接了各種后臺存儲。
圖 10-7 Rend多端口連接后臺存儲服務
鑒于 Rend 的模塊化,很容易在不同的端口上引入其他的服務器,幾行代碼就能實現批處理和流量副本。允許不同后臺的插件式嵌人,通過一個接口和一個構造函數即可。已經證明了這種設計的有效性,一個工程師在一天內熟悉了相關代碼并學習了 LMDB,把它集成起來作為了存儲后臺。這些代碼參見 https://github.com/Netflix/rend-Imdb ( https://github.com/Netflix/rend-Imdb )。
Mnemonic 存儲
Mnemonic 是基于 RocksDB 的 L2 解決方案,在硬盤上存儲數據。協議解析、連接管理、Mnemonic 的并發控制等所有的管理都使用了和 Rend 相同的庫。Mnemonic 是嵌入到 Moneta 服務器的一個后臺服務,Mnemonic 項目暴露出一個定制化的 C API 供 Rend 處理器使用。Mnemonic 的基本結構如圖 10-8 所示。
圖 10-8 Mnemonic 的基本結構組成
Mnemonic 中有趣的部分是在 C++的核心層封裝了 RocksDB。Mnemonic 處理 Memcached 協議風格的請求,實現了 Memeached 的所需操作,包括 TTL 支持。它包含了一個重要的特性:將請求分發到一個本地系統的多個 RocksDB 數據庫,減少了每個 RocksDB 數據庫實例的負載。
在研究過有效訪問 SSD 的幾種技術之后,Netflix 選擇了 RocksDB,一個嵌入式鍵值對存儲,它使用了日志結構合并樹的數據結構。寫操作首先插入到一個內存數據結構中(一個內存表),當寫滿的時候再寫入到硬盤上。當寫入硬盤的時候,內存表是一個不可修改的 SST 文件。這樣形成了批量的序列化寫人 SSD 的操作,減少了大量的內部垃圾回收,改善了 SSD 在長時間運行實例上的時延。
Netflix 開始使用有層次的精簡配置,主要原因是在多個數據庫中分發請求。然而,當評估生產數據的精簡配置以及與生產環境類似的流量的時候,發現這樣的配置會引起大量額外的 SSD 讀寫,增加了時延。SSD 讀流量經常達到 200MB/sec。評估時的流量包括了長時間的高寫操作,仿真了每天的批處理計算進程。在此期間,RocksDB 持續的移動 L0 記錄達到了一個很高的水平,放大成為非常高的寫操作。
為了避免過載,Netflix 切換到 FIFO 型的精簡配置。在這種配置中,沒有真正的精簡操作被完成。基于數據庫的最大尺寸,刪除舊的 SST 文件。記錄在硬盤的 level 0 中,所以只在多個 SST 文件中按時間排序。這種配置的下降趨勢在于讀操作必須在判斷一個鍵是否命中之前以時間倒序檢查每個 SST 文件。這種檢查通常不需要硬盤讀操作,RocksDB 中的大量過濾器杜絕了高比例的對每個 SST 的硬盤訪問。然而,有利有弊,SST 文件的數量影響了賦值操作的有效性,將低于正常有層次風格的精簡配置。Netflix 通過初始進入系統時的讀寫請求在多個 RocksDB 進行分發減少了掃描多個文件的負面影響。(未完待續)
- EOF -
文末留言,分享你對緩存的理解與看法,截止到2021年1月15日12點,精選后點贊數前5名,獲得作者簽名書《深入分布式緩存》一本
想要加入中生代架構群的小伙伴,請添加群合伙人大白的微信
申請備注(姓名+公司+技術方向)才能通過哦!
阿里技術精彩文章推薦
往期推薦
深度:揭秘阿里巴巴的客群畫像
多隆:從工程師到阿里巴巴合伙人
阿里技術專家楚衡:架構制圖的工具與方法論
螞蟻集團技術專家山丘:性能優化常見壓測模型及優缺點
阿里文娛技術專家戰獒: 領域驅動設計詳解之What, Why, How?
阿里專家馬飛翔:一文讀懂架構整潔之道
阿里專家常昊:新人如何上手項目管理?
螞蟻集團沈凋墨:Kubernetes-微內核的分布式操作系統
阿里合伙人范禹:常掛在阿里技術人嘴邊的四句土話
阿里技術專家都鐸:一文搞懂技術債
支付寶研究員兼OceanBase總架構師楊傳輝:我在數據庫夢之隊的十年成長路
阿里技術專家麒燁:修煉測試基本功
阿里計算平臺掌門人賈揚清:我對人工智能方向的一點淺見
螞蟻資深算法專家周俊:從原理到落地,支付寶如何打造保護隱私的共享智能?
阿里高級技術專家簫逸:如何畫好一張架構圖?
阿里高級技術專家張建飛:應用架構分離業務邏輯和技術細節之道
螞蟻科技 Service Mesh 落地實踐與挑戰 | GIAC 實錄
阿里6年,我的技術蛻變之路!
螞蟻集團涵暢:再啟程,Service Mesh 前路雖長,尤可期許
阿里P9專家右軍:大話軟件質量穩定性
阿里合伙人程立:阿里15年,我撕掉了身上兩個標簽
阿里高工流生 | 云原生時代的 DevOps 之道
阿里高級技術專家邱小俠:微服務架構的理論基礎 - 康威定律
阿里P9專家右軍:以終為始的架構設計
阿里P8架構師:淘寶技術架構從1.0到4.0的架構變遷!12頁PPT詳解
阿里技術:如何畫出一張合格的技術架構圖?
螞蟻資深技術專家王旭:開源項目是如何讓這個世界更安全的?
阿里資深技術專家崮德:8 個影響我職業生涯的重要技能
阿里儒梟:我看技術人的成長路徑
阿里高級技術專家宋意:平凡人在阿里十年的成長之旅
阿里技術專家甘盤:淺談雙十一背后的支付寶LDC架構和其CAP分析
阿里技術專家光錐:億級長連網關的云原生演進之路
阿里云原生張羽辰:服務發現技術選型那點事兒
螞蟻研究員玉伯:做一個簡單自由有愛的技術人
阿里高級技術專家至簡: Service Mesh 在超大規模場景下的落地挑戰
阿里巴巴山獵:手把手教你玩轉全鏈路監控
阿里涉江:你真的會學習嗎?從結構化思維說起
螞蟻金服資深技術專家經國:云原生時代微服務的高可用架構設計
? ?END ? ?? #架構師必備#點分享點點贊點在看總結
以上是生活随笔為你收集整理的深入分布式缓存之EVCache探秘开局篇(文末赠书)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最短路之 SPFA(判环+负权)
- 下一篇: 大厂面试官必问的 MySQL 索引调优等