Pinterest大規(guī)模緩存集群的架構(gòu)剖析,pinterest后臺分析Pinterest大規(guī)模緩存集群的架構(gòu)剖析作者 Kevin Lin譯者 朱琪珊策劃 萬佳隨著越來越多的用戶到 Pinterest 尋求靈感,Pinterest 核心基礎(chǔ)設(shè)施系統(tǒng)的需求增長的比以往任何時候都快。我們的核心存儲系統(tǒng)之一是位于許多微服......
作者 Kevin Lin
譯者 朱琪珊
策劃 萬佳
隨著越來越多的用戶到 Pinterest 尋求靈感,Pinterest 核心基礎(chǔ)設(shè)施系統(tǒng)的需求增長的比以往任何時候都快。我們的核心存儲系統(tǒng)之一是位于許多微服務(wù)和數(shù)據(jù)庫前面的分布式緩存層。它處于 Pinterest 基礎(chǔ)架構(gòu)技術(shù)棧的底部,負(fù)責(zé)吸收由用戶增長驅(qū)動的絕大多數(shù)后端流量。
Pinterest 的分布式緩存集群建立在 AWS 的 EC2 實例上,由數(shù)千臺機(jī)器組成,緩存了數(shù)百 TB 的數(shù)據(jù),高峰時,每秒可處理 1.5 億個請求。該緩存層通過降低整個后端技術(shù)棧的延遲,來優(yōu)化頂層性能,并通過減少昂貴的后端所需的容量來提供顯著的成本效率。
本文中,我們將對支持 Pinterest 的大規(guī)模緩存集群的架構(gòu)進(jìn)行深入的技術(shù)研究。
1應(yīng)用數(shù)據(jù)緩存
每個對 Pinterest 的 API 請求都會在內(nèi)部根據(jù)技術(shù)棧分發(fā)到復(fù)雜的 RPC 樹,并在完成其關(guān)鍵路徑前會涉及數(shù)十個服務(wù)。這可能包括查詢關(guān)鍵數(shù)據(jù)(例如 Pinterest 的圖片和收藏板)的服務(wù),推快遞相關(guān)圖片的推薦系統(tǒng)和垃圾內(nèi)容檢測系統(tǒng)。在這些服務(wù)中,只要其輸入數(shù)據(jù)可以被唯一鍵值表示,就可以將該離散的查詢單元的結(jié)果緩存在臨時存儲系統(tǒng)中,以便將來重用。
在 Pinterest,分布式緩存層的最常見用途是通過后備語義(lookaside semantics)來存儲這類中間計算的結(jié)果。這使得緩存層能吸收一大部分流量。如果沒有緩存層,這些流量會流向涉及復(fù)雜計算和昂貴存儲的服務(wù)和數(shù)據(jù)庫。憑借著毫秒級的尾延遲(tail latency),以及極低的單位請求基礎(chǔ)架構(gòu)成本,這個分布式緩存層提供了一個高性能低成本的后端擴(kuò)展機(jī)制,以滿足 Pinterest 不斷增長的需求。
簡化版的 Pinterest 的 API 請求生命周期:經(jīng)過主要 API 服務(wù),其依賴項后端以及分布式緩存層。
通過提供分布式緩存層即服務(wù),應(yīng)用開發(fā)人員可以專注于實現(xiàn)業(yè)務(wù)邏輯,而不必?fù)?dān)心分布式數(shù)據(jù)的一致性、高可用性或者內(nèi)存容量。緩存層用戶使用通用的路由抽象層,以確保應(yīng)用程序具有容錯性和一致的數(shù)據(jù)視圖。此外,緩存服務(wù)端集群可以獨(dú)立于應(yīng)用層橫向擴(kuò)展,從而透明地調(diào)整內(nèi)存或吞吐量,以適應(yīng)資源使用情況的變化。
2分布式緩存的骨干:Memcached 和 Mcrouter
Memcached 和 mcrouter 構(gòu)成了 Pinterest 分布式緩存基礎(chǔ)架構(gòu)的骨干,并且在 Pinterest 的存儲基礎(chǔ)架構(gòu)中起著至關(guān)重要的作用。Memcached 是由純 C 語言編寫的開源且高效的內(nèi)存鍵值存儲。Mcrouter 是應(yīng)用層的 Memcached 協(xié)議代理,位于 Memcached 集群的前面,并提供強(qiáng)大的高可用性和路由功能。
Memcached 是緩存解決方案中非常有吸引力的選擇:
得益于其異步事件驅(qū)動的體系結(jié)構(gòu)和多線程處理模型,memcached 非常高效且易于進(jìn)行橫向擴(kuò)展以滿足容量需求。
Extstore 通過實例的 NVMe 閃存磁盤上的二級溫存儲(secondary warm storage)層,幫助實現(xiàn)了驚人的存儲效率。
Memcached 精心設(shè)計的簡單體系結(jié)構(gòu)提供了在其之上構(gòu)建抽象層的靈活性,以及簡單易行的水平可擴(kuò)展性以滿足日益增長的需求。一個 Memcached 進(jìn)程本身只是一個簡單的鍵值存儲,根據(jù)設(shè)計,它對其它的 Memceched 進(jìn)程的存在毫無了解,甚至沒有 Memcached 集群的概念。
Memcached 在數(shù)十年的開發(fā)過程中已經(jīng)經(jīng)過準(zhǔn)確性和性能的嚴(yán)格測試,并擁有非常活躍的開源社區(qū)(該社區(qū)還將多個 Pinterest 提交的補(bǔ)丁合并至上游。)。
Memcached 自帶了對 TLS 終止功能的原生支持,從而使我們能通過 TLS 雙向身份驗證的流量(該過程還額外包括內(nèi)部搭建的基于 SPIFFE 授權(quán)訪問控制)來保護(hù)整個集群。
Mcrouter 在 2014 年由 Facebook 開源,在擴(kuò)展其 Memcached 部署方面發(fā)揮了關(guān)鍵作用。Mcrouter 也非常適合 Pinterest 的架構(gòu),原因如下:
通過為應(yīng)用開發(fā)人員提供與整個緩存集群進(jìn)行交互的單個終端節(jié)點(diǎn),Mcrouter 充當(dāng)了 Memcached 服務(wù)器集群的有效抽象。此外,將 mcrouter 用作整個系統(tǒng)的唯一接口可以確保 Pinterest 上所有服務(wù)和機(jī)器之間有通用及全局一致的流量行為。
Mcrouter 提供了解耦的控制平面和數(shù)據(jù)平面:Memcached 服務(wù)器集群的整個拓?fù)浣Y(jié)構(gòu)被劃分為多個“池”(邏輯集群),而管理客戶端和服務(wù)器池之間交互的請求路由策略和行為均被獨(dú)立管理。
Mcrouter 的配置 API 為復(fù)雜的路由提供了強(qiáng)大的基礎(chǔ),包括區(qū)域親和性路由,用于實現(xiàn)數(shù)據(jù)冗余的復(fù)制,多層緩存層和影子流量。
作為使用 memcached 的 ASCII 協(xié)議的應(yīng)用層代理,mcrouter 開放了針對智能協(xié)議的功能,例如請求處理(TTL 修改、運(yùn)行中壓縮等)。
Mcrouter 原生地提供了豐富的可觀察性功能,并且對客戶端應(yīng)用來說不需要任何成本。這為我們整個基礎(chǔ)架構(gòu)中的 Memcached 流量提供了詳細(xì)的可見性。對我們而言,其中最重要的指標(biāo)包括百分位請求延遲,按單個客戶端和服務(wù)器維度劃分的吞吐量,與鍵前綴和鍵模式有關(guān)的請求趨勢以及用于檢測服務(wù)器行為異常的錯誤率。
從 mcrouter 到 Memcached 的請求路由總覽。每個鍵前綴都與一個路由策略相關(guān)聯(lián),圖中展示了兩個例子。
在實踐中,mcrouter 作為邊車代理(proxy sidecar)被部署在和服務(wù)同一機(jī)器的單獨(dú)進(jìn)程。如圖 2 所示,應(yīng)用程序(可以由任何語言編寫)在回快遞時將 Memcached 協(xié)議請求發(fā)快遞給 mcrouter,然后 mcrouter 作為代理將這些請求發(fā)國際快遞數(shù)千個上游 memcached 服務(wù)器。這種架構(gòu)能使我們在完全托管的緩存服務(wù)器集群中構(gòu)建強(qiáng)大功能的同時,對客戶端服務(wù)保持完全透明。
盡管從 Pinterest 早期開始,memcached 一直就是 Pinterest 基礎(chǔ)架構(gòu)的一部分,我們對其客戶端的拓展策略在這些年來也在不斷進(jìn)化。具體來說,路由和服務(wù)發(fā)現(xiàn)在最開始是通過客戶端庫完成的(這其實很脆弱,而且它還與二進(jìn)制部署緊密耦合)。然后,該方法被內(nèi)部構(gòu)建的一個路由代理取代(該路由代理沒有提供用于高可用性的基礎(chǔ)功能),最終被 mcrouter 取代。
3計算和存儲效率
Memcached 的效率很高:單個 r5.2xlarge EC2 實例每秒能支持超過 10 萬個請求和數(shù)以萬計的并發(fā) TCP 連接,同時不會顯著地增加客戶端的延遲。這使 Memcached 成為 Pinterest 吞吐效率最高的生產(chǎn)服務(wù)。這部分歸功于編寫良好的 C 語言代碼以及其體系結(jié)構(gòu)。該體系結(jié)構(gòu)利用了多個工作線程,每個工作線程獨(dú)立地運(yùn)行由”libevent“驅(qū)動的事件循環(huán),來支持傳入的連接。
在 Pinterest,Memcached 的 extstore 在存儲效率方面取得了巨大的成功,具體的用例包括可視搜索以及個性化搜索推薦引擎。extstore 擴(kuò)展了緩存數(shù)據(jù)容量,在 DRAM 之外增加了掛載在本地的 NVMe 閃存盤,從而將每個實例的可用存儲容量從約 55 GB(r5.2xlarge)增加到將近 1.7 TB(i3.2xlarge),而實例成本只是略有增長。
在實踐中,extstore 大大優(yōu)化了數(shù)據(jù)用量受限的用例,盡管 DRAM 和 SSD 響應(yīng)時間之間有幾個數(shù)量級的差異,extstore 卻沒有犧牲端到端延遲。extstore 的內(nèi)置調(diào)整工具使我們能找到一個平衡了磁盤 I/O、磁盤到內(nèi)存的重新緩存速率、壓縮頻率和壓縮程度以及客戶端尾部響應(yīng)時間的最佳平衡點(diǎn)。
4高可用性
Pinterest 的所有基礎(chǔ)架構(gòu)系統(tǒng)都是高可用的,我們的緩存系統(tǒng)也不例外。通過利用 mcrouter 提供的豐富的路由功能,我們的 memcached 集群有著一系列的容錯功能:
針對部分失控或完全宕機(jī)的服務(wù)器的自動故障轉(zhuǎn)移。網(wǎng)絡(luò)本身就是不可靠且有損耗的。我們整個緩存架構(gòu)假定這是不可改變的事實,在服務(wù)器不可用或速度緩慢時也可以保持可用性。幸運(yùn)的是,緩存數(shù)據(jù)在本質(zhì)上是瞬態(tài)的,這放寬了對數(shù)據(jù)持久性的要求,而持久性存儲(例如數(shù)據(jù)庫)對數(shù)據(jù)持久性的要求很高。在 Pinterest 中,mcrouter 會自動地在請求響應(yīng)緩慢時,或者某個服務(wù)器宕機(jī)時故障轉(zhuǎn)移到全局共享集群,并且 mcrouter 還會通過主動的運(yùn)行狀況檢查將服務(wù)器加入服務(wù)池中。通過自動故障轉(zhuǎn)移以及一系列的單個服務(wù)器故障的代理層檢測,運(yùn)維人員可以在最短的生產(chǎn)停機(jī)時間內(nèi)識別并更換行為異常的服務(wù)器。
通過透明的跨區(qū)域復(fù)制實現(xiàn)數(shù)據(jù)冗余。我們的關(guān)鍵用例是跨不同的 AWS 可用區(qū)(AZ)進(jìn)行多集群復(fù)制的。這樣就可以在完全丟失可用區(qū)的情況下實現(xiàn)零停機(jī)時間:所有請求都將自動重定向到位于另一個可用區(qū)中的運(yùn)行狀況良好的副本節(jié)點(diǎn)(replica),在該副本節(jié)點(diǎn)中有完整的數(shù)據(jù)冗余副本。
與實際生產(chǎn)流量隔離的影子測試。mcrouter 中的流量路由功能使我們可以進(jìn)行各種彈性測試,包括集群到集群的暗流量以及在實際生產(chǎn)請求中人為加入的延遲和停機(jī)時間的測試,而不會影響生產(chǎn)。
5負(fù)載均衡和數(shù)據(jù)分片
分布式系統(tǒng)的關(guān)鍵功能之一是水平可伸縮性,這是一種可以橫向擴(kuò)展而不是縱向擴(kuò)展以適應(yīng)額外的流量增長的能力。在 Pinterest,我們絕大多數(shù)的緩存工作量都是受吞吐量限制的,這需要集群中實例的數(shù)量與請求的數(shù)量大致呈線性比例關(guān)系。然而,memcached 本身是一個非常簡單的鍵值存儲,它本身并不會知道集群中的其他節(jié)點(diǎn)。那么每秒數(shù)億個請求是如果通過網(wǎng)絡(luò)發(fā)國際快遞正確的服務(wù)器上的呢
Mcrouter 通過對每個請求的緩存鍵運(yùn)用哈希算法,來將請求確定性地發(fā)國際快遞池中的某一個主機(jī)。這對于在服務(wù)器之間平均分配流量非常有幫助,但是 memcached 有一個獨(dú)特的要求,即它的集群需要任意可伸縮性,也就是說運(yùn)維人員要能夠自由地根據(jù)不斷變化的流量需求,來調(diào)整集群容量,同時最大程度地減少客戶端的影響。
一致性哈希確保了在合格分片的總數(shù)增加或減少時,大多數(shù)鍵空間分區(qū)也可以映射到同一服務(wù)器。高度集中和可預(yù)測的命中率影響,允許系統(tǒng)在擴(kuò)展時對客戶端透明,從而防止容量的小范圍變化導(dǎo)致集群命中率出現(xiàn)災(zāi)難性下降。
一致性哈希算法保證了當(dāng)單一節(jié)點(diǎn)加入現(xiàn)有集群時,大多數(shù)鍵值空間所分配的服務(wù)器不變
客戶端路由層將單個鍵值前綴映射到一個或多個這樣的一致哈希池,這些一致哈希池位于某個路由策略之后,包括跨可用區(qū)復(fù)制集群的可用區(qū)親和性偏好路由,針對位于基于閃存的容量集群后方的基于內(nèi)存集群的 L1L2 路由(具有穿透)等。這樣可以隔離流量,從而按客戶端的用例情況來分配容量,并且可以確保來自 Pinterest 集群中任何客戶端機(jī)器的一致緩存路由行為。
6優(yōu)劣權(quán)衡和我們的考慮
所有足夠復(fù)雜的基礎(chǔ)架構(gòu)系統(tǒng)都具有一個共同特點(diǎn):充滿了(往往非常細(xì)微的)優(yōu)劣權(quán)衡。在構(gòu)建和擴(kuò)展我們的緩存系統(tǒng)的過程中,我們權(quán)衡了許多方案的成本和收益。如下是最重要的幾點(diǎn):
中間代理層會產(chǎn)生大量的計算和 I/O 開銷,特別是對于具有嚴(yán)格的延遲 SLO 并且注重性能的系統(tǒng)而言。但是,mcrouter 所提供的高可用性抽象,靈活的路由行為以及許多其他功能遠(yuǎn)遠(yuǎn)比性能損耗更重要。
全局共享的代理配置會給更改部署帶來風(fēng)險,因為在部署時,所有控制平面更改都會應(yīng)用到 Pinterest 的含有數(shù)萬臺機(jī)器的整個集群中。然而,這也確保了全局一致的 memcached 集群拓?fù)浜团c之相關(guān)的路由策略,無論客戶端通過何種方式在 Pinterest 內(nèi)何處進(jìn)行部署。
我們管理維護(hù)著約一百個不同的 Memcached 集群,其中,許多集群具有不同的租戶(tenancy)特征(專用與共享)、硬件實例類型和路由策略。雖然這給團(tuán)隊帶來了相當(dāng)大的運(yùn)維負(fù)擔(dān),但它也允許每個用例達(dá)到有效的性能和可用性隔離,同時還能通過選擇最適合某個特定工作負(fù)載使用情況的參數(shù)和實例類型來達(dá)到效率優(yōu)化。
在大多數(shù)情況下,一致性哈希方案在上游服務(wù)器池之間進(jìn)行負(fù)載分配的效果很好,即使在鍵空間由類似前綴的鍵簇組成的情況下也是如此。但是,這不能解決熱鍵問題——特定鍵集的請求量的異常增加仍然會產(chǎn)生因服務(wù)器集群中的熱分片所導(dǎo)致的負(fù)載不平衡的問題。
7展望
展望未來,我們希望繼續(xù)提高 Pinterest 緩存基礎(chǔ)架構(gòu)的效率、可靠性和性能。我們的努力包括當(dāng)前的一些實驗性項目,例如將 memcached 核心直接嵌入到主機(jī)應(yīng)用程序進(jìn)程中,以處理性能關(guān)鍵的用例(這能使 memcached 與服務(wù)流程共享內(nèi)存空間,并消除網(wǎng)絡(luò)和 I/O 開銷)。此外還有可靠性項目,例如設(shè)計一個穩(wěn)健的多區(qū)域冗余解決方案。
原文鏈接:
https://medium.com/pinterestengineering/scalingcacheinfrastructureatpinterest422d6d294ece
特別聲明:以上文章內(nèi)容僅代表作者本人觀點(diǎn),不代表ESG跨境電商觀點(diǎn)或立場。如有關(guān)于作品內(nèi)容、版權(quán)或其它問題請于作品發(fā)表后的30日內(nèi)與ESG跨境電商聯(lián)系。
二維碼加載中...
使用微信掃一掃登錄
使用賬號密碼登錄
平臺顧問
微信掃一掃
馬上聯(lián)系在線顧問
小程序
ESG跨境小程序
手機(jī)入駐更便捷
返回頂部