您好,登錄后才能下訂單哦!
本文根據(jù)徐海峰2018年5月12日在【第九屆中國數(shù)據(jù)庫技術(shù)大會(huì)】上的演講內(nèi)容整理而成。
講師介紹:
徐海峰,花名:大嘴。10年互聯(lián)網(wǎng)經(jīng)驗(yàn)。現(xiàn)任閱文集團(tuán)首席架構(gòu)師、技術(shù)專家。主要負(fù)責(zé)閱文集團(tuán)內(nèi)容中心分布式系統(tǒng)的架構(gòu)與實(shí)現(xiàn)、海量數(shù)據(jù)的分布式存儲(chǔ)與分布式計(jì)算。兼負(fù)責(zé)公司的專利、技術(shù)等開源布道。曾任ctrip國際機(jī)票計(jì)價(jià)引擎架構(gòu)師、5173分布式存儲(chǔ)與計(jì)算架構(gòu)師等工作。多年來一直專心致力于網(wǎng)站的分布式架構(gòu)、海量數(shù)據(jù)存儲(chǔ)與計(jì)算等中間件的研究與實(shí)現(xiàn),并形成有成型的技術(shù)認(rèn)知與理論體系。對(duì)大型網(wǎng)站的架構(gòu)與分布式系統(tǒng)有豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)。
內(nèi)容摘要:
通常的緩存系統(tǒng)(典型如memcahed)普遍都將數(shù)據(jù)內(nèi)存化,而不支持持久化??v使后來的Redis解決了數(shù)據(jù)無法持久化的“硬傷”,但通常緩存系統(tǒng)的持久化功能是否啟用也一直是一個(gè)讓人很糾結(jié)的問題。之所以糾結(jié)主要是幾個(gè)原因:1. 緩存系統(tǒng)啟用持久化后性能明顯下降;2. 數(shù)據(jù)開啟了持久化,但機(jī)器down機(jī)恢復(fù)后依然無法使用或者數(shù)據(jù)無法自動(dòng)更新到最新版本;3. 主存依然是內(nèi)存,所以數(shù)據(jù)大小需受制于內(nèi)存,依然無法存儲(chǔ)比內(nèi)存大的數(shù)據(jù),故持久化僅僅是備份;4. 設(shè)計(jì)的時(shí)候沒考慮持久化,啟用持久化后使用非常別扭;而我們的lest從設(shè)計(jì)開始就解決了這些問題,并且還帶來了更多很有意思、也很有實(shí)用價(jià)值的技術(shù),比如私有的通訊與存儲(chǔ)協(xié)議、全程無鎖的多線程模型等等。
正文演講:
今天主要是想和大家分享我們現(xiàn)在用的持久化緩存—lest,說是緩存,但因?yàn)槭浅志没?,所以我個(gè)人認(rèn)為稱作存儲(chǔ)系統(tǒng)可能更好一些,它確實(shí)是KV結(jié)構(gòu),并且包含了String、List、Map等等。目前已上線使用,支持1PB到2PB的數(shù)據(jù)。
講到緩存,在大家的印象中緩存像什么?其實(shí)緩存和神藥有很多的相同之處,首先它們都是為了解決“行不行”的問題,使用之后99%作用明顯,1%無作用,而且是立馬見效,通常會(huì)在幾分鐘或者幾小時(shí)失效,而且都是走的“治標(biāo)治本”的路子,多級(jí)緩存,從客戶端到數(shù)據(jù)庫。
除此之外,二者的出發(fā)點(diǎn)都是為了穩(wěn)定、快速和持久,通常用戶都是不管三七二十一,先用了再說,且還會(huì)產(chǎn)生心理依賴,領(lǐng)導(dǎo)對(duì)于其效果也會(huì)比較滿意,自己也感覺從苦逼碼農(nóng)晉升到了金光閃閃的框架師。
雖然現(xiàn)實(shí)生活中我們很難拒絕使用緩存,但是緩存用多了也會(huì)出現(xiàn)很多問題,尤其是當(dāng)數(shù)據(jù)量大和機(jī)器多了以后,各種問題就會(huì)接踵而至。例如現(xiàn)在的緩存基本都是內(nèi)存式的,一斷電數(shù)據(jù)就沒有了,恢復(fù)起來也是相當(dāng)困難。
做了主備之后,你會(huì)發(fā)現(xiàn)備機(jī)其實(shí)沒有什么用,主機(jī)宕了,切到備機(jī)上,很多數(shù)據(jù)都是不同步的,想要同步還需要時(shí)間。前兩天,我們還討論,主備好像沒什么用,還是多主比較好用。
最關(guān)鍵的問題就是很難管理。緩存用了之后就扔不了,只敢加量,不敢減量。緩存服務(wù)器越來越多,可能從一臺(tái)變成了兩臺(tái)、四臺(tái)、八臺(tái)……不僅管理成本越來越高,寫代碼也變得很復(fù)雜,因?yàn)楹芏嗑彺嫦到y(tǒng)都會(huì)為了速度快而設(shè)在客戶端,所以,每增加一個(gè)機(jī)器,所有的客戶端都要配置,可能有的做得好的團(tuán)隊(duì)會(huì)有配置系統(tǒng)自動(dòng)完成,但要是做的不好的團(tuán)隊(duì),就需要重新發(fā)布一下程序,如果要是個(gè)新手,很可能還會(huì)給你寫成個(gè)死的。
所以,歸根結(jié)底還是要強(qiáng)身健體的,為了杜絕這些情況,我們實(shí)現(xiàn)了Lest。
首先就是緩存同步,可以做到擴(kuò)容時(shí)無感知;第二,主機(jī)宕機(jī)了也能很容易的起來,備機(jī)可能需要稍微頂一下,但主機(jī)必須很快起來,因?yàn)槲覀兊脑L問基本上一天七、八億次,如果主機(jī)宕掉打到數(shù)據(jù)庫上,緩存穿透的話,那就基本上完了。所以我們采用了上述四個(gè)策略來解決了這個(gè)問題。
我們的緩存內(nèi)容是String、List和Map。這其中List和Map的存儲(chǔ)比較難做,因?yàn)槠浒薪Y(jié)構(gòu)的數(shù)據(jù)。例如,如果要在List中查詢從第二個(gè)到第十個(gè)的數(shù)據(jù),Redis很容易就做到了,但如果是全內(nèi)存,存儲(chǔ)在磁盤上就比較困難。
所以,我們自己做了一些設(shè)計(jì)來實(shí)現(xiàn),上圖中就是我們的總體架構(gòu)圖。右上是Tracker,類似于很多大廠都在做的緩存代理層,接下來是存儲(chǔ)機(jī)器,操作機(jī)器會(huì)分段,如256段、128段等等,數(shù)據(jù)會(huì)分配到不同的段上去。通訊和存儲(chǔ)的實(shí)現(xiàn),我們用了自己設(shè)計(jì)的協(xié)議。
負(fù)載均衡,其實(shí)是老生常談了,緩存的一個(gè)最大特點(diǎn)就是key要自定義。業(yè)務(wù)自定義因?yàn)橐鎯?chǔ)到磁盤上,因此很難做類似元數(shù)據(jù)管理的工作。我們選擇的方式是Hash,不過使用Hash比較麻煩的地方是,如果機(jī)器增加的話,Hash值也會(huì)發(fā)生變化。所以,我們?cè)谠黾訖C(jī)器的時(shí)候會(huì)有一個(gè)小竅門,以2*數(shù)字的方式去增加,比如一臺(tái)變兩臺(tái),兩條邊四臺(tái),四臺(tái)變八臺(tái)。這種方式同步量是最少的,50%,假設(shè)你是一臺(tái)變?nèi)_(tái),那么動(dòng)的數(shù)據(jù)就是66.7%。如果大家是使用Hash,我建議大家用2*數(shù)字的擴(kuò)容方式會(huì)比較好。
數(shù)據(jù)存儲(chǔ)下來之后,我們就需要同步,我們有組的標(biāo)簽,同組之內(nèi)可以數(shù)據(jù)同步,相互備份,它是沒有Slave的,全部都是主。這里會(huì)牽扯到版本問題,我們后面會(huì)講到。
負(fù)載均衡的算法就是二次Hash到加權(quán)二次Hash的演變,剛開始的時(shí)候,我們使用兩次Hash去做,第一次Hash得到段,第二次Hash得到是哪臺(tái)機(jī)器,但其實(shí)ID生成器生成的ID因?yàn)闃I(yè)務(wù)的關(guān)系并不均衡,這導(dǎo)致緩存的存儲(chǔ)量大小很偏,可能出現(xiàn)一臺(tái)機(jī)器中有20%,另一臺(tái)則有80%。
這種情況也很好處理,加權(quán)就可以了,相當(dāng)于一致性Hash,每臺(tái)機(jī)器都有一個(gè)類似7%這樣的素?cái)?shù)百分?jǐn)?shù)加權(quán)。為什么選擇素?cái)?shù)呢?這是因?yàn)閷?duì)素?cái)?shù)Hash會(huì)比較均勻。
我們?cè)诖疟P上做了一個(gè)256×256的文件夾,在磁盤層面就把一些文件打亂。我們知道磁盤對(duì)小文件其實(shí)是比較可怕的,因?yàn)槭褂肧SD,我們現(xiàn)在的成本還是比較高,之后我們會(huì)考慮使用磁盤,會(huì)加類似B樹這樣子的東西。
目前,因?yàn)榭紤]到有很多小文件,選用了SSD,從而避免掉了磁盤會(huì)遇到的一些問題。如果是1億KB的數(shù)據(jù),經(jīng)過Hash放到一個(gè)文件夾中大概也只有幾百KB,不會(huì)超過3000KB,這個(gè)壓力還是可以接受的。
上圖是數(shù)據(jù)存儲(chǔ)的模型,最前面是Head,頭部加了很多元數(shù)據(jù)。比如整個(gè)是一個(gè)string,那么黃色的部分是客戶端存下來的真正內(nèi)容,len表示長(zhǎng)度,Version表示版本,我們整套都是用C來寫的,因此性能大概會(huì)提升十倍以上。并且我們還做了一個(gè)保證單調(diào)遞增的ID生成器,它的算法其實(shí)就是一個(gè)時(shí)間向量算法的衍生,解決了版本控制的問題,換句話說就是哪個(gè)數(shù)字最大,肯定就是最后的版本。Reserved代表類型,這里存的可能是string、list或者是map。同時(shí)為了未來的擴(kuò)展,我們還會(huì)有一個(gè)預(yù)留出來的地方。
其實(shí)List和Map與String差不多,大家看圖即可,就不再一一介紹了。
這些存儲(chǔ)如果要手工實(shí)現(xiàn)可能有些困難,所以我們?nèi)プ隽艘粋€(gè)HMS對(duì)象,這是一個(gè)支持全部類型的數(shù)據(jù)協(xié)議,包括int、long等等。最經(jīng)典的使用方式是部署在服務(wù)器端,因?yàn)榉?wù)器端使用C無法像Java那樣反射,這時(shí)我們會(huì)用一個(gè)數(shù)學(xué)結(jié)構(gòu)來代表整個(gè)內(nèi)容,如果使用Key的話可以達(dá)到log N的查詢效率。
以上是我們做的API,幾乎可以支持所有的操作,用法與Redis差不多,Redis能做的操作,lest基本也能做。
同步架構(gòu)如上圖,如果是同組的話,兩個(gè)storage之間到Tracker上拿到數(shù)據(jù),然后再做同步,這其中還會(huì)涉及到一個(gè)高速IP協(xié)議。
每次記錄都會(huì)產(chǎn)生binlog,將binlog分門別類的記下來,然后去其上讀即可。
同步復(fù)制狀態(tài),狀態(tài)轉(zhuǎn)移就是1+1大于等于2,控制簡(jiǎn)單,傳輸數(shù)據(jù)量大,而復(fù)制狀態(tài)機(jī),控制比較復(fù)雜,傳輸?shù)臄?shù)據(jù)其實(shí)很少。
上圖是我們第一次對(duì)lest做性能測(cè)試得到的結(jié)果。前段時(shí)間,我們申請(qǐng)到了新的機(jī)器,我們又重新做了一遍測(cè)試。
上圖是處理請(qǐng)求正確響應(yīng)數(shù),其中紅色的是萬兆服務(wù)器+SSD,黃色的是千兆服務(wù)器+SATA硬盤。得到的這個(gè)性能結(jié)果我個(gè)人認(rèn)為還有提升空間,因?yàn)槲覀兊目蛻舳瞬粔蚨?,只有十臺(tái),至少要有二三十臺(tái)才能壓出它的真實(shí)性能?,F(xiàn)在的性能數(shù)據(jù)差不多是它真正性能的60%。
從圖中我們可以看到,當(dāng)數(shù)據(jù)達(dá)到10K以上,性能其實(shí)一直在走下坡路,如果大家去對(duì)比Redis也會(huì)發(fā)現(xiàn),當(dāng)數(shù)據(jù)到10K,Redis性能也會(huì)下降45%。這說明緩存還是和小數(shù)據(jù)更合拍。
上圖是最大響應(yīng)時(shí)間,圖中的822我也不知道怎么來的,可能是一個(gè)特別異常的值,除去這個(gè)值,其它數(shù)值的狀態(tài)還是比較平穩(wěn)的,最大響應(yīng)時(shí)間的單位是毫秒,基本上是在一兩百毫秒之間。
上圖是最小響應(yīng)時(shí)間,其值基本分布在一點(diǎn)幾毫秒。
上圖是傳輸量,也就是網(wǎng)卡,很明顯,萬兆占據(jù)優(yōu)勢(shì),這是因?yàn)樗緛砭捅惹д滓?,其可能只打到?0%,還有10%的增長(zhǎng)空間。
上圖是SSD服務(wù)器壓力,CPU的狀況差不多,如果十個(gè)服務(wù)器瘋狂打,那么CPU的壓力在20%左右,隨著數(shù)據(jù)變大,處理時(shí)間變多,CPU壓力就下降了。圖中還有網(wǎng)絡(luò)的出和入,其中入會(huì)比較小,而出會(huì)比較大,如果是Redis,出會(huì)更大。
Lest的優(yōu)劣勢(shì)很明顯,它是一個(gè)吃磁盤不太吃內(nèi)存的東西,具體優(yōu)劣勢(shì)可參考上圖。相比來說,如果使用Redis服務(wù)器需要二三十臺(tái)的場(chǎng)景,lest三臺(tái)就可以扛下來。另外,相比其它緩存,lest基本可以做到寫代碼無感知,另外,我比較推薦使用SSD,因?yàn)楝F(xiàn)在SSD還是蠻便宜的,比內(nèi)存要便宜。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。