您好,登錄后才能下訂單哦!
阿里妹導讀:本文以雙11面臨的挑戰為背景,從Tair(阿里自研高速緩存系統)發展和應用開始談起,重點分享了性能優化方面的實踐,最后對緩存熱點難題給出了解決方案,希望能對大家的工作有所啟發。
本文作者為宗岱,阿里巴巴資深技術專家,2008年加入淘寶,阿里分布式緩存、NoSQL數據庫Tair和Tengine負責人。
Tair發展歷程
Tair在阿里巴巴被廣泛使用,無論是淘寶天貓瀏覽下單,還是打開優酷瀏覽播放時,背后都有Tair的身影默默支撐巨大的流量。Tair的發展歷程如下:
2010.04 Tair v1.0正式推出@淘寶核心系統;
2012.06 Tair v2.0推出LDB持久化產品,滿足持久化存儲需求;
2012.10 推出RDB緩存產品,引入類Redis接口,滿足復雜數據結構的存儲需求;
2013.03 在LDB的基礎上針對全量導入場景上線Fastdump產品,大幅度降低導入時間和訪問延時;
2014.07 Tair v3.0 正式上線,性能數倍提升;
2016.11 泰斗智能運維平臺上線,助力2016雙11邁入千億時代;
2017.11 性能飛躍,熱點散列,資源調度,支持萬億流量。
Tair是一個高性能、分布式、可擴展、高可靠的key/value結構存儲系統!Tair特性主要體現在以下幾個方面:
高性能:在高吞吐下保證低延遲,Tair是阿里集團內調用量最大系統之一,雙11達到每秒5億次峰值的調用量,平均訪問延遲在1毫秒以下;
高可用:通過自動failover,限流,審計和機房內容災以及多單元多地域,確保系統在任何情況下都能正常運行;
規模化:分布全球各個數據中心,阿里集團各個BU都在使用;
業務覆蓋:電商、螞蟻、合一、菜鳥、高德、阿里健康等。
Tair除了普通Key/Value系統提供的功能,比如get、put、delete以及批量接口外,還有一些附加的實用功能,使得其有更廣的適用場景。Tair應用場景包括以下四種:
MDB 典型應用場景:用于緩存,降低對后端數據庫的訪問壓力,比如淘寶中的商品都是緩存在Tair中;用于臨時數據存儲,部分數據丟失不會對業務產生較大影響,例如登陸;
LDB 典型應用場景:通用kv存儲、交易快照、安全風控等;存儲黑白單數據,讀qps很高;計數器功能,更新非常頻繁,且數據不可丟失。
RDB 典型應用場景:復雜的數據結構的緩存與存儲,如播放列表,直播間等。
FastDump 典型應用場景:周期性地將離線數據快速地導入到Tair集群中,快速使用到新的數據,對在線讀取要求非常高;讀取低延遲,不能有毛刺。
雙 11 挑戰怎么辦?
2012-2017年數據如圖,可以看到,2012年GMV小于200億,2017年GMV達到1682億,交易創建峰值從1.4萬達到32.5萬,峰值QPS從1300萬達到近5億。
從圖中可以看出,tair訪問增速遠大于交易創建峰值,交易創建峰值也大于GMV的增長。也就是0點的那刻,對Tair來說,在保證高并發訪問的同時,如何確保低延遲,如何確保成本低于業務增速的技術挑戰越來越大。
對于分布式存儲系統來說,熱點問題都是比較難解決的。而緩存系統流量特別大,熱點問題更為突出。2017年雙11,我們通過了熱點散列,徹底解決掉了緩存熱點問題。
同時,為了承載每秒32.5萬筆交易阿里的技術架構也不斷演進成為多地域多單元的架構,不僅采用了阿里云上的單元,而且也有和離線服務混部的單元,這里對我們的挑戰是如何快速彈性的部署和下線集群。
多地域多單元
先看下我們大致整體的部署架構和tair在系統中的位置。從這張簡圖上看到,我們是一個多地域多機房多單元的部署架構。整個系統上從流量的接入層,到應用層。然后應用層依賴了各種中間件,例如消息隊列,配置中心等等。最底層是基礎的數據層,tair和數據庫。在數據這一層,我們需要為業務做需要的數據同步,以保障上層業務是無狀態的。
多地域多單元除了防止黑天鵝之外,另外一個重要的作用是能夠通過快速上線一個單元來實現承載部分的流量。Tair也做了一整套控制系統來實現快速的彈性建站。
彈性建站
Tair本身是一個很復雜分布式存儲系統,規模也非常龐大。所以我們有一個叫泰斗的運營管理平臺。在這里面通過任務編排,任務執行,驗證和交付等流程來確保快速的一鍵建站,離在線混部集群的快上快下工作。在部署工作完成后,會經過一系列系統,集群,實例上的連通性驗證來確保服務完整無誤后,再交付上線使用。如果有一絲遺漏,那么業務流量過來時,可能會觸發大規模故障。這里面,如果是帶數據的持久化集群,那么在部署完成后,還需要等待存量數據遷移完成并且數據達到同步后才能進入驗證階段。
Tair的每一個業務集群水位其實是不一樣的,雙11前的每一次全鏈路壓測,由于業務模型的變化,所用Tair資源會發生變化,造成水位出現變化。在此情況下,我們每次都需要壓測多個集群間調度的Tair資源。如果水位低,就會把某些機器服務器資源往水位高挪,達到所有集群水位值接近。
數據同步
多地域多單元,必須要求我們數據層能夠做到數據的同步,并且能夠提供給業務各種不同的讀寫模式。對于單元化業務,我們提供了本單元訪問本地Tair的能力,對于有些非單元化業務,我們也提供了更靈活的訪問模型。同步延遲是我們一直在做的事情,2017年雙11每秒同步數據已經達到了千萬級別,那么,如何更好地解決非單元化業務在多單元寫入數據沖突問題?這也是我們一直考慮的。
服務器成本并不是隨著訪問量線性增長,每年以百分之三四十成本在下降,我們主要通過服務器性能優化、客戶端性能優化和不同的業務解決方案三方面達到此目標。
先來看下我們如何從服務端角度提升性能和降低成本的。這里的工作主要分為兩大塊:一塊是避免線程切換調度,降低鎖競爭和無鎖化,另外一塊是采用用戶態協議棧+DPDK來將run-to-completion進行到底。
內存數據結構
MDB內存數據結構示意圖
我們在進程啟動之后會申請一大塊內存,在內存中將格式組織起來。主要有slab分配器、hashmap和內存池,內存寫滿后會經過LRU鏈進行數據淘汰。隨著服務器CPU核數不斷增加,如果不能很好處理鎖競爭,很難提升整體性能。
通過參考各種文獻,并結合tair自身引擎需求,我們使用了細粒度鎖、無鎖數據結構、CPU本地數據結構和RCU機制來提升引擎的并行性。左圖為未經過優化時各個功能模塊的CPU消耗圖,可以看到網絡部分和數據查找部分消耗最多,優化后(右圖)有80%的處理都是在網絡和數據的查找,這是符合我們期望的。
用戶態協議棧
鎖優化后,我們發現很多CPU消耗在內核態上,這時我們采用DPDK+Alisocket來替換掉原有內核態協議棧,Alisocket采用DPDK在用戶態進行網卡收包,并利用自身協議棧提供socket API,對其進行集成。我們將tair,memcached以及業內以性能著稱的seastar框架相比,tair的性能優勢在seastar 10%以上。
內存合并
當性能提升后,單位qps所占用的內存就變少了,所以內存變得很緊缺。另外一個現狀,tair是一個多租戶的系統,各個業務行為不太一樣,時常會造成page已經分配完畢,但是很多slab里的page都是未寫滿的。而有少量slab確實已經全占滿了,造成了看上去有容量,但無法分配數據的情況。
此時,我們實施了一個將同一slab里未寫滿page內存合并的功能,可以釋放出大量空閑內存。從圖中可以看到,在同一個slab里,記錄了每個page的使用率,并掛載到不同規格的bucket上。合并時,將使用率低的page往使用率高的page上合并。同時還需要將各個相關聯的數據結構,包括LRU鏈,相當于整個內存結構的重整。這個功能在線上的公用集群里效果特別好,根據不同場景,可以大幅提升內存使用效率。
客戶端優化
上面這些是服務端的變化,接下來看看客戶端的性能。我們的客戶端是運行在客戶服務器上的,所以占用了客戶的資源。如果能盡可能低的降低資源消耗,對我們整個系統來說,成本都是有利的。客戶端我們做了兩方面優化:網絡框架替換,適配協程,從原有的mina替換成netty,吞吐量提升40%;序列化優化,集成 kryo和hessian,吞吐量提升16%+。
內存網格
如何與業務結合來降低整體Tair與業務成本?Tair提供了多級存儲一體化解決業務問題,比如安全風控場景,讀寫量超大、有大量本地計算,我們可以在業務機器本地存下該業務機器所要訪問的數據,大量讀會命中在本地,而且寫在一段時間內是可合并的,在一定周期后,合并寫到遠端Tair集群上作為最終存儲。我們提供讀寫穿透,包括合并寫和原有Tair本身具有多單元復制的能力,雙11時業務對Tair讀取降至27.68%,對Tair寫入降至55.75%。
緩存擊穿
緩存從開始的單點發展到分布式系統,通過數據分片方式組織,但對每一個數據分片來說,還是作為單點存在的。當有大促活動或熱點新聞時,數據往往是在某一個分片上的,這就會造成單點訪問,進而緩存中某個節點就會無法承受這么大壓力,致使大量請求沒有辦法響應。對于緩存系統一個自保的方法是限流。但是限流對于整個系統來說,并無濟于事。限流后,一部分流量會去訪問數據庫,那依然和剛剛所說的無法承受是一樣的結果,整個系統出現異常。
所以在這里,唯一的解決辦法是緩存系統能夠作為流量的終結點。不管是大促,還是熱點新聞,還是業務自己的異常。緩存都能夠把這些流量吸收掉,并且能讓業務看到熱點的情況。
熱點散列
經過多種方案的探索,采用了熱點散列方案。我們評估過客戶端本地cache方案和二級緩存方案,它們可以在一定程度上解決熱點問題,但各有弊端。例如二級緩存的服務器數目無法預估,本地cache方案對的業務側內存和性能的影響。而熱點散列直接在數據節點上加hotzone區域,讓hotzone承擔熱點數據存儲。對于整個方案來說,最關鍵有以下幾步:
智能識別。熱點數據總是在變化的,或是頻率熱點,或是流量熱點。內部實現采用多級LRU的數據結構,設定不同權值放到不同層級的LRU上,一旦LRU數據寫滿后,會從低級LRU鏈開始淘汰,確保權值高的得到保留。
實時反饋和動態散列。當訪問到熱點時,appserver和服務端就會聯動起來,根據預先設定好的訪問模型動態散列到其它數據節點hotzone上去訪問,集群中所有節點都會承擔這個功能。
通過這種方式,我們將原來單點訪問承擔的流量通過集群中部分機器來承擔。
整個工程實現是很復雜的,熱點散列在雙11中取得了非常顯著的效果。峰值每秒吸收了800多w的訪問量。從右圖可以看到,紅色的線是如果未開啟熱點散列的水位,綠色的線是開啟熱點散列的水位。如果未開啟,很多集群都超過了死亡水位,也就是我們集群水位的130%。而開啟之后,通過將熱點散列到整個集群,水位降低到了安全線下。換而言之,如果不開啟,那么很多集群都可能出現問題。
寫熱點
寫熱點與讀熱點有類似的地方,這塊主要是通過合并寫操作來實施。首先依然是識別出熱點,如果是熱點寫操作,那么該請求會被分發到專門的熱點合并線程處理,該線程根據key對寫請求進行一定時間內的合并,隨后由定時線程按照預設的合并周期將合并后的請求提交到引擎層。通過這種方式來大幅降低引擎層的壓力。
經過雙11考驗對讀寫熱點的處理,我們可以放心的說,Tair將緩存包括kv存儲部分的讀寫熱點徹底解決了。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。