2016-04-25-信息系統實踐手記5-CACHE設計一例


layout: post
title: 2016-04-25-信息系統實踐手記5-CACHE設計一例
key: 20160425
tags: 業務 場景 CACHE 系統分析 系統設計 緩存
modify_date: 2016-04-25
---html

信息系統實踐手記5-CACHE設計一例

說明:git

正文:程序員

  • 信息系統實踐手記系列是系筆者在平時研發中前後遇到的大小的問題,其中比較典型的內容加以收集和分享。
  • 信息系統實踐手記目錄:博客園(或查看源碼的README.MD文件)

摘要:github

  • 此文描述了對CACHE緩存的一些理解。

正文web

1.CACHE是啥?

最近一直在瞭解scala,Spark,Python,數據挖掘,以及複雜科學的一些內容,在充實和忙碌之餘,雖興趣濃厚,但體力不支,疲勞的很,無奈耽擱了實踐手記。
本來計劃2周掛出一篇來分享,實在抱歉。要分享的東西太多,碼字太費時間,有時候甚至以爲開會也許更好(不少人反感開會,那是由於沒開太高效的會)!其實不少東西主要仍是考本身去走,去體會。
閒話不說,切入正題。
不少研發人員,尤爲是開發程序的同志,找到一個cache框架或類庫可用,好比hibernate的cache功能,而後就一股腦用上去。雖然會有效果,很愉悅,是好事,既增長經驗,也體會了框架的魅力和效率,
但其實還有東西能夠進一步去領會。究竟爲啥要用CACHE?CACHE是啥?什麼樣的場景用什麼樣的CACHE?不多有人問。
那CACHE究竟是啥呢?還真難於表述清晰,但有一些要點:
  • CACHE的產生是爲了緩解處理鏈上不一樣節點之間速度不協調的狀況。舉例若干:
    • 計算機系統:通常有速度梯度:CPU內部寄存器(register)IO>內存IO>磁盤IO>網絡IO,爲協調它們之間傳遞數據的速度差,就可設置緩存結構,叫CACHE;
      • 說明1:以上說的是通常狀況,不考慮特別的磁陣RAID,高速SCSI,千兆或萬兆網絡等;
      • 說明2:CPU內部也分L1,L2,L3等多級寄存器結構,當作多級CACHE使用,早先的386/486處理器沒分那麼多層次;
    • 地鐵系統:有時候出事故,人特多,站內站外由管理員把守入口分批放人到1層大廳,則1層大廳是一個CACHE;管理員分批從大廳放人到B1層站臺,則B1站臺也是一個CACHE;當CACHE快撐滿的時候,管理員就會喊「慢慢來,不要擠,暫時關閉,你們耐心等待!」,因而人就被囤積在不一樣的CACHE裏,以便協調地鐵運量和人流涌入的速度差問題。
    • 工廠流水線:另外一個典型例子是工廠的流水線。之前老式流水線每一個工位站1我的,處理1個裝配動做,好比給黃小鴨玩具裝上1條腿。一個工件,若是流經10個處理節點,那就會有10我的來處理10個步驟。顯然,老闆指望流水線一直處於充滿狀態,則最高效的源源不斷有產出。但意外總會發生,好比某工件N流轉到Px節點,Px節點的工人很累,處理較慢,致使Px-1步驟流出的工件不斷堆積,而這個Px處理節點處理臺的工件堆積場所,就是一個BUFFER緩存區(也就是CACHE),它愈來愈滿,就提醒Px的工人,加緊幹,不然一旦CACHE撐爆,就沒法克服(追上)速度差(時間差)的問題!(畫外音:能夠看出流水線機制的高效和科學,以及「殘酷」)。
    • 生產者消費者模式:經典的程序設計模式「生產者和消費者」模型也有一個CACHE的設計,就是協調生產和消費的速度差,相似「工廠流水線」
  • CACHE其實是用空間上的代價來緩解時間上的不協調。
    • 你確定要問「既然速度有差別,那CACHE再大也沒用?」,的確,再大的CACHE也是用來臨時克服速度差別的,它指望能夠用空間暫時的堆積追回偶發致使的時間不協調(速度差是絕對的,這個在設計場景以前就知道,但速度不協調是偶發的,這個要區別開!)。若是永遠沒法「追回來」,那麼再大的CACHE也會有問題,那麼就是設計上的問題,就不是CACHE機制能夠解決的。
    • 處理節點Px每每速度不一樣,因此必須用不一樣算法來安排。好比:
      • 經過編譯器編譯的源碼,會根據OS的不一樣及其內存頁面調度算法,互相結合,處理好代碼的擺放,並充分考慮到CPU/MEM/DISK/NETWORK的差別;保持MEM代碼段高命中,下降頁丟失中斷,等等。
      • 程序自己也應該充分利用諸如「多線程」,「併發計算」,「分佈式計算」等方法,來從宏觀的算法層面,解決掉速度差別,從而適當的利用CACHE來防止偶發的速度不協調,而不是算法自己有永久性的硬傷「速度不匹配」。能夠適當的使用一些主流成熟前三名的框架來解決實際問題。
      • 程序終究是要達成業務須要的,也就是完成功能目標(Feature)。而功能和業務自己是有特色的,有時空特性的,是高併發業務?仍是隨機業務?業務的時空特性如何?是否和上下班高峯有關? 是否和網站的維護週期有關?是否和購物的時間段有關?總之從業務觸發,須要專業的領域知識(行業支持),而且須要深厚的技術功底,這樣的從場景出發的系統分析和系統設計行爲,是何其重要!這方面的人才很是緊缺。
  • CACHE所處理的時空不協調,多是偶發的,也多是來自於業務模型;
    • 經過上述的不一樣層次(編譯器,OS,程序,框架類庫,業務場景分析)的討論,基本上能妥善的處理業務,達成場景,使用必要的CACHE結構。但業務模型老是會偶發時空不一致,尤爲是在當今多任務的計算機架構(之前主機時代只有大型機是多進程的,如今微機也是多任務並細化到線程)。很容易計算力不夠須要增長更多CPU的core,數據量大沒地方放,就增長MEM,MEM增長後也會致使低速的磁盤IO和網絡IO也變大。
    • 另外在對業務模型不斷調優和擴容的過程當中,不協調也會天然產生的,而若是程序模型比較優秀,相關必要的地方原本就有CACHE,那麼CACHE將爲程序運做提供餘地。
    • 即使是簡單的業務模型,並且調優完成,且一直正常運做。但也可能由於「網絡故障,CPU失效,內存或磁盤損壞,某個計算節點離線」等問題而打破平衡。這時候,甚至連寫LOG日誌來記錄狀態也顯得很奢侈或捉襟見肘。此時,若是程序在框架設計上已經未雨綢繆的安排了充分和必要的CACHE,則徹底能夠提高健壯性,甚至在偶發災難衝擊中堅強運行,恢復運做。
  • 客觀世界和程序世界都是複雜的,而複雜系統常常引起意外和不協調,CACHE則應運而生:
    • CPU裏面的微指令集中用到了L1,L2,L3,它們就是各級CACHE;
    • MEM,DISK,網卡等設備,不管在硬件的接口驅動程序BIOS中,仍是在程序員編制的應用程序中,都安排了CACHE,來處理設備受到外界速度不匹配的衝擊。
    • 程序設計中不少模式,好比消費者生產者,就必然有CACHE存在,以緩解生產和消費的速度不匹配;
    • 真實世界的倉庫存貨,小超市囤貨,高架路上的緊急停車帶,上下岔道區域,展覽會門口的回形排隊護欄,流水線的每一個節點的BUFFER緩衝帶等等,都是CACHE的好例子;

只有理解了天然現象,業務規律和程序能力邊界,才能深刻體會如何在程序設計中,在什麼樣的業務場景下使用怎樣的CACHE設計,以便到達好處和結果。不建議只爲了技術用技術,必須明確使用的目的爲什麼,才能正確的使用。算法

2.CACHE設計一例

這裏簡單舉一個例子,仍是前幾篇分享的客戶端和服務器,它們是提供GIS地圖服務的服務器和客戶端;而這個提供GIS業務的服務器就用到不少CACHE; 撇開客戶端業務展示不說,不少後臺服務是由作GIS業務的應用SERVER提供,簡稱爲GS,而GS須要從設備管理平臺,簡稱DS獲取設備信息;設計模式

  • 由於DS不提供設備信息的訂閱(很遺憾),則沒法使用高效的觀察者模式來獲取設備變動信息,而只能由GS經過階段同步(輪詢模型)來花巨大的代價向DS獲取其實不多變化的設備更新信息。爲了階段同步,GS只能在內存(或DB)作了一個CACHE,來存放好比每30分鐘的同步信息;
  • 最早是X分鐘同步,按照經典作法,同步數據放在DB。但爲提高速度,解決業務場景的高速要求和DB處理的慢速狀況,將DB的數據「上提」到內存的CACHE中,之後作業務直接查CACHE,處理CACHE;這裏就天然的引起了一個問題,CACHE的髒數據須要同步回到DB,由於數據存在於兩個地方,一個CACHE是臨時的,一個DB是持久化的,那麼它們之間也有同步問題,這是使用CACHE常常要面臨的狀況。其實最後由於原來程序框架作的不佳,致使了批量修改完成後,還遺留了很多小尾巴,只能case by case的修復,不細說。
  • 咱們GS平臺,還和第三方,好比一個城市的路口卡口管理平臺(簡稱KS)對接,上次講過平臺對接問題了,這裏假設順利對接。那麼KS的數據,也會階段性的同步到咱們GS來。一個典型的應用是GS向KS訂閱了一種「告警A」,當KS發生事件A而發出「告警A」時,將會推送到GS平臺,那麼GS平臺分發給客戶端。這裏顯然有速度的不協調,若是告警頻繁,GS一時處理不過來,那麼就要CACHE,怎麼弄?也能夠不用本身寫代碼,咱們GS和GS的客戶端是經過ActiveMQ的消息中間件來傳遞消息。訂閱以後,不一樣主題的消息和用戶就會有本身的BUFFER來存放,即使KS平臺突發大量告警A到GS,GS來不及分發,那就放入MQ本身管理的緩存隊列,MQ本身處理。固然這裏咱們看到了上面討論過的CACHE的幾個問題:
    • 若是KS平臺的「告警A」一直高頻持續發送,那麼最終GS接收代碼來不急放入MQ,或者來得及放入MQ,但MQ終將崩潰。因此這裏就遇到了前幾篇提到的平臺對接中,對兩個有交互的平臺之間的信令和數據的「時空特性」必定要定義清晰,好比咱們GS和KS就定義了最高併發不能超過1秒10條(10CAPS),不然GS拒絕而不是經過CACHE儘可能容納和處理。萬事都有限度,討論清楚就行!
    • 這裏還有一個隱蔽問題,你們不知道看出來沒有。這裏假設我GS的JAVA接收代碼,從網絡socket套接字獲取的批量字節流,速度極快,放入MQ幾乎不花時間。若是沒有這個假設,並且放入速度的確很慢,那麼MQ不會最終「爆炸」,首先奔潰的及時GS的接收代碼片斷。這個判斷,通常是根據程序員的經驗和業界的經驗來肯定的。它老是很是快,放入message,通常老是比消費處理message快很多。
  • CACHE也能存在於高層次和高抽象級別的。好比當前的hibernate庫支持對象到DATA MODEL的映射,而業務是針對對象,不是直接赤裸的和數據交互的。針對對象的操做好比func1()也是能夠CACHE緩存的,以便第二次一樣的調用func1()的時候,極大的提高速度和效率。 這裏固然也會看到一個髒數據和失效的問題,再也不討論。

END

相關文章
相關標籤/搜索