背景
云(yun)主機(ji)創(chuang)建(jian)有兩種(zhong)方式,一種(zhong)通(tong)過(guo)鏡像下載來創(chuang)建(jian),另(ling)一種(zhong)通(tong)過(guo)快照回(hui)滾(gun)(gun)來創(chuang)建(jian), 前者是通(tong)用的傳統方式,后者依賴(lai)于(yu)CBS云(yun)盤能力。 隨著CBS云(yun)盤使用越(yue)來越(yue)廣泛,騰訊(xun)云(yun)主機(ji)創(chuang)建(jian)也由(you)原來的鏡像下載切換到CBS云(yun)盤快照回(hui)滾(gun)(gun)模式。
通過傳統(tong)鏡(jing)像(xiang)下載的(de)(de)(de)(de)方(fang)式來(lai)創(chuang)建(jian)(jian)云(yun)主機(ji)(ji)(ji),在(zai)云(yun)主機(ji)(ji)(ji)拉起前,需(xu)要(yao)將整個鏡(jing)像(xiang)文件都下載到(dao)宿主機(ji)(ji)(ji)上,所(suo)以云(yun)主機(ji)(ji)(ji)的(de)(de)(de)(de)創(chuang)建(jian)(jian)時間(jian)很大程度上依賴所(suo)選取的(de)(de)(de)(de)鏡(jing)像(xiang)和(he)當時下載鏡(jing)像(xiang)的(de)(de)(de)(de)帶寬。當遇到(dao)比較大的(de)(de)(de)(de)鏡(jing)像(xiang)時,云(yun)主機(ji)(ji)(ji)創(chuang)建(jian)(jian)時間(jian)經常(chang)會達(da)到(dao)幾百秒,這樣的(de)(de)(de)(de)用(yong)戶(hu)體驗(yan)不是太好(hao); 另外(wai),當批(pi)量創(chuang)建(jian)(jian)時,需(xu)要(yao)消耗大量的(de)(de)(de)(de)內網帶寬資源,需(xu)要(yao)在(zai)盡(jin)量占用(yong)網絡帶寬的(de)(de)(de)(de)同時做好(hao)Qos,保證不影響用(yong)戶(hu)的(de)(de)(de)(de)正常(chang)使用(yong)。
使用云(yun)(yun)盤(pan)快照(zhao)(zhao)回滾(gun)的(de)方(fang)式來創建云(yun)(yun)主機,不需要(yao)提前下(xia)載(zai)鏡像,而是(shi)在(zai)云(yun)(yun)主機拉起時,優先將要(yao)訪問的(de)數據從快照(zhao)(zhao)系統(tong)(tong)搬遷到(dao)CBS云(yun)(yun)盤(pan)系統(tong)(tong)中。 我們(men)觀察到(dao),云(yun)(yun)主機拉起過程中訪問的(de)數據量(liang)和(he)鏡像大小(xiao)并(bing)不是(shi)嚴格(ge)的(de)線性關系,即便是(shi)較大的(de)鏡像,在(zai)云(yun)(yun)主機拉起時也只會訪問到(dao)很少一部分數據,搬遷流程如下(xia):
圖1. 云盤快(kuai)照數據搬遷流(liu)程
當(dang)(dang)有(you)快(kuai)照(zhao)(zhao)回(hui)滾請(qing)求時(shi),我們首先(xian)會在后臺啟動一個任務,將快(kuai)照(zhao)(zhao)數據(ju)按順序從(cong)(cong)COS讀出寫(xie)(xie)入(ru)(ru)到存儲池(chi)中,同時(shi)我們不會阻(zu)(zu)礙用戶(hu)對回(hui)滾磁盤的(de)(de)正常讀寫(xie)(xie)。 當(dang)(dang)有(you)用戶(hu)請(qing)求過來時(shi)(步驟(zou)1),會先(xian)在driver中檢查對應lba的(de)(de)快(kuai)照(zhao)(zhao)數據(ju)是否已經被寫(xie)(xie)入(ru)(ru),如果寫(xie)(xie)入(ru)(ru)則(ze)IO直接下發(步驟(zou)7),否則(ze),會阻(zu)(zu)塞IO并先(xian)給(gei)scheduler發送trigger請(qing)求(步驟(zou)3),scheduler會優先(xian)將trigger請(qing)求處(chu)理,交給(gei)搬遷(qian)模塊將對應的(de)(de)快(kuai)照(zhao)(zhao)數據(ju)從(cong)(cong)COS讀出,寫(xie)(xie)入(ru)(ru)到存儲池(chi)(步驟(zou)3、4、5),等寫(xie)(xie)入(ru)(ru)完(wan)畢后,scheduler先(xian)記錄搬遷(qian)bitmap到zk并給(gei)driver返(fan)回(hui)trigger response和當(dang)(dang)前的(de)(de)快(kuai)照(zhao)(zhao)數據(ju)回(hui)滾進度(步驟(zou)6),driver收到后則(ze)不再阻(zu)(zu)塞io, 讓其(qi)正常下發(步驟(zou)7)。
聚(ju)焦(jiao)延(yan)遲和并發(fa),云(yun)主機創建優(you)化之路(lu)
云盤快照回滾優先(xian)搬(ban)遷關鍵(jian)數(shu)據這種機制為我們批量創建(jian)云主(zhu)機奠定了基礎,在此(ci)基礎上,我們還圍繞著延遲和并(bing)發這兩點做了一系列優化。
transfer增加cache
子(zi)機批(pi)量(liang)(liang)創建時,經(jing)常(chang)是使用同一(yi)個鏡像克(ke)隆出幾百或上千臺子(zi)機,如果所有數據都從COS系統拉(la)取(qu),對COS的(de)(de)讀壓力會(hui)非常(chang)大,會(hui)觸(chu)發COS的(de)(de)Qos流控。為了讓批(pi)量(liang)(liang)創建時讀取(qu)鏡像的(de)(de)流量(liang)(liang)不(bu)再受限于COS的(de)(de)帶寬, 我們(men)在transfer中增(zeng)加(jia)了cache,每個transfer中都緩存(cun)鏡像的(de)(de)部(bu)分數據塊,一(yi)旦(dan)命中transfer的(de)(de)cache就不(bu)再從COS拉(la)取(qu)數據,這樣每個transfer只需拉(la)取(qu)一(yi)次鏡像; 當cache流量(liang)(liang)達到瓶(ping)頸時,可以通過臨時增(zeng)加(jia)節點來(lai)增(zeng)加(jia)帶寬,具(ju)備(bei)水平擴展能力。
在增加了(le)(le)cache后(hou),我(wo)們對transfer部署也做了(le)(le)優化,每個zone都部署了(le)(le)若(ruo)干個節點,當有數(shu)據塊搬遷(qian)(qian)請(qing)求時,任務總是會優先落到(dao)和CBS盤(pan)底層存儲節點相(xiang)同(tong)zone的transfer上,這樣就可以實現就近搬遷(qian)(qian)。
通過cache優化,可以(yi)將(jiang)單個數(shu)據塊的搬遷耗時(shi)從(cong)100+ms降低(di)到(dao)10+ms, 大(da)大(da)降低(di)了IO延遲。
圖2. transfer cache
scheduler性能優化
在快(kuai)照(zhao)(zhao)回滾創(chuang)建云主機過(guo)程(cheng)中(zhong),核心處理邏輯(ji)在scheduler,因為client端每(mei)個(ge)IO trigger請求都(dou)要經過(guo)scheduler, 并且由(you)于(yu)每(mei)個(ge)由(you)trigger觸發的(de)快(kuai)照(zhao)(zhao)數據塊搬遷都(dou)要在zk里記錄起來, 所以(yi)scheduler的(de)負載以(yi)及zk寫入(ru)能力會直接影(ying)響到整個(ge)快(kuai)照(zhao)(zhao)系統的(de)吞吐。
首先,我們優化了scheduler,將請求(qiu)接收、處(chu)理(li)以及與后端(duan)交互部分的邏輯拆開來,形成流水線,盡(jin)量(liang)減少因某個請求(qiu)處(chu)理(li)慢導(dao)致其(qi)他請求(qiu)排隊的情況, 每個部分都由(you)一(yi)個線程池來并行處(chu)理(li),盡(jin)量(liang)將整機的計(ji)算(suan)能力(li)利用(yong)起(qi)來;
其次,針對zk寫(xie)入(ru)壓力大(da)的(de)(de)問(wen)題,我(wo)們(men)將寫(xie)入(ru)zk的(de)(de)數(shu)(shu)據做了分(fen)類,變化不頻繁的(de)(de)一(yi)些(xie)元(yuan)數(shu)(shu)據還是(shi)寫(xie)入(ru)zk; 而記錄trigger搬遷狀態的(de)(de)那些(xie)元(yuan)數(shu)(shu)據,需要頻繁修(xiu)改,這(zhe)部(bu)分(fen)數(shu)(shu)據不適合存zk,我(wo)們(men)將其offload到一(yi)個qps更高的(de)(de)存儲(chu)系統上,這(zhe)樣一(yi)來,scheduler的(de)(de)處理(li)能力得到了成倍的(de)(de)增長。
另外,為防止回滾的(de)(de)流量影響到(dao)其(qi)他用戶對(dui)磁盤的(de)(de)正(zheng)常使用,我們在scheduler做了必要的(de)(de)Qos。 首先限(xian)(xian)制(zhi)落到(dao)同(tong)(tong)一個(ge)副本(ben)組(zu)的(de)(de)回滾帶(dai)寬(kuan), 在整個(ge)副本(ben)組(zu)帶(dai)寬(kuan)空閑時(shi)(shi),回滾流量不能超過限(xian)(xian)制(zhi); 而當整個(ge)副本(ben)組(zu)的(de)(de)帶(dai)寬(kuan)達到(dao)上限(xian)(xian)時(shi)(shi),回滾帶(dai)寬(kuan)會自動回退(tui),優(you)先保(bao)(bao)證用戶的(de)(de)正(zheng)常IO延遲。其(qi)次,當同(tong)(tong)時(shi)(shi)有順(shun)序搬(ban)遷(qian)任務(wu)和trigger請求任務(wu)時(shi)(shi),優(you)先處(chu)理trigger請求任務(wu),保(bao)(bao)證用戶體驗。
最后,我們通過對scheduler改(gai)造,做到水平可擴展(zhan), 使其不再成(cheng)為(wei)性(xing)能瓶頸。
圖3. scheduler 拆分(fen)
買盤調度
當用快(kuai)(kuai)照(zhao)回(hui)滾(gun)的(de)(de)(de)(de)方(fang)式批量(liang)(liang)創建云(yun)(yun)(yun)主機(ji)時(shi), 會將(jiang)快(kuai)(kuai)照(zhao)數據寫(xie)(xie)入(ru)新(xin)創建的(de)(de)(de)(de)所有(you)CBS云(yun)(yun)(yun)盤(pan)(pan)。 如(ru)果大(da)量(liang)(liang)的(de)(de)(de)(de)云(yun)(yun)(yun)盤(pan)(pan)落在(zai)同一(yi)個(ge)(ge)副(fu)(fu)(fu)本(ben)組(zu),則(ze)會造成(cheng)這個(ge)(ge)副(fu)(fu)(fu)本(ben)組(zu)寫(xie)(xie)入(ru)流(liu)量(liang)(liang)過大(da),觸發前一(yi)節提到(dao)的(de)(de)(de)(de)副(fu)(fu)(fu)本(ben)組(zu)回(hui)滾(gun)帶(dai)寬(kuan)限(xian)制。為避免這個(ge)(ge)問(wen)題,我們(men)加入(ru)一(yi)個(ge)(ge)調度系統(tong),在(zai)批量(liang)(liang)購(gou)買(mai)云(yun)(yun)(yun)盤(pan)(pan)時(shi),從副(fu)(fu)(fu)本(ben)組(zu)剩余容量(liang)(liang)、已創建的(de)(de)(de)(de)volume數、回(hui)滾(gun)帶(dai)寬(kuan)、副(fu)(fu)(fu)本(ben)組(zu)寫(xie)(xie)入(ru)帶(dai)寬(kuan)四個(ge)(ge)緯(wei)度綜合考(kao)量(liang)(liang),把(ba)同一(yi)批次(ci)創建的(de)(de)(de)(de)CBS云(yun)(yun)(yun)盤(pan)(pan)盡量(liang)(liang)打(da)散到(dao)多個(ge)(ge)副(fu)(fu)(fu)本(ben)組(zu)。這樣一(yi)來,首(shou)先可(ke)以保證在(zai)創建時(shi),單個(ge)(ge)副(fu)(fu)(fu)本(ben)組(zu)不會成(cheng)為流(liu)量(liang)(liang)熱點;其次(ci)可(ke)以在(zai)一(yi)定程(cheng)度上保證所有(you)的(de)(de)(de)(de)副(fu)(fu)(fu)本(ben)組(zu)在(zai)創建時(shi)流(liu)量(liang)(liang)均衡,將(jiang)整個(ge)(ge)存(cun)儲池的(de)(de)(de)(de)帶(dai)寬(kuan)充(chong)分利用起來;最后,同一(yi)批次(ci)購(gou)買(mai)的(de)(de)(de)(de)CBS云(yun)(yun)(yun)盤(pan)(pan)打(da)散,可(ke)以將(jiang)用戶因為某個(ge)(ge)副(fu)(fu)(fu)本(ben)組(zu)出故障受到(dao)的(de)(de)(de)(de)影(ying)響降(jiang)到(dao)最低。
減少子(zi)機拉起時的數據量
前(qian)面主要從降低(di)延遲(chi)和增大回滾帶(dai)寬角度去考慮(lv)如何優化,目的(de)是讓后(hou)端系統能夠承載(zai)更大的(de)回滾帶(dai)寬,提(ti)升(sheng)快(kuai)照(zhao)數據(ju)(ju)搬(ban)遷(qian)(qian)效率。如果在快(kuai)照(zhao)數據(ju)(ju)搬(ban)遷(qian)(qian)過程中,CBS云(yun)盤有(you)IO訪問到還未搬(ban)遷(qian)(qian)的(de)數據(ju)(ju)塊(kuai),就會產(chan)生一個trigger請求,后(hou)臺(tai)系統需要優先(xian)搬(ban)遷(qian)(qian)trigger請求對應位置的(de)快(kuai)照(zhao)數據(ju)(ju),這對scheduler會造成額外的(de)負擔(dan),所以如何減(jian)(jian)少子機(ji)拉(la)起時產(chan)生的(de)IO trigger,減(jian)(jian)少對后(hou)端系統的(de)壓力(li),對云(yun)主機(ji)并發創建很(hen)有(you)意義。
對子(zi)機拉(la)(la)起(qi)過程(cheng)進行分析,我們發(fa)現,在(zai)(zai)子(zi)機拉(la)(la)起(qi)過程(cheng)中(zhong),文件(jian)(jian)系統(tong)(tong)擴容(rong)(rong)和配(pei)置文件(jian)(jian)修改(gai)都會(hui)在(zai)(zai)后(hou)端(duan)(duan)產生(sheng)(sheng)不少(shao)io trigger。 文件(jian)(jian)系統(tong)(tong)擴容(rong)(rong)一(yi)般(ban)發(fa)生(sheng)(sheng)在(zai)(zai)快照里的文件(jian)(jian)系統(tong)(tong)size小(xiao)于要回(hui)滾的CBS云盤size,在(zai)(zai)這種場景下,需要先將原文件(jian)(jian)系統(tong)(tong)的元(yuan)數(shu)據全(quan)部讀到內存中(zhong),修改(gai)后(hou)再寫(xie)(xie)入。像ext系列(lie)文件(jian)(jian)系統(tong)(tong)的元(yuan)數(shu)據是散落(luo)在(zai)(zai)每個塊組中(zhong)的,所以(yi)讀元(yuan)數(shu)據會(hui)變(bian)成(cheng)隨機讀操作,幾乎每個隨機讀都會(hui)產生(sheng)(sheng)一(yi)個trigger,觸發(fa)后(hou)端(duan)(duan)快照數(shu)據塊搬遷,而文件(jian)(jian)系統(tong)(tong)的block大小(xiao)遠(yuan)小(xiao)于快照粒度,這里相(xiang)當(dang)于發(fa)生(sheng)(sheng)了讀寫(xie)(xie)放大; 為此,我們通(tong)過修改(gai)文件(jian)(jian)系統(tong)(tong)配(pei)置,讓(rang)所有元(yuan)數(shu)據集中(zhong),這樣(yang)讀元(yuan)數(shu)據就變(bian)成(cheng)了順(shun)序讀寫(xie)(xie),這樣(yang)就可(ke)以(yi)將請求合并,從而減少(shao)后(hou)端(duan)(duan)壓力。 經過優(you)化(hua)后(hou),文件(jian)(jian)系統(tong)(tong)擴容(rong)(rong)時(shi)(shi),后(hou)端(duan)(duan)IO壓力可(ke)以(yi)降低到原來的五分之(zhi)一(yi),耗(hao)時(shi)(shi)降低到原來的四分之(zhi)一(yi)。
其(qi)次,對于配置文(wen)件(jian)(jian)(jian)修改,如果直接在原文(wen)件(jian)(jian)(jian)上修改,既要(yao)讀(du)(du)寫(xie)(xie)文(wen)件(jian)(jian)(jian)元數(shu)(shu)據(ju)(ju),又要(yao)讀(du)(du)寫(xie)(xie)文(wen)件(jian)(jian)(jian)數(shu)(shu)據(ju)(ju),開銷比較大;所以改成刪除(chu)+寫(xie)(xie)新文(wen)件(jian)(jian)(jian)的(de)方式,這(zhe)樣不(bu)需(xu)要(yao)讀(du)(du)文(wen)件(jian)(jian)(jian)數(shu)(shu)據(ju)(ju),可以有效減少IO。
總結:
通過上述幾個層面的技術優化,目前,騰訊云已經可以做(zuo)到八千臺(tai)子(zi)機并發(fa)創(chuang)建,為客戶提(ti)(ti)供更好的服務體(ti)驗(yan)。后續(xu),我(wo)們(men)的優化還會一直進行下去,歡迎大家給我(wo)們(men)提(ti)(ti)出(chu)寶貴意見(jian)。