老曹眼中的緩存技術
緩存是系統快速響應中的一種關鍵技術,是一組被保存起來以備將來使用的東西,介于應用開發和系統開發之間,是產品經理們經常顧及不到的地方,算是技術架構中的非功能性約束吧。
也就是說,緩存是系統調優時常用且行之有效的手段,無論從操作系統還是應用系統,緩存策略無處不在。
很多技術都打著緩存的旗號,所以談起緩存往往似是而非,與語境有著緊密的關系,換個說法,來看一看緩存在不同場景的分類。
客戶端緩存
瀏覽器的緩存可以將之前渲染的頁面保存為文件,當用戶再次訪問時可用避開網絡連接,從而減少負載?,F在的HTML5支持了本地存儲,大部分BS 應用都可以舉重若輕了。
如何把客戶端緩存對于業務組件透明和客戶端緩存數據及時更新,是客戶端緩存能否成功應用的關鍵。
客戶端可以將內容緩存在內存,文件,或本地數據庫(例如Sqlite)中。
例如,iOS 的圖片緩存框架SDWeb架構如下:
web代理
web 代理的作用跟瀏覽器的內置緩存類似,只是位于瀏覽器和互聯網之間,網絡請求通過代理來中繼。對于企業而言,即可以節省成本,又能提高性能。
對于Web代理而言,曾經流行的是Squid,它支持建立復雜緩存層級結構的能力,詳細的日志、高性能緩存以及用戶認證支持。Squid同時支持各種插件,例如Squid Guard就是一個提供URL過濾的插件,對于屏蔽某些站點和內容十分有用。如果想分析Squid的各種指標,webalizer 應該是個不錯的選擇。
Squid 的內部機制如下:
邊緣緩存
邊緣緩存位于應用服務器的前面,可以處理來自不同用戶的請求,主要用于向用戶提供靜態的內容,以減少應用服務器的介入。邊緣緩存的商業化服務就是CDN了,例如AWS 的Cloud Front,我國的ChinaCache等。
邊緣緩存的一個有名的開源工具就是varnish,在默認情況下進行保守緩存。也就是說,varnish 只緩存它所知的安全內容。varnish的一個特性是使用虛擬內存,精妙之處在于利用了操作系統的管理機制。varnish可以高度定制如何處理請求,緩存哪些內容。
Varnish 的內部機制如下:
平臺緩存
平臺緩存是用來寫應用的框架,或者緩存的專用庫(如PHP中的Smarty模版庫)。
Java 語言中,緩存框架更多,例如EHcache,Cacheonix,Voldemort,JBoss Cache等等。
看一下EHcache的系統結構結構:
Ehcache是一個Java實現的開源分布式緩存框架,可以讓數據保存在不同服務器的內存中,在需要數據的時候可以快速存取。通過聲明配置、在xml中配置、在程序里配置或者調用構造方法時傳入不同的參數。
Voldemort是一款基于Java開發的分布式鍵-值緩存系統,像JBoss Cache一樣,Voldemort同樣支持多臺服務器之間的緩存同步,以增強系統的可靠性和讀取性能。
簡單來說,就平臺級緩存而言,只需要在框架側配置一下屬性即可,而不需要調用特定的方法或函數。
應用緩存
應用級緩存,需要自己通過代碼來實現緩存。這里是NoSQL的勝場,不論是Redis 還是MongoDB,都可以作為應用緩存的工具。一個典型的方式是,每分鐘或一段時間后統一生成某類頁面存儲在緩存中,也可以在熱數據變化時更新緩存。
Redis 在應用級緩存中的作用舉足輕重,新浪微博有著幾乎世界上最大的redis 集群。 Redis支持主從同步。數據可以從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。這使得Redis可執行單層樹復制。存盤可以有意無意的對數據進行寫操作。由于完全實現了發布/訂閱機制,使得從數據庫在任何地方同步樹時,可訂閱一個頻道并接收主服務器完整的消息發布記錄。同步對讀取操作的可擴展性和數據冗余很有幫助。
Redis 的客戶端編程語言眾多,可以滿足絕大多數的應用。
數據庫緩存
數據庫緩存是一類特殊的緩存。大多數數據庫不需要配置就可以快速運行,但并沒有為特定的需求進行優化。在數據庫調優的時候,緩存優化是一項很重要的工作。
以MySQL為例,MySQL中使用了查詢緩沖機制,將SELECT語句和查詢結果存放在緩沖區中,以后對于同樣的SELECT語句,將直接從緩沖區中讀取結果,以節省查詢時間,提高了SQL查詢的效率。
通過調節以下幾個參數可以知道query_cache_size設置得是否合理:
- Qcache inserts
- Qcache hits
- Qcache lowmem prunes
- Qcache free blocks
- Qcache total blocks
當然,深入數據庫還有很多值得學習的地方。
緩存的協議支持
對web應用而言,http1.0 提供了一些很基本的緩存特性,例如在服務器側設置Expires 的http頭來告訴客戶端在重新請求文件之前緩存多久是安全的,可以通過if-modified-since 的條件請求來使用緩存。其中,發送的時間是文件最初被下載的時間,而不是即將過期的時間,如果文件沒有改變,服務器可以用304-Not Modified 來應答。客戶端收到304代碼,就可以使用緩存的文件版本了??蛻舳丝梢栽O置Pragma:no-cache從服務器之間獲取內容。
Http 1.1有了較大的增強,緩存系統被形式化了,引入了實體標簽e-tags,是文件或對象的唯一標識。這意味著可以請求一個資源、提供所持有的文件,然后詢問服務器這個文件是否有變化。如果某一個文件的e-tag 是有效的,服務器會生成304-Not Modified 應答,并提供正確文件的e-tag,否則,發送200-OK應答。以瀏覽器為例的示意圖如下:
關于HTTP2.0中有關緩存的技術,還有待研究。
總而言之,緩存——cache,是一種挺復雜的技術,除了應用場景之外,更進一步,還要理解命中,Cache Miss,存儲成本,索引成本,失效,替代策略等諸多概念,進而了解緩存算法,分布式緩存及其同步,多級緩存的設計......真正的掌握緩存技術。
【本文來自51CTO專欄作者老曹的原創文章,作者微信公眾號:喔家ArchiSelf,id:wrieless-com】