KV 存儲發展歷程
美團第一代的分布式 KV 存儲如下圖左側的架構所示,相信很多公司都經歷過這個階段。在客戶端內做一致性哈希,在后端部署很多的 Memcached 實例,這樣就實現了最基本的 KV 存儲分布式設計。但這樣的設計存在很明顯的問題:比如在宕機摘除節點時,會丟數據,緩存空間不夠需要擴容,一致性哈希也會丟失一些數據等等,這樣會給業務開發帶來的很多困擾。
隨著 Redis 項目的成熟,美團也引入了 Redis 來解決我們上面提到的問題,進而演進出來如上圖右側這樣一個架構。大家可以看到,客戶端還是一樣,采用了一致性哈希算法,服務器端變成了 Redis 組成的主從結構。當任何一個節點宕機,我們可以通過 Redis 哨兵完成 Failover,實現高可用。但有一個問題還是沒有解決,如果擴縮容的話,一致性哈希仍然會丟數據,那么這個問題該如何解決呢?
這個時候,我們發現有了一個比較成熟的 KV 存儲開源項目:阿里 Tair 。2014年,我們引入了 Tair 來滿足業務 KV 存儲方面的需求。Tair 開源版本的架構主要分成三部分:上圖下邊是存儲節點,存儲節點會上報心跳到它的中心節點,中心節點內部有兩個配置管理節點,會監控所有的存儲節點。當有任何存儲節點宕機或者擴容時,它會做集群拓撲的重新構建。當客戶端啟動時,它會直接從中心節點拉來一個路由表。這個路由表簡單來說就是一個集群的數據分布圖,客戶端根據路由表直接去存儲節點讀寫。針對之前 KV 的擴容丟數據問題,它也有數據遷移機制來保證數據的完整性。
但是,我們在使用的過程中,還遇到了一些其他問題,比如中心節點雖然是主備高可用的,但實際上它沒有類似于分布式仲裁的機制,所以在網絡分割的情況下,它是有可能發生“腦裂”的,這個也給我們的業務造成過比較大的影響。另外,在容災擴容時,也遇到過數據遷移影響到業務可用性的問題。另外,我們之前用過 Redis ,業務會發現 Redis 的數據結構特別豐富,而 Tair 還不支持這些數據結構。雖然我們用 Tair 解決了一些問題,但是 Tair 也無法完全滿足業務需求。畢竟,在美團這樣一個業務規模較大和業務復雜度較高的場景下,很難有開源系統能很好地滿足我們的需求。最終,我們決定在已應用的開源系統之上進行自研。
剛好在2015 年, Redis 官方正式發布了集群版本 Redis Cluster。所以,我們緊跟社區步伐,并結合內部需求做了很多開發工作,演進出了全內存、高吞吐、低延遲的 KV 存儲 Squirrel。另外,基于 Tair,我們還加入了很多自研的功能,演進出持久化、大容量、數據高可靠的 KV 存儲 Cellar 。因為 Tair 的開源版本已經有四五年沒有更新了,所以,Cellar 的迭代完全靠美團自研,而 Redis 社區一直很活躍。總的來說,Squirrel 的迭代是自研和社區并重,自研功能設計上也會盡量與官方架構進行兼容。后面大家可以看到,因為這些不同,Cellar 和 Squirrel 在解決同樣的問題時也選取了不同的設計方案。
這兩個存儲其實都是 KV 存儲領域不同的解決方案。在實際應用上,如果業務的數據量小,對延遲敏感,我們建議大家用 Squirrel ;如果數據量大,對延遲不是特別敏感,我們建議用成本更低的 Cellar 。目前這兩套 KV 存儲系統在美團內部每天的調用量均已突破萬億,它們的請求峰值也都突破了每秒億級。
內存 KV Squirrel 架構和實踐
在開始之前,本文先介紹兩個存儲系統共通的地方。比如分布式存儲的經典問題:數據是如何分布的?這個問題在 KV 存儲領域,就是 Key 是怎么分布到存儲節點上的。這里 Squirrel 跟 Cellar 是一樣的。當我們拿到一個 Key 后,用固定的哈希算法拿到一個哈希值,然后將哈希值對 Slot 數目取模得到一個Slot id,我們兩個 KV 現在都是預分片16384個 Slot 。得到 Slot id 之后,再根據路由表就能查到這個 Slot 存儲在哪個存儲節點上。這個路由表簡單來說就是一個 Slot 到存儲節點的對照表。
KV 數據分布介紹
接下來講一下對高可用架構的認知,個人認為高可用可以從宏觀和微觀兩個角度來看。從宏觀的角度來看,高可用就是指容災怎么做。比如說掛掉了一個節點,你該怎么做?一個機房或者說某個地域的一批機房宕機了,你該怎么做?而從微觀的角度看,高可用就是怎么能保證端到端的高成功率。我們在做一些運維升級或者擴縮容數據遷移的時候,能否做到業務請求的高可用?本文也會從宏觀和微觀兩個角度來分享美團做的一些高可用工作。
Squirrel 架構
上圖就是我們的 Squirrel 架構。中間部分跟 Redis 官方集群是一致的。它有主從的結構, Redis 實例之間通過 Gossip 協議去通信。我們在右邊添加了一個集群調度平臺,包含調度服務、擴縮容服務和高可用服務等,它會去管理整個集群,把管理結果作為元數據更新到 ZooKeeper。我們的客戶端會訂閱 ZooKeeper 上的元數據變更,實時獲取到集群的拓撲狀態,直接在 Redis 集群進行讀寫操作。
Squirrel 節點容災
然后再看一下 Squirrel 容災怎么做。對于 Redis 集群而言,節點宕機已經有完備的處理機制了。官方提供的方案,任何一個節點從宕機到被標記為 FAIL 摘除,一般需要經過 30 秒。主庫的摘除可能會影響數據的完整性,所以,我們需要謹慎一些。但是對于從庫呢?我們認為這個過程完全沒必要。另一點,我們都知道內存的 KV 存儲數據量一般都比較小。對于業務量很大的公司來說,它往往會有很多的集群。如果發生交換機故障,會影響到很多的集群,宕機之后去補副本就會變得非常麻煩。為了解決這兩個問題,我們做了 HA 高可用服務。
它的架構如下圖所示,它會實時監控集群的所有節點。不管是網絡抖動,還是發生了宕機(比如說 Redis 2 ),它可以實時更新 ZooKeeper ,告訴 ZooKeeper 去摘除 Redis 2 ,客戶端收到消息后,讀流量就直接路由到 Redis 3上。如果 Redis 2 只是幾十秒的網絡抖動,過幾十秒之后,如果 HA 節點監控到它恢復后,會把它重新加回。
Squirrel—節點容災
如果過了一段時間,HA 判斷它屬于一個永久性的宕機,HA 節點會直接從 Kubernetes 集群申請一個新的 Redis 4 容器實例,把它加到集群里。此時,拓撲結構又變成了一主兩從的標準結構,HA 節點更新完集群拓撲之后,就會去寫 ZooKeeper 通知客戶端去更新路由,客戶端就能到 Redis 4 這個新從庫上進行讀操作。
通過上述方案,我們把從庫的摘除時間從 30 秒降低到了 5 秒。另外,我們通過 HA 自動申請容器實例加入集群的方式,把宕機補副本變成了一個分鐘級的自動操作,不需要任何人工的介入。
Squirrel 跨地域容災
我們解決了單節點宕機的問題,那么跨地域問題如何解決呢?我們首先來看下跨地域有什么不同。第一,相對于同地域機房間的網絡而言,跨地域專線很不穩定;第二,跨地域專線的帶寬是非常有限且昂貴的。而集群內的復制沒有考慮極端的網絡環境。假如我們把主庫部署到北京,兩個從庫部署在上海,同樣一份數據要在北上專線傳輸兩次,這樣會造成巨大的專線帶寬浪費。另外,隨著業務的發展和演進,我們也在做單元化部署和異地多活架構。用官方的主從同步,滿足不了我們的這些需求。基于此,我們又做了集群間的復制方案。
如上圖所示,這里畫出了北京的主集群以及上海的從集群,我們要做的是通過集群同步服務,把北京主集群的數據同步到上海從集群上。按照流程,首先要向我們的同步調度模塊下發“在兩個集群間建立同步鏈路”的任務,同步調度模塊會根據主從集群的拓撲結構,把主從集群間的同步任務下發到同步集群,同步集群收到同步任務后會扮成 Redis 的 Slave,通過 Redis 的復制協議,從主集群上的從庫拉取數據,包括 RDB以及后續的增量變更。同步機收到數據后會把它轉成客戶端的寫命令,寫到上海從集群的主節點里。
通過這樣的方式,我們把北京主集群的數據同步到了上海的從集群。同樣的,我們要做異地多活也很簡單,再加一個反向的同步鏈路,就可以實現集群間的雙向同步。
接下來我們講一下如何做好微觀角度的高可用,也就是保持端到端的高成功率。對于 Squirrel ,主要講如下三個影響成功率的問題:
數據遷移造成超時抖動。
持久化造成超時抖動。
熱點 Key 請求導致單節點過載。
Squirrel 智能遷移
對于數據遷移,我們主要遇到三個問題:
Redis Cluster 雖然提供了數據遷移能力,但是對于要遷哪些 Slot,Slot 從哪遷到哪,它并不管。
做數據遷移的時候,大家都想越快越好,但是遷移速度過快又可能影響業務正常請求。
Redis 的 Migrate 命令會阻塞工作線程,尤其在遷移大 Value 的時候會阻塞特別久。
為了解決這些問題,我們做了全新的遷移服務。
下面我們按照工作流,講一下它是如何運行的。首先生成遷移任務,這步的核心是“就近原則”,比如說同機房的兩個節點做遷移肯定比跨機房的兩個節點快。遷移任務生成之后,會把任務下發到一批遷移機上。遷移機遷移的時候,有這樣幾個特點:
會在集群內遷出節點間做并發,比如同時給 Redis 1、Redis 3 下發遷移命令。
每個 Migrate 命令會遷移一批 Key。
我們會用監控服務去實時采集客戶端的成功率、耗時,服務端的負載、QPS 等,之后把這個狀態反饋到遷移機上。遷移數據的過程就類似 TCP 慢啟動的過程,它會把速度一直往上加,若出現請求成功率下降等情況,它的速度就會降低,最終遷移速度會在動態平衡中穩定下來,這樣就達到了最快速的遷移,同時又盡可能小地影響業務的正常請求。
接下來,我們看一下大 Value 的遷移,我們實現了一個異步 Migrate 命令,該命令執行時,Redis 的主線程會繼續處理其他的正常請求。如果此時有對正在遷移 Key 的寫請求過來,Redis 會直接返回錯誤。這樣最大限度保證了業務請求的正常處理,同時又不會阻塞主線程。
Squirrel 持久化重構
Redis 主從同步時會生成 RDB。生成 RDB 的過程會調用 Fork 產生一個子進程去寫數據到硬盤,Fork 雖然有操作系統的 COW 機制,但是當內存用量達到 10 G 或 20 G 時,依然會造成整個進程接近秒級的阻塞。這對在線業務來說幾乎是無法接受的。我們也會為數據可靠性要求高的業務去開啟 AOF,而開 AOF 就可能因 IO 抖動造成進程阻塞,這也會影響請求成功率。對官方持久化機制的這兩個問題,我們的解決方案是重構持久化機制。
上圖是我們最新版的 Redis 持久化機制,寫請求會先寫到 DB 里,然后寫到內存 Backlog,這跟官方是一樣的。同時它會把請求發給異步線程,異步線程負責把變更刷到硬盤的 Backlog 里。當硬盤 Backlog 過多時,我們會主動在業務低峰期做一次 RDB ,然后把 RDB 之前生成的 Backlog 刪除。
如果這時候我們要做主從同步,去尋找同步點的時候,該怎么辦?第一步還是跟官方一樣,我們會從內存 Backlog 里找有沒有要求的同步點,如果沒有,我們會去硬盤 Backlog 找同步點。由于硬盤空間很大,硬盤 Backlog 可以存儲特別多的數據,所以很少會出現找不到同步點的情況。如果硬盤 Backlog 也沒有,我們就會觸發一次類似于全量重傳的操作,但這里的全量重傳是不需要當場生成 RDB 的,它可以直接用硬盤已存的 RDB 及其之后的硬盤 Backlog 完成全量重傳。通過這個設計,我們減少了很多的全量重傳。
另外,我們通過控制在低峰區生成 RDB ,減少了很多 RDB 造成的抖動。同時,我們也避免了寫 AOF 造成的抖動。不過,這個方案因為寫 AOF 是完全異步的,所以會比官方的數據可靠性差一些,但我們認為這個代價換來了可用性的提升,這是非常值得的。
Squirrel 熱點 Key
下面看一下 Squirrel 的熱點 Key 解決方案。如下圖所示,普通主、從是一個正常集群中的節點,熱點主、從是游離于正常集群之外的節點。我們看一下它們之間怎么發生聯系。
當有請求進來讀寫普通節點時,節點內會同時做請求 Key 的統計。如果某個 Key 達到了一定的訪問量或者帶寬的占用量,會自動觸發流控以限制熱點 Key 訪問,防止節點被熱點請求打滿。同時,監控服務會周期性的去所有 Redis 實例上查詢統計到的熱點 Key。如果有熱點,監控服務會把熱點 Key 所在 Slot 上報到我們的遷移服務。遷移服務這時會把熱點主從節點加入到這個集群中,然后把熱點 Slot 遷移到這個熱點主從上。因為熱點主從上只有熱點 Slot 的請求,所以熱點 Key的處理能力得到了大幅提升。通過這樣的設計,我們可以做到實時的熱點監控,并及時通過流控去止損;通過熱點遷移,我們能做到自動的熱點隔離和快速的容量擴充。
持久化 KV Cellar 架構和實踐
下面看一下持久化 KV Cellar 的架構和實踐。下圖是我們最新的 Cellar 架構圖。
跟阿里開源的 Tair 主要有兩個架構上的不同。第一個是OB,第二個是 ZooKeeper。我們的 OB 跟 ZooKeeper 的 Observer 是類似的作用,提供 Cellar 中心節點元數據的查詢服務。它可以實時與中心節點的 Master 同步最新的路由表,客戶端的路由表都是從 OB 去拿。這樣做的好處主要有兩點,第一,把大量的業務客戶端跟集群的大腦 Master 做了天然的隔離,防止路由表請求影響集群的管理。第二,因為 OB 只供路由表查詢,不參與集群的管理,所以它可以進行水平擴展,極大地提升了我們路由表的查詢能力。另外,我們引入了 ZooKeeper 做分布式仲裁,解決我剛才提到的 Master、Slave 在網絡分割情況下的“腦裂”問題,并且通過把集群的元數據存儲到 ZooKeeper,我們保證了元數據的高可靠。
Cellar 節點容災
介紹完整體的架構,我們看一下 Cellar 怎么做節點容災。一個集群節點的宕機一般是臨時的,一個節點的網絡抖動也是臨時的,它們會很快地恢復,并重新加入集群。因為節點的臨時離開就把它徹底摘除,并做數據副本補全操作,會消耗大量資源,進而影響到業務請求。所以,我們實現了 Handoff 機制來解決這種節點短時故障帶來的影響。
如上圖所示 ,如果 A 節點宕機了,會觸發 Handoff 機制,這時候中心節點會通知客戶端 A節點發生了故障,讓客戶端把分片 1 的請求也打到 B 上。B 節點正常處理完客戶端的讀寫請求之后,還會把本應該寫入 A 節點的分片 1&2 數據寫入到本地的 Log 中。
如果 A 節點宕機后 3~5 分鐘,或者網絡抖動 30~50 秒之后恢復了,A 節點就會上報心跳到中心節點,中心節點就會通知 B 節點:“ A 節點恢復了,你去把它不在期間的數據傳給它。”這時候,B 節點就會把本地存儲的 Log 回寫到 A 節點上。等到 A 節點擁有了故障期間的全量數據之后,中心節點就會告訴客戶端,A 節點已經徹底恢復了,客戶端就可以重新把分片 1 的請求打回 A 節點。
通過這樣的操作,我們可以做到秒級的快速節點摘除,而且節點恢復后加回,只需補齊少量的增量數據。另外如果 A 節點要做升級,中心節點先通過主動 Handoff 把 A 節點流量切到 B 節點,A 升級后再回寫增量 Log,然后切回流量加入集群。這樣通過主動觸發 Handoff 機制,我們就實現了靜默升級的功能。
Cellar 跨地域容災
下面我介紹一下 Cellar 跨地域容災是怎么做的。Cellar 跟 Squirrel 面對的跨地域容災問題是一樣的,解決方案同樣也是集群間復制。以下圖一個北京主集群、上海從集群的跨地域場景為例,比如說客戶端的寫操作到了北京的主集群 A 節點,A 節點會像正常集群內復制一樣,把它復制到 B 和 D 節點上。同時 A 節點還會把數據復制一份到從集群的 H 節點。H 節點處理完集群間復制寫入之后,它也會做從集群內的復制,把這個寫操作復制到從集群的 I 、K 節點上。通過在主從集群的節點間建立這樣一個復制鏈路,我們完成了集群間的數據復制,并且這個復制保證了最低的跨地域帶寬占用。同樣的,集群間的兩個節點通過配置兩個雙向復制的鏈路,就可以達到雙向同步異地多活的效果。
Cellar 強一致
我們做好了節點容災以及跨地域容災后,業務又對我們提出了更高要求:強一致存儲。我們之前的數據復制是異步的,在做故障摘除時,可能因為故障節點數據還沒復制出來,導致數據丟失。但是對于金融支付等場景來說,它們是不容許數據丟失的。面對這個難題,我們該怎么解決?目前業界主流的解決方案是基于 Paxos 或 Raft 協議的強一致復制。我們最終選擇了 Raft 協議。主要是因為 Raft 論文是非常詳實的,是一篇工程化程度很高的論文。業界也有不少比較成熟的 Raft 開源實現,可以作為我們研發的基礎,進而能夠縮短研發周期。
下圖是現在 Cellar 集群 Raft 復制模式下的架構圖,中心節點會做 Raft 組的調度,它會決定每一個 Slot 的三副本存在哪些節點上。
大家可以看到 Slot 1 在存儲節點 1、2、4 上,Slot 2 在存儲節點2、3、4上。每個 Slot 組成一個 Raft 組,客戶端會去 Raft Leader 上進行讀寫。由于我們是預分配了 16384 個 Slot,所以,在集群規模很小的時候,我們的存儲節點上可能會有數百甚至上千個 Slot 。
這時候如果每個 Raft 復制組都有自己的復制線程、 復制請求和 Log等,那么資源消耗會非常大,寫入性能會很差。所以我們做了 Multi Raft 實現, Cellar 會把同一個節點上所有的 Raft 復制組寫一份 Log,用同一組線程去做復制,不同 Raft 組間的復制包也會按照目標節點做整合,以保證寫入性能不會因 Raft 組過多而變差。Raft 內部其實是有自己的選主機制,它可以控制自己的主節點,如果有任何節點宕機,它可以通過選舉機制選出新的主節點。
那么,中心節點是不是就不需要管理 Raft 組了嗎?不是的。這里講一個典型的場景,如果一個集群的部分節點經過幾輪宕機恢復的過程, Raft Leader 在存儲節點之間會變得極其不均。而為了保證數據的強一致,客戶端的讀寫流量又必須發到 Raft Leader,這時候集群的節點流量會很不均衡。所以我們的中心節點還會做 Raft 組的 Leader 調度。比如說 Slot 1 存儲在節點 1、2、4,并且節點 1 是 Leader。如果節點 1 掛了,Raft 把節點 2 選成了 Leader。然后節點 1 恢復了并重新加入集群,中心節點這時會讓節點 2 把 Leader 還給節點 1 。這樣,即便經過一系列宕機和恢復,我們存儲節點之間的 Leader 數目仍然能保證是均衡的。
接下來,我們看一下 Cellar 如何保證它的端到端高成功率。這里也講三個影響成功率的問題。Cellar 遇到的數據遷移和熱點 Key 問題與 Squirrel 是一樣的,但解決方案不一樣。這是因為 Cellar 走的是自研路徑,不用考慮與官方版本的兼容性,對架構改動更大些。另一個問題是慢請求阻塞服務隊列導致大面積超時,這是 Cellar 網絡、工作多線程模型設計下會遇到的不同問題。
Cellar 智能遷移
上圖是 Cellar 智能遷移架構圖。我們把桶的遷移分成了三個狀態。第一個狀態就是正常的狀態,沒有任何遷移。如果這時候要把 Slot 2 從 A 節點遷移到 B節點,A 會給 Slot 2 打一個快照,然后把這個快照全量發到 B 節點上。在遷移數據的時候, B 節點的回包會帶回 B 節點的狀態。B 的狀態包括什么?引擎的壓力、網卡流量、隊列長度等。A 節點會根據 B 節點的狀態調整自己的遷移速度。像 Squirrel 一樣,它經過一段時間調整后,遷移速度會達到一個動態平衡,達到最快速的遷移,同時又盡可能小地影響業務的正常請求。
當 Slot 2 遷移完后, 會進入圖中 Slot 3 的狀態。客戶端這時可能還沒更新路由表,當它請求到了 A 節點,A 節點會發現客戶端請求錯了節點,但它不會返回錯誤,它會把請求代理到 B 節點上,然后把 B 的響應包再返回客戶端。同時它會告訴客戶端,需要更新一下路由表了,此后客戶端就能直接訪問到 B 節點。這樣就解決了客戶端路由更新延遲造成的請求錯誤。
Cellar 快慢列隊
下圖上方是一個標準的線程隊列模型。網絡線程池接收網絡流量解析出請求包,然后把請求放到工作隊列里,工作線程池會從工作隊列取請求來處理,然后把響應包放回網絡線程池發出。
我們分析線上發生的超時案例時發現,一批超時請求當中往往只有一兩個請求是引擎處理慢導致的,大部分請求,只是因為在隊列等待過久導致整體響應時間過長而超時了。從線上分析來看,真正的慢請求占超時請求的比例只有 1/20。
我們的解法是什么樣?很簡單,拆線程池、拆隊列。我們的網絡線程在收到包之后,會根據它的請求特點,是讀還是寫,快還是慢,分到四個隊列里。讀寫請求比較好區分,但快慢怎么分開?我們會根據請求的 Key 個數、Value大小、數據結構元素數等對請求進行快慢區分。然后用對應的四個工作線程池處理對應隊列的請求,就實現了快慢讀寫請求的隔離。這樣如果我有一個讀的慢請求,不會影響另外三種請求的正常處理。不過這樣也會帶來一個問題,我們的線程池從一個變成四個,那線程數是不是變成原來的四倍?其實并不是的,我們某個線程池空閑的時候會去幫助其它的線程池處理請求。所以,我們線程池變成了四個,但是線程總數并沒有變。我們線上驗證中這樣的設計能把服務 TP999 的延遲降低 86%,可大幅降低超時率。
Cellar 熱點 Key
上圖是 Cellar 熱點 Key 解決方案的架構圖。我們可以看到中心節點加了一個職責,多了熱點區域管理,它現在不只負責正常的數據副本分布,還要管理熱點數據的分布,圖示這個集群在節點 C、D 放了熱點區域。我們通過讀寫流程看一下這個方案是怎么運轉的。如果客戶端有一個寫操作到了 A 節點,A 節點處理完成后,會根據實時的熱點統計結果判斷寫入的 Key 是否為熱點。
如果這個 Key 是一個熱點,那么它會在做集群內復制的同時,還會把這個數據復制有熱點區域的節點,也就是圖中的 C、D 節點。同時,存儲節點在返回結果給客戶端時,會告訴客戶端,這個 Key 是熱點,這時客戶端內會緩存這個熱點 Key。當客戶端有這個 Key 的讀請求時,它就會直接去熱點區域做數據的讀取。通過這樣的方式,我們可以做到只對熱點數據做擴容,不像 Squirrel ,要把整個 Slot 遷出來做擴容。有必要的話,中心節點也可以把熱點區域放到集群的所有節點上,所有的熱點讀請求就能均衡的分到所有節點上。另外,通過這種實時的熱點數據復制,我們很好地解決了類似客戶端緩存熱點 KV 方案造成的一致性問題。
發展規劃和業界趨勢
最后,一起來看看我們項目的規劃和業界的技術趨勢。這部分內容會按照服務、系統、硬件三層來進行闡述。首先在服務層,主要有三點:
Redis Gossip 協議優化。大家都知道 Gossip 協議在集群的規模變大之后,消息量會劇增,它的 Failover 時間也會變得越來越長。所以當集群規模達到 TB 級后,集群的可用性會受到很大的影響,所以我們后面會重點在這方面做一些優化。
我們已經在 Cellar 存儲節點的數據副本間做了 Raft 復制,可以保證數據強一致,后面我們會在 Cellar 的中心點內部也做一個 Raft 復制,這樣就不用依賴于 ZooKeeper 做分布式仲裁、元數據存儲了,我們的架構也會變得更加簡單、可靠。
Squirrel 和 Cellar 雖然都是 KV 存儲,但是因為它們是基于不同的開源項目研發的,所以 API 和訪問協議不同,我們之后會考慮將 Squirrel 和 Cellar 在 SDK 層做整合,雖然后端會有不同的存儲集群,但業務側可以用一套 SDK 進行訪問。
在系統層面,我們正在調研并去落地一些 Kernel Bypass 技術,像 DPDK、SPDK 這種網絡和硬盤的用戶態 IO 技術。它可以繞過內核,通過輪詢機制訪問這些設備,可以極大提升系統的 IO 能力。存儲作為 IO 密集型服務,性能會獲得大幅的提升。
在硬件層面,像支持 RDMA 的智能網卡能大幅降低網絡延遲和提升吞吐;還有像 3D XPoint 這樣的閃存技術,比如英特爾新發布的 AEP 存儲,其訪問延遲已經比較接近內存了,以后閃存跟內存之間的界限也會變得越來越模糊;最后,看一下計算型硬件,比如通過在閃存上加 FPGA 卡,把原本應該 CPU 做的工作,像數據壓縮、解壓等,下沉到卡上執行,這種硬件能在解放 CPU 的同時,也可以降低服務的響應延遲。
作者簡介
澤斌,美團點評高級技術專家,2014 年加入美團。
編輯:hfy
評論
查看更多