2017双11技术揭秘—分布式缓存服务Tair的热点数据散列机制
摘要: Tair是阿里巴巴集團(tuán)自研的彈性緩存/存儲(chǔ)平臺(tái),在內(nèi)部有著大量的部署和使用。Tair的核心組件是一個(gè)高性能、可擴(kuò)展、高可靠的NoSQL存儲(chǔ)系統(tǒng)。目前支持MDB、LDB、RDB等存儲(chǔ)引擎。本文基于Tair的存儲(chǔ)和訪問原理,對(duì)緩存的讀寫熱點(diǎn)問題進(jìn)行討論,并給出一個(gè)滿足現(xiàn)階段需求的熱點(diǎn)數(shù)據(jù)讀寫問題的解決方案。
作者:劉歡(淺奕)
1 問題背景
分布式緩存一般被定義為一個(gè)數(shù)據(jù)集合,它將數(shù)據(jù)分布(或分區(qū))于任意數(shù)目的集群節(jié)點(diǎn)上。集群中的一個(gè)具體節(jié)點(diǎn)負(fù)責(zé)緩存中的一部分?jǐn)?shù)據(jù),整體對(duì)外提供統(tǒng)一的訪問接口[1]。分布式緩存一般基于冗余備份機(jī)制實(shí)現(xiàn)數(shù)據(jù)高可用,又被稱為內(nèi)存數(shù)據(jù)網(wǎng)格(IMDG, in-memory data grid)。在云平臺(tái)飛速發(fā)展的今天,作為提升應(yīng)用性能的重要手段,分布式緩存技術(shù)在工業(yè)界得到了越來越廣泛的關(guān)注和研發(fā)投入[2]。彈性緩存平臺(tái)[3]是分布式緩存集群在云計(jì)算場(chǎng)景下的新形態(tài),其強(qiáng)調(diào)集群的動(dòng)態(tài)擴(kuò)展性與高可用性。動(dòng)態(tài)擴(kuò)展性表達(dá)了緩存平臺(tái)可提供透明的服務(wù)擴(kuò)展的能力,高可用性則表達(dá)了緩存平臺(tái)可以容忍節(jié)點(diǎn)失效。
Tair是阿里巴巴集團(tuán)自研的彈性緩存/存儲(chǔ)平臺(tái),在內(nèi)部有著大量的部署和使用。Tair的核心組件是一個(gè)高性能、可擴(kuò)展、高可靠的NoSQL存儲(chǔ)系統(tǒng)。目前支持MDB、LDB、RDB等存儲(chǔ)引擎。其中MDB是類似Memcached的內(nèi)存存儲(chǔ)引擎,LDB是使用LSM Tree的持久化磁盤KV存儲(chǔ)引擎,RDB是支持Queue、Set、Maps等數(shù)據(jù)結(jié)構(gòu)的內(nèi)存及持久化存儲(chǔ)引擎。
Tair的數(shù)據(jù)分片和路由算法采用了Amazon于2007年提出的一種改進(jìn)的一致性哈希算法[4]。該算法將整個(gè)哈希空間分為若干等大小的Q份數(shù)據(jù)分區(qū)(也稱為虛擬節(jié)點(diǎn),Q>>N,N為緩存節(jié)點(diǎn)數(shù)),每個(gè)緩存節(jié)點(diǎn)依據(jù)其處理能力分配不同數(shù)量的數(shù)據(jù)分區(qū)。客戶端請(qǐng)求的數(shù)據(jù)Key值經(jīng)哈希函數(shù)映射至哈希環(huán)上的位置記為token,token值再次被哈希映射為某一分區(qū)標(biāo)識(shí)。得到分區(qū)標(biāo)識(shí)后,客戶端從分區(qū)服務(wù)器映射表中查詢存放該數(shù)據(jù)分區(qū)的緩存節(jié)點(diǎn)后進(jìn)行數(shù)據(jù)訪問。使用該算法對(duì)相同數(shù)據(jù)Key進(jìn)行計(jì)算,其必然會(huì)被映射到固定的DataServer上,如圖:
此時(shí)DataServer單節(jié)點(diǎn)的讀寫性能便成了單數(shù)據(jù)Key的讀寫性能瓶頸,且無法通過水平擴(kuò)展節(jié)點(diǎn)的方式來解決。由于阿里巴巴集團(tuán)內(nèi)部電商系的促銷活動(dòng)天然的存在熱點(diǎn)數(shù)據(jù),所以要增強(qiáng)整個(gè)彈性緩存/存儲(chǔ)平臺(tái)的穩(wěn)定性和服務(wù)能力,就必須提升熱點(diǎn)數(shù)據(jù)的讀寫能力,使其能做到水平擴(kuò)展。
2 解決方案
解決方案分為三部分:熱點(diǎn)識(shí)別、讀熱點(diǎn)方案和寫熱點(diǎn)方案。
其中讀寫熱點(diǎn)方案都是以服務(wù)端能對(duì)熱點(diǎn)訪問進(jìn)行精準(zhǔn)的識(shí)別為前提的。另外對(duì)于可以提前預(yù)知熱點(diǎn)Key的情況,也提供相應(yīng)的客戶端API以支持特定數(shù)據(jù)Key或者特定Namespace的所有數(shù)據(jù)Key預(yù)先標(biāo)記為熱點(diǎn)Key的能力。
2.1 DataServer上的熱點(diǎn)統(tǒng)計(jì)過程
DataServer收到客戶端的請(qǐng)求后,由每個(gè)具體處理請(qǐng)求的工作線程(Worker Thread)進(jìn)行請(qǐng)求的統(tǒng)計(jì)。工作線程用來統(tǒng)計(jì)熱點(diǎn)的數(shù)據(jù)結(jié)構(gòu)均為ThreadLocal模式的數(shù)據(jù)結(jié)構(gòu),完全無鎖化設(shè)計(jì)。熱點(diǎn)識(shí)別算法使用精心設(shè)計(jì)的多級(jí)加權(quán)LRU鏈和HashMap組合的數(shù)據(jù)結(jié)構(gòu),在保證服務(wù)端請(qǐng)求處理效率的前提下進(jìn)行請(qǐng)求的全統(tǒng)計(jì),支持QPS熱點(diǎn)和流量熱點(diǎn)(即請(qǐng)求的QPS不大但是數(shù)據(jù)本身過大而造成的大流量所形成的熱點(diǎn))的精準(zhǔn)識(shí)別。每個(gè)采樣周期結(jié)束時(shí),工作線程會(huì)將統(tǒng)計(jì)的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)交到后臺(tái)的統(tǒng)計(jì)線程池進(jìn)行分析處理。統(tǒng)計(jì)工作異步在后臺(tái)進(jìn)行,不搶占正常的數(shù)據(jù)請(qǐng)求的處理資源。
2.2 讀熱點(diǎn)方案
2.2.1 服務(wù)端設(shè)計(jì)
原始Tair的數(shù)據(jù)訪問方式是先進(jìn)行Hash(Key)%BucketCount的計(jì)算,得出具體的數(shù)據(jù)存儲(chǔ)Bucket,再檢索數(shù)據(jù)路由表找到該Bucket所在的DataServer后對(duì)其進(jìn)行讀寫請(qǐng)求的。所以相同Key的讀寫請(qǐng)求必然落在固定的DataServer上,且無法通過水平擴(kuò)展DataServer數(shù)量來解決。
本方案通過在DataServer上劃分一塊HotZone存儲(chǔ)區(qū)域的方式來解決熱點(diǎn)數(shù)據(jù)的訪問。該區(qū)域存儲(chǔ)當(dāng)前產(chǎn)生的所有讀熱點(diǎn)的數(shù)據(jù),由客戶端配置的緩存訪問邏輯來處理各級(jí)緩存的訪問。多級(jí)緩存架構(gòu)如下:
所有DataServer的HotZone存儲(chǔ)區(qū)域之間沒有權(quán)重關(guān)系,每個(gè)HotZone都存儲(chǔ)相同的讀熱點(diǎn)數(shù)據(jù)。客戶端對(duì)熱點(diǎn)數(shù)據(jù)Key的請(qǐng)求會(huì)隨機(jī)到任意一臺(tái)DataServer的HotZone區(qū)域,這樣單點(diǎn)的熱點(diǎn)請(qǐng)求就被散列到多個(gè)節(jié)點(diǎn)乃至整個(gè)集群。
2.2.2客戶端設(shè)計(jì)
2.2.2.1 客戶端邏輯
當(dāng)客戶端在第一次請(qǐng)求前初始化時(shí),會(huì)獲取整個(gè)Tair集群的節(jié)點(diǎn)信息以及完整的數(shù)據(jù)路由表,同時(shí)也會(huì)獲取配置的熱點(diǎn)散列機(jī)器數(shù)(即客戶端訪問的HotZone的節(jié)點(diǎn)范圍)。隨后客戶端隨機(jī)選擇一個(gè)HotZone區(qū)域作為自身固定的讀寫HotZone區(qū)域。在DataServer數(shù)量和散列機(jī)器數(shù)配置未發(fā)生變化的情況下,不會(huì)改變選擇。即每個(gè)客戶端只訪問唯一的HotZone區(qū)域。
客戶端收到服務(wù)端反饋的熱點(diǎn)Key信息后,至少在客戶端生效N秒。在熱點(diǎn)Key生效期間,當(dāng)客戶端訪問到該Key時(shí),熱點(diǎn)的數(shù)據(jù)會(huì)首先嘗試從HotZone節(jié)點(diǎn)進(jìn)行訪問,此時(shí)HotZone節(jié)點(diǎn)和源數(shù)據(jù)DataServer節(jié)點(diǎn)形成一個(gè)二級(jí)的Cache模型。客戶端內(nèi)部包含了兩級(jí)Cache的處理邏輯,即對(duì)于熱點(diǎn)數(shù)據(jù),客戶端首先請(qǐng)求HotZone節(jié)點(diǎn),如果數(shù)據(jù)不存在,則繼續(xù)請(qǐng)求源數(shù)據(jù)節(jié)點(diǎn),獲取數(shù)據(jù)后異步將數(shù)據(jù)存儲(chǔ)到HotZone節(jié)點(diǎn)里。使用Tair客戶端的應(yīng)用常規(guī)調(diào)用獲取數(shù)據(jù)的接口即可,整個(gè)熱點(diǎn)的反饋、識(shí)別以及對(duì)多級(jí)緩存的訪問對(duì)外部完全透明。HotZone緩存數(shù)據(jù)的一致性由客戶端初始化時(shí)設(shè)置的過期時(shí)間來保證,具體的時(shí)間由具體業(yè)務(wù)對(duì)緩存數(shù)據(jù)不一致的最大容忍時(shí)間來決定。
客戶端存儲(chǔ)于本地的熱點(diǎn)反饋過期后,數(shù)據(jù)Key會(huì)到源DataServer節(jié)點(diǎn)讀取。如果該Key依舊在服務(wù)端處于熱點(diǎn)狀態(tài),客戶端會(huì)再次收到熱點(diǎn)反饋包。因?yàn)樗锌蛻舳舜鎯?chǔ)于本地的熱點(diǎn)反饋信息的失效節(jié)奏不同,所以不會(huì)出現(xiàn)同一瞬間所有的請(qǐng)求都回源的情況。即使所有請(qǐng)求回源,也僅需要回源讀取一次即可,最大的讀取次數(shù)僅為應(yīng)用機(jī)器數(shù)。若回源后發(fā)現(xiàn)該Key已不是熱點(diǎn),客戶端便回到常規(guī)的訪問模式。
2.2.2.2 散列比和QPS偏差的關(guān)系
設(shè)集群普通QPS為 C,熱點(diǎn)QPS為 H,機(jī)器數(shù)為 N,則每臺(tái)機(jī)器QPS為:
A=(C+H)/N
則普通機(jī)器QPS偏差比為:
P_c=(C/N)/A=(C/N)/((C+H)/N)=C/(C+H) ,當(dāng) H=0 時(shí),P_c=1
則熱點(diǎn)機(jī)器偏差比為:
P_h=(C/N+H)/A=(C/N+H)/((C+H)/N)=(C+HN)/(C+H) ,當(dāng) H=0 時(shí),P_h=1
進(jìn)行散列后,設(shè)散列機(jī)器數(shù)為 M,則熱點(diǎn)機(jī)器偏差比為:
P_(h’)=(C/N+H/M)/A=(C/N+H/M)/((C+H)/N)=(CM+HN)/(M(C+H))
設(shè)散列比為 K,即 M=KN,則有:
P_(h’)=(CM+HN)/(M(C+H))=(CKN+HN)/(KN(C+H))=(CK+H)/(K(C+H)),當(dāng) K=1 時(shí), P_(h’)=1
2.3 寫熱點(diǎn)方案
2.3.1 服務(wù)端設(shè)計(jì)
2.3.1.1 處理方式
對(duì)于寫熱點(diǎn),因?yàn)橐恢滦缘膯栴},難以使用多級(jí)緩存的方式來解決。如果采用寫本地Cache,再異步更新源DataServer的方案。那么在Cache寫入但尚未更新的時(shí)候,如果業(yè)務(wù)機(jī)器宕機(jī),就會(huì)有已寫數(shù)據(jù)丟失的問題。同時(shí),本地 Cache會(huì)導(dǎo)致進(jìn)行數(shù)據(jù)更新的某應(yīng)用機(jī)器當(dāng)前更新周期內(nèi)的修改對(duì)其他應(yīng)用機(jī)器不可見,從而延長數(shù)據(jù)不一致的時(shí)間。故多級(jí)Cache的方案無法支持寫熱點(diǎn)。最終寫熱點(diǎn)采用在服務(wù)端進(jìn)行請(qǐng)求合并的方式進(jìn)行處理。
熱點(diǎn)Key的寫請(qǐng)求在IO線程被分發(fā)到專門的熱點(diǎn)合并線程處理,該線程根據(jù)Key對(duì)寫請(qǐng)求進(jìn)行一定時(shí)間內(nèi)的合并,隨后由定時(shí)線程按照預(yù)設(shè)的合并周期將合并后的請(qǐng)求提交到引擎層。合并過程中請(qǐng)求結(jié)果暫時(shí)不返回給客戶端,等請(qǐng)求合并寫入引擎成功后統(tǒng)一返回。這樣做不會(huì)有一致性的問題,不會(huì)出現(xiàn)寫成功后卻讀到舊數(shù)據(jù),也避免了LDB集群返回成功,數(shù)據(jù)并未落盤的情況(假寫)。具體的合并周期在服務(wù)端可配置,并支持動(dòng)態(tài)修改生效。
2.3.2 客戶端設(shè)計(jì)
寫熱點(diǎn)的方案對(duì)客戶端完全透明,不需要客戶端做任何修改。
2.3.3 性能指標(biāo)
LDB集群實(shí)際壓測(cè)效果為單Key合并能做到單Key百萬的QPS(1ms合并,不限制合并次數(shù)),線上實(shí)際集群為了盡可能保證實(shí)時(shí)性,均采用了最大0.1ms以及單次最大合并次數(shù)為100次的限制。這樣單Key在引擎層的最大落盤QPS就能控制在10000以下(而合并的QPS則取決于應(yīng)用的訪問頻率)。Tair服務(wù)端的包處理是完全異步化的,進(jìn)行熱點(diǎn)請(qǐng)求的合并操作并不阻塞對(duì)其他請(qǐng)求的處理。唯一的影響就是增大客戶端對(duì)熱點(diǎn)key的寫請(qǐng)求的RT. 按照現(xiàn)在的配置,最壞情況下,客戶端的熱點(diǎn)key的寫操作會(huì)增大0.1ms,這個(gè)影響是微乎其微的。
總結(jié)
以上是生活随笔為你收集整理的2017双11技术揭秘—分布式缓存服务Tair的热点数据散列机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自动替换 Kubernetes 镜像
- 下一篇: 打通钉钉+WebHook:日志服务告警升