Z_HPC_緩存策略

在服務器端程序開發(fā)領域咐刨,性能問題一直是備受關注的重點码俩。業(yè)界有大量的框架度帮、組件、類庫都是以性能為賣點而廣為人知稿存。然而笨篷,服務器端程序在性能問題上應該有何種基本思路,這個卻很少被這些項目的文檔提及瓣履。本文正式希望介紹服務器端解決性能問題的基本策略和經(jīng)典實踐率翅,并分為幾個部分來說明:


緩存策略的概念和實例

緩存策略的難點:不同特點的緩存數(shù)據(jù)的清理機制

分布策略的概念和實例

分布策略的難點:共享數(shù)據(jù)安全性與代碼復雜度的平衡

緩存策略的概念

? ? ? ? 我們提到服務器端性能問題的時候,往往會混淆不清拂苹。因為當我們訪問一個服務器時安聘,出現(xiàn)服務卡住不能得到數(shù)據(jù),就會認為是“性能問題”瓢棒。但是實際上這個性能問題可能是有不同的原因浴韭,表現(xiàn)出來都是針對客戶請求的延遲很長甚至中斷。我們來看看這些原因有哪些:第一個是所謂并發(fā)數(shù)不足脯宿,也就是同時請求的客戶過多念颈,導致超過容納能力的客戶被拒絕服務,這種情況往往會因為服務器內(nèi)存耗盡而導致的连霉;第二個是處理延遲過長榴芳,也就是有一些客戶的請求處理時間已經(jīng)超過用戶可以忍受的長度嗡靡,這種情況常常表現(xiàn)為CPU占用滿額100%。

? ? ? ? 我們在服務器開發(fā)的時候窟感,最常用到的有下面這幾種硬件:CPU讨彼、內(nèi)存、磁盤柿祈、網(wǎng)卡哈误。其中CPU是代表計算機處理時間的,硬盤的空間一般很大躏嚎,主要是讀寫磁盤會帶來比較大的處理延遲蜜自,而內(nèi)存、網(wǎng)卡則是受存儲卢佣、帶寬的容量限制的重荠。所以當我們的服務器出現(xiàn)性能問題的時候,就是這幾個硬件某一個甚至幾個都出現(xiàn)負荷占滿的情況虚茶。這四個硬件的資源一般可以抽象成兩類:一類是時間資源戈鲁,比如CPU和磁盤讀寫;一類是空間資源媳危,比如內(nèi)存和網(wǎng)卡帶寬荞彼。所以當我們的服務器出現(xiàn)性能問題,有一個最基本的思路待笑,就是——時間空間轉(zhuǎn)換鸣皂。我們可以舉幾個例子來說明這個問題。

[水壩就是用水庫空間來換流量時間的例子]

? ? ? ? 當我們訪問一個WEB的網(wǎng)站的時候暮蹂,輸入的URL地址會被服務器變成對磁盤上某個文件的讀取寞缝。如果有大量的用戶訪問這個網(wǎng)站,每次的請求都會造成對磁盤的讀操作仰泻,可能會讓磁盤不堪重負荆陆,導致無法即時讀取到文件內(nèi)容。但是如果我們寫的程序集侯,會把讀取過一次的文件內(nèi)容被啼,長時間的保存在內(nèi)存中,當有另外一個對同樣文件的讀取時棠枉,就直接從內(nèi)存中把數(shù)據(jù)返回給客戶端浓体,就無需去讓磁盤讀取了。由于用戶訪問的文件往往很集中辈讶,所以大量的請求可能都能從內(nèi)存中找到保存的副本命浴,這樣就能大大提高服務器能承載的訪問量了。這種做法,就是用內(nèi)存的空間生闲,換取了磁盤的讀寫時間媳溺,屬于用空間換時間的策略。

[方便面預先緩存了大量的烹飪操作]

? ? ? ? 舉另外一個例子:我們寫一個網(wǎng)絡游戲的服務器端程序碍讯,通過讀寫數(shù)據(jù)庫來提供玩家資料存檔悬蔽。如果有大量玩家進入這個服務器,必定有很多玩家的數(shù)據(jù)資料變化捉兴,比如升級屯阀、獲得武器等等,這些通過讀寫數(shù)據(jù)庫來實現(xiàn)的操作轴术,可能會讓數(shù)據(jù)庫進程負荷過重,導致玩家無法即時完成游戲操作钦无。我們會發(fā)現(xiàn)游戲中的讀操作逗栽,大部分都是針是對一些靜態(tài)數(shù)據(jù)的,比如游戲中的關卡數(shù)據(jù)失暂、武器道具的具體信息彼宠;而很多寫操作,實際上是會覆蓋的弟塞,比如我的經(jīng)驗值凭峡,可能每打一個怪都會增加幾十點,但是最后記錄的只是最終的一個經(jīng)驗值决记,而不會記錄下打怪的每個過程摧冀。所以我們也可以使用時空轉(zhuǎn)換的策略來提供性能:我們可以用內(nèi)存,把那些游戲中的靜態(tài)數(shù)據(jù)系宫,都一次性讀取并保存起來索昂,這樣每次讀這些數(shù)據(jù),都和數(shù)據(jù)庫無關了扩借;而玩家的資料數(shù)據(jù)椒惨,則不是每次變化都去寫數(shù)據(jù)庫,而是先在內(nèi)存中保持一個玩家數(shù)據(jù)的副本潮罪,所有的寫操作都先去寫內(nèi)存中的結構康谆,然后定期再由服務器主動寫回到數(shù)據(jù)庫中,這樣可以把多次的寫數(shù)據(jù)庫操作變成一次寫操作嫉到,也能節(jié)省很多寫數(shù)據(jù)庫的消耗沃暗。這種做法也是用空間換時間的策略。

[拼裝家具很省運輸空間屯碴,但是安裝很費時]

? ? ? ? 最后說說用時間換空間的例子:假設我們要開發(fā)一個企業(yè)通訊錄的數(shù)據(jù)存儲系統(tǒng)描睦,客戶要求我們能保存下通訊錄的每次新增、修改导而、刪除操作忱叭,也就是這個數(shù)據(jù)的所有變更歷史隔崎,以便可以讓數(shù)據(jù)回退到任何一個過去的時間點。那么我們最簡單的做法韵丑,就是這個數(shù)據(jù)在任何變化的時候爵卒,都拷貝一份副本。但是這樣會非常的浪費磁盤空間撵彻,因為這個數(shù)據(jù)本身變化的部分可能只有很小一部分钓株,但是要拷貝的副本可能很大。這種情況下陌僵,我們就可以在每次數(shù)據(jù)變化的時候轴合,都記下一條記錄,內(nèi)容就是數(shù)據(jù)變化的情況:插入了一條內(nèi)容是某某的聯(lián)系方法碗短、刪除了一條某某的聯(lián)系方法……受葛,這樣我們記錄的數(shù)據(jù),僅僅就是變化的部分偎谁,而不需要拷貝很多份副本总滩。當我們需要恢復到任何一個時間點的時候,只需要按這些記錄依次對數(shù)據(jù)修改一遍巡雨,直到指定的時間點的記錄即可闰渔。這個恢復的時間可能會有點長,但是卻可以大大節(jié)省存儲空間。這就是用CPU的時間來換磁盤的存儲空間的策略。我們現(xiàn)在常見的MySQLInnoDB日志型數(shù)據(jù)表叹卷,以及SVN源代碼存儲,都是使用這種策略的炕舵。

另外,我們的Web服務器跟畅,在發(fā)送HTML文件內(nèi)容的時候咽筋,往往也會先用ZIP壓縮,然后發(fā)送給瀏覽器徊件,瀏覽器收到后要先解壓奸攻,然后才能顯示,這個也是用服務器和客戶端的CPU時間虱痕,來換取網(wǎng)絡帶寬的空間睹耐。


圖片發(fā)自簡書App

在我們的計算機體系中,緩存的思路幾乎無處不在部翘,比如我們的CPU里面就有1級緩存硝训、2級緩存,他們就是為了用這些快速的存儲空間,換取對內(nèi)存這種相對比較慢的存儲空間的等待時間窖梁。我們的顯示卡里面也帶有大容量的緩存赘风,他們是用來存儲顯示圖形的運算結果的。

[通往大空間的郊區(qū)路上容易交通堵塞]

緩存的本質(zhì)纵刘,除了讓“已經(jīng)處理過的數(shù)據(jù)邀窃,不需要重復處理”以外,還有“以快速的數(shù)據(jù)存儲讀寫假哎,代替較慢速的存儲讀寫”的策略瞬捕。我們在選擇緩存策略進行時空轉(zhuǎn)換的時候,必須明確我們要轉(zhuǎn)換的時間和空間是否合理舵抹,是否能達到效果肪虎。比如早期有一些人會把WEB文件緩存在分布式磁盤上(例如NFS),但是由于通過網(wǎng)絡訪問磁盤本身就是一個比較慢的操作惧蛹,而且還會占用可能就不充裕的網(wǎng)絡帶寬空間笋轨,導致性能可能變得更慢。

在設計緩存機制的時候赊淑,我們還容易碰到另外一個風險,就是對緩存數(shù)據(jù)的編程處理問題仅讽。如果我們要緩存的數(shù)據(jù)陶缺,并不是完全無需處理直接讀寫的,而是需要讀入內(nèi)存后洁灵,以某種語言的結構體或者對象來處理的饱岸,這就需要涉及到“序列化”和“反序列化”的問題。如果我們采用直接拷貝內(nèi)存的方式來緩存數(shù)據(jù)徽千,當我們的這些數(shù)據(jù)需要跨進程苫费、甚至跨語言訪問的時候,會出現(xiàn)那些指針双抽、ID百框、句柄數(shù)據(jù)的失效。因為在另外一個進程空間里牍汹,這些“標記型”的數(shù)據(jù)都是不存在的铐维。因此我們需要更深入的對數(shù)據(jù)緩存的方法,我們可能會使用所謂深拷貝的方案慎菲,也就是跟著那些指針去找出目標內(nèi)存的數(shù)據(jù)嫁蛇,一并拷貝。一些更現(xiàn)代的做法露该,則是使用所謂序列化方案來解決這個問題睬棚,也就是用一些明確定義了的“拷貝方法”來定義一個結構體,然后用戶就能明確的知道這個數(shù)據(jù)會被拷貝,直接取消了指針之類的內(nèi)存地址數(shù)據(jù)的存在抑党。比如著名的Protocol Buffer就能很方便的進行內(nèi)存包警、磁盤、網(wǎng)絡位置的緩存新荤;現(xiàn)在我們常見的JSON揽趾,也被一些系統(tǒng)用來作為緩存的數(shù)據(jù)格式。

但是我們需要注意的是苛骨,緩存的數(shù)據(jù)和我們程序真正要操作的數(shù)據(jù)篱瞎,往往是需要進行一些拷貝和運算的,這就是序列化和反序列化的過程痒芝,這個過程很快俐筋,也有可能很慢。所以我們在選擇數(shù)據(jù)緩存結構的時候严衬,必須要注意其轉(zhuǎn)換時間澄者,否則你緩存的效果可能被這些數(shù)據(jù)拷貝、轉(zhuǎn)換消耗去很多请琳,嚴重的甚至比不緩存更差粱挡。一般來說,緩存的數(shù)據(jù)越解決使用時的內(nèi)存結構俄精,其轉(zhuǎn)換速度就越快询筏,在這點上,Protocol Buffer采用TLV編碼竖慧,就比不上直接memcpy的一個C結構體嫌套,但是比編碼成純文本的XML或者JSON要來的更快。因為編解碼的過程往往要進行復雜的查表映射圾旨,列表結構等操作踱讨。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市砍的,隨后出現(xiàn)的幾起案子痹筛,更是在濱河造成了極大的恐慌,老刑警劉巖廓鞠,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件味混,死亡現(xiàn)場離奇詭異,居然都是意外死亡诫惭,警方通過查閱死者的電腦和手機翁锡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夕土,“玉大人馆衔,你說我怎么就攤上這事瘟判。” “怎么了角溃?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵拷获,是天一觀的道長。 經(jīng)常有香客問我减细,道長匆瓜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任未蝌,我火速辦了婚禮驮吱,結果婚禮上,老公的妹妹穿的比我還像新娘萧吠。我一直安慰自己左冬,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布纸型。 她就那樣靜靜地躺著拇砰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狰腌。 梳的紋絲不亂的頭發(fā)上除破,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音琼腔,去河邊找鬼皂岔。 笑死,一個胖子當著我的面吹牛展姐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剖毯,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼圾笨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了逊谋?” 一聲冷哼從身側(cè)響起擂达,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎胶滋,沒想到半個月后板鬓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡究恤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年俭令,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片部宿。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡抄腔,死狀恐怖瓢湃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赫蛇,我是刑警寧澤绵患,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站悟耘,受9級特大地震影響落蝙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜暂幼,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一筏勒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粟誓,春花似錦奏寨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悲酷,卻和暖如春套菜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背设易。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工逗柴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人顿肺。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓戏溺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親屠尊。 傳聞我的和親對象是個殘疾皇子旷祸,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 在服務器端程序開發(fā)領域,性能問題一直是備受關注的重點讼昆。業(yè)界有大量的框架托享、組件、類庫都是以性能為賣點而廣為人知浸赫。然而...
    零一間閱讀 864評論 0 12
  • 在服務器端程序開發(fā)領域既峡,性能問題一直是備受關注的重點羡榴。業(yè)界有大量的框架、組件运敢、類庫都是以性能為賣點而廣為人知炕矮。然而...
    dreamer_lk閱讀 1,001評論 0 17
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評論 25 707
  • 阿彌陀佛么么噠
    洋六六閱讀 354評論 0 0
  • 我向你跪拜 我對你虔誠 我為你點亮油燈 我聲稱自己是罪人 我向你祈福 我對你叩問 我為你塑了金身 我聲稱要拯救自己...
    晚樹閱讀 413評論 13 25