Redis中存儲億級鍵值對

遷移系統時,有時你必須創建一個小腳手架。咱們最近不得不這樣作:在Instagram上,於遺留緣由,咱們須要將大約3億張照片映射到建立它們的用戶的ID,以便了解要查詢的分片(請參閱有關 咱們的更多信息) 分片設置)。雖然全部客戶端和API應用程序都已更新並向咱們返回 完整信息,但仍有許多人緩存的舊數據。咱們須要一個解決方案:
  1. 查找鍵並快速返回值
  2. 將數據存在內存中,理想狀況下是在EC2高內存類型(17GB或34GB,而不是68GB實例類型)中
  3. 兼容咱們現有的基礎結構
  4. 持久化,以便在服務器宕機時咱們沒必要重跑
這個問題的一個簡單解決方案是將它們簡單地存儲在數據庫行中,其中包含「Media ID」和「User ID」列。可是,考慮到這些ID從未更新(僅插入),SQL數據庫彷佛是多餘的。不須要事務,也和其餘表沒有任何關係。
相反,咱們轉向 Redis,一個咱們在Instagram上普遍使用的鍵值存儲。Redis是一把key-value的瑞士軍刀; 而不是像Memcached那樣普通的「Set key,get key」機制,它提供了強大的聚合類型,若有序集合和列表。它具備可配置的持久化模型,其中後臺以指定的時間間隔保存,而且能夠設置主從同步。咱們全部的Redis都在主從服務器上運行,從服務器設置爲每分鐘保存到磁盤。
首先,咱們決定以最簡單的方式使用Redis:對於每一個ID,key將是媒體ID,值將是用戶ID:
SET media:1155315 939
GET media:1155315
> 939複製代碼
然而,在對此解決方案進行模型設計時,咱們發現Redis須要大約70 MB才存儲1,000,000個key。根據咱們須要的300,000,000,大約要21GB的數據,已經比亞馬遜EC2上的17GB實例類型更大。
咱們向Redis的核心開發人員之一,樂於助人的 Pieter Noordhuis提出了意見,他建議咱們使用Redis哈希。Redis中的哈希是字典,能夠很是有效地編碼在內存中; Redis設置'hash-zipmap-max-entries'配置散列能夠有效編碼的最大條目數。咱們發現這個設置最好在1000左右; 任何更高的配置HSET命令都會引發很明顯的CPU使用。有關更多詳細信息,你能夠 查看zipmap源文件
爲了用散列類型,咱們將全部媒體ID分配到1000個桶中(咱們只取ID,除以1000並丟棄剩餘部分)。這決定了屬於哪一個鍵,接下來在該鍵的散列中,Media ID是散列中的查找鍵,用戶ID是值。一個例子,給定媒體ID爲1155315,它屬於桶1155(1155315/1000 = 1155):
HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
> "939"複製代碼
內存差別很是驚人; 使用咱們的1,000,000個key(編碼爲1000個哈希,每一個1000個子key),Redis只須要16MB存儲。擴展到3億個key,總數不到5GB,事實上,它甚至適合亞馬遜上更便宜的m1.large實例類型,大約是咱們本來須要的更大實例成本的1/3。最重要的是,散列中的查找仍然是O(1),很是快。
若是你對嘗試這些感興趣,咱們用於運行這些測試的腳本 能夠做爲GitHub上的Gist(咱們在腳本中有Memcached用於比較, 百萬個key須要大約52MB)。
更多文章歡迎訪問: http://www.apexyun.com
公衆號:銀河系1號
聯繫郵箱:public@space-explore.com
(未經贊成,請勿轉載)    
相關文章
相關標籤/搜索