揭秘!Netflix百萬用戶的鍵值數(shù)據(jù)抽象層及其設(shè)計(jì)理念
在 Netflix,我們?yōu)閿?shù)百萬用戶提供無縫、高質(zhì)量的流媒體體驗(yàn)的能力取決于強(qiáng)大的全球后端基礎(chǔ)設(shè)施。該基礎(chǔ)設(shè)施的核心是我們使用多個(gè)在線分布式數(shù)據(jù)庫(kù),例如Apache Cassandra,這是一種以高可用性和可擴(kuò)展性而聞名的 NoSQL 數(shù)據(jù)庫(kù)。Cassandra 是 Netflix 內(nèi)各種用例的支柱,從用戶注冊(cè)和存儲(chǔ)觀看歷史記錄到支持實(shí)時(shí)分析和直播。
隨著新鍵值數(shù)據(jù)庫(kù)的引入和服務(wù)所有者推出新用例,我們遇到了許多數(shù)據(jù)存儲(chǔ)誤用方面的挑戰(zhàn)。首先,開發(fā)人員很難在這種跨多個(gè)商店的復(fù)雜全球部署中推斷一致性、耐用性和性能。其次,開發(fā)人員必須不斷重新學(xué)習(xí)新的數(shù)據(jù)建模實(shí)踐和常見但關(guān)鍵的數(shù)據(jù)訪問模式。這些挑戰(zhàn)包括尾部延遲和冪等性、管理具有多行的“寬”分區(qū)、處理單個(gè)大型“胖”列以及響應(yīng)分頁(yè)緩慢。此外,與多個(gè)本機(jī)數(shù)據(jù)庫(kù) API 的緊密耦合(這些 API 不斷發(fā)展,有時(shí)會(huì)引入向后不兼容的更改)導(dǎo)致整個(gè)組織都在進(jìn)行工程工作以維護(hù)和優(yōu)化我們的微服務(wù)的數(shù)據(jù)訪問。
為了克服這些挑戰(zhàn),我們開發(fā)了一種基于數(shù)據(jù)網(wǎng)關(guān)平臺(tái)的整體方法。這種方法促成了幾種基礎(chǔ)抽象服務(wù)的創(chuàng)建,其中最成熟的是我們的鍵值 (KV) 數(shù)據(jù)抽象層 (DAL)。這種抽象簡(jiǎn)化了數(shù)據(jù)訪問,增強(qiáng)了我們基礎(chǔ)設(shè)施的可靠性,并使我們能夠以最少的開發(fā)人員工作量支持 Netflix 要求的廣泛用例。
在這篇文章中,我們深入探討了 Netflix 的 KV 抽象的工作原理、指導(dǎo)其設(shè)計(jì)的架構(gòu)原則、我們?cè)跀U(kuò)展不同用例時(shí)面臨的挑戰(zhàn),以及使我們能夠?qū)崿F(xiàn) Netflix 全球運(yùn)營(yíng)所需的性能和可靠性的技術(shù)創(chuàng)新。
鍵值服務(wù)
引入 KV 數(shù)據(jù)抽象服務(wù)是為了解決我們?cè)诜植际綌?shù)據(jù)庫(kù)中面臨的數(shù)據(jù)訪問模式的持續(xù)挑戰(zhàn)。我們的目標(biāo)是構(gòu)建一個(gè)多功能且高效的數(shù)據(jù)存儲(chǔ)解決方案,可以處理各種各樣的用例,從最簡(jiǎn)單的哈希圖到更復(fù)雜的數(shù)據(jù)結(jié)構(gòu),同時(shí)確保高可用性、可調(diào)一致性和低延遲。
數(shù)據(jù)模型
KV 抽象的核心是兩級(jí)映射 架構(gòu)。第一級(jí)是散列字符串ID(主鍵),第二級(jí)是字節(jié)鍵值對(duì)的有序映射。此模型支持簡(jiǎn)單和復(fù)雜的數(shù)據(jù)模型,在靈活性和效率之間取得平衡。
HashMap <String, SortedMap <Bytes, Bytes>>
Records對(duì)于結(jié)構(gòu)化或按時(shí)間順序排列的復(fù)雜數(shù)據(jù)模型Events,這種兩級(jí)方法可以有效地處理分層結(jié)構(gòu),從而允許一起檢索相關(guān)數(shù)據(jù)。對(duì)于更簡(jiǎn)單的用例,它還表示平面鍵值Maps(例如id → {"" → value})或命名Sets(例如id → {key → ""})。這種適應(yīng)性使 KV 抽象可用于數(shù)百種不同的用例,使其成為在 Netflix 等大型基礎(chǔ)設(shè)施中管理簡(jiǎn)單和復(fù)雜數(shù)據(jù)模型的多功能解決方案。
KV 數(shù)據(jù)可以在高層次上進(jìn)行可視化,如下圖所示,其中顯示了三條記錄。
圖片
message Item (
Bytes key,
Bytes value,
Metadata metadata,
Integer chunk
)
數(shù)據(jù)庫(kù)無關(guān)的抽象
KV 抽象旨在隱藏底層數(shù)據(jù)庫(kù)的實(shí)現(xiàn)細(xì)節(jié),為應(yīng)用程序開發(fā)人員提供一致的接口,而不管該用例的最佳存儲(chǔ)系統(tǒng)是什么。雖然 Cassandra 就是一個(gè)例子,但該抽象適用于多種數(shù)據(jù)存儲(chǔ),如EVCache、DynamoDB、RocksDB等……
例如,當(dāng)使用 Cassandra 實(shí)現(xiàn)時(shí),抽象利用了 Cassandra 的分區(qū)和聚類功能。記錄ID充當(dāng)分區(qū)鍵,項(xiàng)目鍵充當(dāng)聚類列:
圖片
Cassandra 中此結(jié)構(gòu)對(duì)應(yīng)的數(shù)據(jù)定義語(yǔ)言 (DDL) 是:
CREATE TABLE IF NOT EXISTS <ns>.<table> (
id text,
key blob,
value blob,
value_metadata blob,
PRIMARY KEY (id, key))
WITH CLUSTERING ORDER BY (key <ASC|DESC>)
命名空間:邏輯和物理配置
命名空間定義了數(shù)據(jù)的存儲(chǔ)位置和存儲(chǔ)方式,在抽象底層存儲(chǔ)系統(tǒng)的同時(shí)提供邏輯和物理分離。它還充當(dāng)訪問模式(例如一致性或延遲目標(biāo))的中央配置。每個(gè)命名空間可以使用不同的后端:Cassandra、EVCache 或多個(gè)后端的組合。這種靈活性使我們的數(shù)據(jù)平臺(tái)能夠根據(jù)性能、耐用性和一致性需求將不同的用例路由到最合適的存儲(chǔ)系統(tǒng)。開發(fā)人員只需提供他們的數(shù)據(jù)問題,而不是數(shù)據(jù)庫(kù)解決方案!
在此示例配置中,ngsegment命名空間由 Cassandra 集群和 EVCache 緩存層支持,從而實(shí)現(xiàn)高度耐用的持久存儲(chǔ)和低延遲點(diǎn)讀取。
"persistence_configuration":[
{
"id":"PRIMARY_STORAGE",
"physical_storage": {
"type":"CASSANDRA",
"cluster":"cassandra_kv_ngsegment",
"dataset":"ngsegment",
"table":"ngsegment",
"regions": ["us-east-1"],
"config": {
"consistency_scope": "LOCAL",
"consistency_target": "READ_YOUR_WRITES"
}
}
},
{
"id":"CACHE",
"physical_storage": {
"type":"CACHE",
"cluster":"evcache_kv_ngsegment"
},
"config": {
"default_cache_ttl": 180s
}
}
]
KV 抽象的關(guān)鍵 API
為了支持不同的用例,KV 抽象提供了四個(gè)基本的 CRUD API:
PutItems — 將一個(gè)或多個(gè)項(xiàng)目寫入記錄
該P(yáng)utItemsAPI是一個(gè)upsert操作,它可以在兩級(jí)map結(jié)構(gòu)中插入新數(shù)據(jù)或者更新現(xiàn)有數(shù)據(jù)。
message PutItemRequest (
IdempotencyToken idempotency_token,
string namespace,
string id,
List<Item> items
)
如您所見,請(qǐng)求包括命名空間、記錄 ID、一個(gè)或多個(gè)項(xiàng)目以及冪等性令牌,以確保重試相同的寫入是安全的。可以通過暫存塊然后使用適當(dāng)?shù)脑獢?shù)據(jù)(例如塊數(shù))提交它們來寫入分塊數(shù)據(jù)。
**GetItems **— 從記錄中讀取一個(gè)或多個(gè)項(xiàng)目
該GetItemsAPI 提供了一種結(jié)構(gòu)化且自適應(yīng)的方法,可使用 ID、謂詞和選擇機(jī)制來獲取數(shù)據(jù)。這種方法既能滿足檢索大量數(shù)據(jù)的需求,又能滿足嚴(yán)格的性能和可靠性服務(wù)級(jí)別目標(biāo) (SLO)。
message GetItemsRequest (
String namespace,
String id,
Predicate predicate,
Selection selection,
Map<String, Struct> signals
)
其中GetItemsRequest包括幾個(gè)關(guān)鍵參數(shù):
- 命名空間:指定邏輯數(shù)據(jù)集或表
- Id:標(biāo)識(shí)頂級(jí) HashMap 中的條目
- 謂詞:過濾匹配的項(xiàng)目,可以檢索所有項(xiàng)目 ( match_all)、特定項(xiàng)目 ( match_keys) 或某個(gè)范圍 ( match_range)
- 選擇:縮小返回的響應(yīng)范圍,例如page_size_bytes分頁(yè)、item_limit限制頁(yè)面中的項(xiàng)目總數(shù)和include/exclude或從響應(yīng)中包含或排除較大的值
- **信號(hào):**提供帶內(nèi)信令來指示客戶端功能,例如支持客戶端壓縮或分塊。
該GetItemResponse消息包含匹配的數(shù)據(jù):
message GetItemResponse (
List<Item> items,
Optional<String> next_page_token
)
- 項(xiàng)目:根據(jù)請(qǐng)求中定義Predicate檢索到的項(xiàng)目列表。Selection
- 下一頁(yè)標(biāo)記:可選標(biāo)記,用于指示后續(xù)讀取的位置(如果需要),這對(duì)于處理跨多個(gè)請(qǐng)求的大型數(shù)據(jù)集至關(guān)重要。分頁(yè)是有效管理數(shù)據(jù)檢索的關(guān)鍵組件,尤其是在處理可能超出典型響應(yīng)大小限制的大型數(shù)據(jù)集時(shí)。
DeleteItems — 從記錄中刪除一個(gè)或多個(gè)項(xiàng)目
該DeleteItemsAPI 提供了靈活的數(shù)據(jù)刪除選項(xiàng),包括記錄級(jí)、項(xiàng)目級(jí)和范圍刪除——同時(shí)支持冪等性。
message DeleteItemsRequest (
IdempotencyToken idempotency_token,
String namespace,
String id,
Predicate predicate
)
就像在 API 中一樣GetItems,Predicate允許一次處理一個(gè)或多個(gè)項(xiàng)目:
- 記錄級(jí)刪除(match_all):無論記錄中的項(xiàng)目數(shù)有多少,都會(huì)以恒定的延遲刪除整個(gè)記錄。
- 項(xiàng)目范圍刪除(match_range):這將刪除記錄中的一系列項(xiàng)目。對(duì)于保留“n 個(gè)最新”或前綴路徑刪除很有用。
- 項(xiàng)目級(jí)刪除(match_keys):刪除一個(gè)或多個(gè)單獨(dú)的項(xiàng)目。
某些存儲(chǔ)引擎(任何推遲真正刪除的存儲(chǔ))如 Cassandra 因墓碑和壓縮開銷而難以處理大量刪除。鍵值優(yōu)化記錄和范圍刪除,以便為操作生成單個(gè)墓碑 — 您可以在關(guān)于刪除和墓碑中了解有關(guān)墓碑的更多信息。
項(xiàng)目級(jí)刪除會(huì)創(chuàng)建許多墓碑,但 KV 通過基于TTL 的抖動(dòng)刪除隱藏了存儲(chǔ)引擎的復(fù)雜性。項(xiàng)目元數(shù)據(jù)不會(huì)立即刪除,而是更新為已過期,并使用隨機(jī)抖動(dòng)的 TTL 來錯(cuò)開刪除。此技術(shù)可維護(hù)讀取分頁(yè)保護(hù)。雖然這不能完全解決問題,但它可以減少負(fù)載峰值并有助于在壓縮趕上時(shí)保持一致的性能。這些策略有助于保持系統(tǒng)性能、減少讀取開銷并通過最大限度地減少刪除的影響來滿足 SLO。
復(fù)雜的 Mutate 和 Scan API
除了對(duì)單個(gè)記錄進(jìn)行簡(jiǎn)單的 CRUD 之外,KV 還支持通過MutateItems和ScanItemsAPI 進(jìn)行復(fù)雜的多項(xiàng)目和多記錄變更和掃描。PutItems還支持通過分塊協(xié)議在單個(gè)記錄中對(duì)大型 blob 數(shù)據(jù)進(jìn)行原子寫入Item。這些復(fù)雜的 API 需要仔細(xì)考慮以確保可預(yù)測(cè)的線性低延遲,我們將在以后的文章中分享有關(guān)其實(shí)現(xiàn)的詳細(xì)信息。
可靠且可預(yù)測(cè)的性能設(shè)計(jì)理念
冪等性可以解決尾部延遲問題
為了確保數(shù)據(jù)完整性PutItems,DeleteItemsAPI 使用冪等性令牌,它可以唯一地標(biāo)識(shí)每個(gè)可變操作,并保證操作按邏輯順序執(zhí)行,即使由于延遲原因而進(jìn)行對(duì)沖或重試也是如此。這在 Cassandra 等最后寫入獲勝的數(shù)據(jù)庫(kù)中尤其重要,因?yàn)榇_保請(qǐng)求的正確順序和重復(fù)數(shù)據(jù)刪除至關(guān)重要。
在 Key-Value 抽象中,冪等性 token 包含生成時(shí)間戳和隨機(jī) nonce token。后端存儲(chǔ)引擎可能需要其中一個(gè)或兩個(gè)來刪除重復(fù)的突變。
message IdempotencyToken (
Timestamp generation_time,
String token
)
在 Netflix,客戶端生成的單調(diào)令牌因其可靠性而受到青睞,尤其是在網(wǎng)絡(luò)延遲可能影響服務(wù)器端令牌生成的環(huán)境中。這將客戶端提供的單調(diào)generation_time時(shí)間戳與 128 位隨機(jī) UUID相結(jié)合token。雖然基于時(shí)鐘的令牌生成可能會(huì)受到時(shí)鐘偏差的影響,但我們?cè)?EC2 Nitro 實(shí)例上的測(cè)試表明偏差很小(不到 1 毫秒)。在某些需要更強(qiáng)排序的情況下,可以使用 Zookeeper 等工具生成區(qū)域唯一令牌,或者可以使用交易 ID 等全局唯一令牌。
下圖展示了我們?cè)?Cassandra 集群上觀察到的時(shí)鐘偏差,表明該技術(shù)在可直接訪問高質(zhì)量時(shí)鐘的現(xiàn)代云虛擬機(jī)上是安全的。為了進(jìn)一步保持安全性,KV 服務(wù)器拒絕帶有較大偏移的令牌的寫入,這既可以防止易受這些攻擊的存儲(chǔ)引擎出現(xiàn)靜默寫入丟棄(寫入的時(shí)間戳遠(yuǎn)在過去)和不可變的末日石(寫入的時(shí)間戳遠(yuǎn)在未來)。
圖片
通過分塊處理大數(shù)據(jù)
鍵值對(duì)還旨在高效處理大型數(shù)據(jù)塊,這是傳統(tǒng)鍵值對(duì)存儲(chǔ)的常見挑戰(zhàn)。數(shù)據(jù)庫(kù)通常面臨每個(gè)鍵或分區(qū)可存儲(chǔ)的數(shù)據(jù)量限制。為了解決這些限制,KV 使用透明分塊來高效管理大數(shù)據(jù)。
對(duì)于小于 1 MiB 的項(xiàng)目,數(shù)據(jù)直接存儲(chǔ)在主后備存儲(chǔ)(例如 Cassandra)中,以確保快速高效的訪問。但是,對(duì)于較大的項(xiàng)目,只有 id 、 key和元數(shù)據(jù)存儲(chǔ)在主存儲(chǔ)中,而實(shí)際數(shù)據(jù)被分成較小的塊并單獨(dú)存儲(chǔ)在塊存儲(chǔ)中。此塊存儲(chǔ)也可以是 Cassandra,但具有針對(duì)處理大值優(yōu)化的不同分區(qū)方案。冪等性令牌將所有這些寫入綁定到一個(gè)原子操作中。
通過將大型項(xiàng)目拆分成塊,我們確保延遲與數(shù)據(jù)大小成線性比例,從而使系統(tǒng)既可預(yù)測(cè)又高效。未來的博客文章將更詳細(xì)地描述分塊架構(gòu),包括其復(fù)雜性和優(yōu)化策略。
客戶端壓縮
KV 抽象利用客戶端有效負(fù)載壓縮來優(yōu)化性能,尤其是對(duì)于大數(shù)據(jù)傳輸。雖然許多數(shù)據(jù)庫(kù)都提供服務(wù)器端壓縮,但在客戶端處理壓縮可以減少昂貴的服務(wù)器 CPU 使用率、網(wǎng)絡(luò)帶寬和磁盤 I/O。在我們的一個(gè)部署中,這有助于支持 Netflix 的搜索,啟用客戶端壓縮可將有效負(fù)載大小減少 75%,從而顯著提高成本效率。
更智能的分頁(yè)
我們選擇以字節(jié)為單位的有效負(fù)載大小作為每個(gè)響應(yīng)頁(yè)面的限制,而不是項(xiàng)目數(shù)量,因?yàn)檫@使我們能夠提供可預(yù)測(cè)的操作 SLO。例如,我們可以在 2 MiB 頁(yè)面讀取上提供個(gè)位數(shù)毫秒的 SLO。相反,使用每頁(yè)項(xiàng)目數(shù)作為限制會(huì)導(dǎo)致不可預(yù)測(cè)的延遲,因?yàn)轫?xiàng)目大小存在很大差異。如果每頁(yè) 10 個(gè)項(xiàng)目的請(qǐng)求是 1 KiB 而不是 1 MiB,則延遲可能會(huì)有很大差異。
使用字節(jié)作為限制會(huì)帶來挑戰(zhàn),因?yàn)楹苌儆泻髠浯鎯?chǔ)支持基于字節(jié)的分頁(yè);大多數(shù)數(shù)據(jù)存儲(chǔ)使用結(jié)果數(shù)(例如 DynamoDB 和 Cassandra 按項(xiàng)目數(shù)或行數(shù)進(jìn)行限制)。為了解決這個(gè)問題,我們對(duì)后備存儲(chǔ)的初始查詢使用靜態(tài)限制,使用此限制進(jìn)行查詢,然后處理結(jié)果。如果需要更多數(shù)據(jù)來滿足字節(jié)限制,則將執(zhí)行其他查詢,直到滿足限制,丟棄多余的結(jié)果并生成頁(yè)面令牌。
這種靜態(tài)限制可能會(huì)導(dǎo)致效率低下,結(jié)果中的一個(gè)大項(xiàng)可能會(huì)導(dǎo)致我們丟棄許多結(jié)果,而小項(xiàng)可能需要多次迭代才能填滿一頁(yè),從而導(dǎo)致讀取放大。為了緩解這些問題,我們實(shí)現(xiàn)了自適應(yīng)分頁(yè),可根據(jù)觀察到的數(shù)據(jù)動(dòng)態(tài)調(diào)整限制。
自適應(yīng)分頁(yè)
當(dāng)發(fā)出初始請(qǐng)求時(shí),將在存儲(chǔ)引擎中執(zhí)行查詢并檢索結(jié)果。當(dāng)消費(fèi)者處理這些結(jié)果時(shí),系統(tǒng)會(huì)跟蹤消費(fèi)的項(xiàng)目數(shù)量和使用的總大小。這些數(shù)據(jù)有助于計(jì)算近似的項(xiàng)目大小,該大小存儲(chǔ)在頁(yè)面令牌中。對(duì)于后續(xù)的頁(yè)面請(qǐng)求,這些存儲(chǔ)的信息允許服務(wù)器對(duì)底層存儲(chǔ)應(yīng)用適當(dāng)?shù)南拗疲瑥亩鴾p少不必要的工作并最大限度地減少讀取放大。
雖然此方法對(duì)于后續(xù)頁(yè)面請(qǐng)求有效,但對(duì)于初始請(qǐng)求會(huì)發(fā)生什么情況?除了將項(xiàng)目大小信息存儲(chǔ)在頁(yè)面令牌中之外,服務(wù)器還會(huì)估算給定命名空間的平均項(xiàng)目大小并將其緩存在本地。此緩存估算值可幫助服務(wù)器為初始請(qǐng)求在后備存儲(chǔ)上設(shè)置更優(yōu)化的限制,從而提高效率。服務(wù)器會(huì)根據(jù)最近的查詢模式或其他因素不斷調(diào)整此限制以保持其準(zhǔn)確性。對(duì)于后續(xù)頁(yè)面,服務(wù)器會(huì)同時(shí)使用緩存數(shù)據(jù)和頁(yè)面令牌中的信息來微調(diào)限制。
圖片
除了自適應(yīng)分頁(yè)之外,如果服務(wù)器檢測(cè)到處理請(qǐng)求有可能超出請(qǐng)求的延遲 SLO,則還有一種機(jī)制可以提前發(fā)送響應(yīng)。
例如,假設(shè)客戶端提交的GetItems請(qǐng)求每頁(yè)限制為 2 MiB,最大端到端延遲限制為 500 毫秒。在處理此請(qǐng)求時(shí),服務(wù)器會(huì)從后備存儲(chǔ)中檢索數(shù)據(jù)。此特定記錄包含數(shù)千個(gè)小項(xiàng)目,因此收集整頁(yè)數(shù)據(jù)通常需要的時(shí)間超過 500 毫秒的 SLO。如果發(fā)生這種情況,客戶端將收到 SLO 違規(guī)錯(cuò)誤,導(dǎo)致請(qǐng)求失敗,即使沒有任何異常。為了防止這種情況,服務(wù)器會(huì)在獲取數(shù)據(jù)時(shí)跟蹤已用時(shí)間。如果它確定繼續(xù)檢索更多數(shù)據(jù)可能會(huì)違反 SLO,則服務(wù)器將停止處理進(jìn)一步的結(jié)果并返回帶有分頁(yè)令牌的響應(yīng)。
圖片
這種方法可確保請(qǐng)求在 SLO 內(nèi)得到處理,即使未滿足整個(gè)頁(yè)面大小,也能為客戶端提供可預(yù)測(cè)的進(jìn)度。此外,如果客戶端是具有適當(dāng)截止期限的 gRPC 服務(wù)器,則客戶端足夠智能,不會(huì)發(fā)出進(jìn)一步的請(qǐng)求,從而減少無用的工作。
如果您想了解更多信息,Netflix 如何確保高可靠性的在線狀態(tài)系統(tǒng)一文將更詳細(xì)地討論這些技術(shù)以及許多其他技術(shù)。
信號(hào)
KV 使用帶內(nèi)消息傳遞(我們稱之為信令),允許動(dòng)態(tài)配置客戶端,并使其能夠?qū)⑵涔δ軅鬟_(dá)給服務(wù)器。這確保了配置設(shè)置和調(diào)整參數(shù)可以在客戶端和服務(wù)器之間無縫交換。如果沒有信令,客戶端將需要靜態(tài)配置(每次更改都需要重新部署),或者,如果使用動(dòng)態(tài)配置,則需要與客戶端團(tuán)隊(duì)進(jìn)行協(xié)調(diào)。
對(duì)于服務(wù)器端信號(hào),當(dāng)客戶端初始化時(shí),它會(huì)向服務(wù)器發(fā)送握手。服務(wù)器會(huì)以信號(hào)(例如目標(biāo)或最大延遲 SLO)進(jìn)行響應(yīng),從而允許客戶端動(dòng)態(tài)調(diào)整超時(shí)和對(duì)沖策略。然后會(huì)在后臺(tái)定期進(jìn)行握手以保持配置最新。對(duì)于客戶端通信信號(hào),客戶端會(huì)隨每個(gè)請(qǐng)求一起傳達(dá)其功能,例如它是否可以處理壓縮、分塊和其他功能。
圖片
Netflix 的 KV 使用情況
KV 抽象支持 Netflix 的幾個(gè)關(guān)鍵用例,包括:
- 流元數(shù)據(jù):高吞吐量、低延遲訪問流元數(shù)據(jù),確保實(shí)時(shí)個(gè)性化內(nèi)容交付。
- 用戶資料:高效存儲(chǔ)和檢索用戶偏好和歷史記錄,實(shí)現(xiàn)跨設(shè)備的無縫、個(gè)性化體驗(yàn)。
- 消息傳遞:存儲(chǔ)和檢索消息傳遞需求的推送注冊(cè)表,使數(shù)百萬個(gè)請(qǐng)求能夠流經(jīng)。
- 實(shí)時(shí)分析:這可以持久產(chǎn)生大規(guī)模印象并提供對(duì)用戶行為和系統(tǒng)性能的洞察,將數(shù)據(jù)從離線移動(dòng)到在線,反之亦然。
未來的增強(qiáng)功能
展望未來,我們計(jì)劃通過以下方式增強(qiáng) KV 抽象:
- 生命周期管理:對(duì)數(shù)據(jù)保留和刪除的細(xì)粒度控制。
- 匯總:通過將包含多項(xiàng)的記錄匯總為較少的后備行來提高檢索效率的技術(shù)。
- 新的存儲(chǔ)引擎:與更多存儲(chǔ)系統(tǒng)集成以支持新的用例。
- 字典壓縮:在保持性能的同時(shí)進(jìn)一步減少數(shù)據(jù)大小。
結(jié)論
Netflix 的鍵值服務(wù)是一種靈活、經(jīng)濟(jì)高效的解決方案,支持從低流量到高流量場(chǎng)景的各種數(shù)據(jù)模式和用例,包括關(guān)鍵的 Netflix 流媒體用例。簡(jiǎn)單而強(qiáng)大的設(shè)計(jì)使其能夠處理各種數(shù)據(jù)模型,如 HashMap、集合、事件存儲(chǔ)、列表和圖形。它從我們的開發(fā)人員那里抽象了底層數(shù)據(jù)庫(kù)的復(fù)雜性,使我們的應(yīng)用程序工程師能夠?qū)W⒂诮鉀Q業(yè)務(wù)問題,而不是成為每個(gè)存儲(chǔ)引擎及其分布式一致性模型的專家。隨著 Netflix 不斷在在線數(shù)據(jù)存儲(chǔ)方面進(jìn)行創(chuàng)新,KV 抽象仍然是高效、可靠地大規(guī)模管理數(shù)據(jù)的核心組件,為未來的增長(zhǎng)奠定了堅(jiān)實(shí)的基礎(chǔ)。