除了常見的redis/memcache等程序外快取服務,還能怎麼快取資料?
快取還有一種常見的玩法,程序內快取。
什麼是程序內快取?
將一些資料快取在站點,或者服務的程序內,這就是程序內快取。
程序內快取的實現載體,最簡單的,可以是乙個帶鎖的map。又或者,可以使用第三方庫,例如leveldb。
程序內快取能儲存啥?
redis/memcache等程序外快取服務能存什麼,程序內快取就能存什麼。
如上圖,可以儲存json資料,可以儲存html頁面,可以儲存物件。
程序內快取有什麼好處?
與沒有快取相比,程序內快取的好處是,資料讀取不再需要訪問後端,例如資料庫。
如上圖,整個訪問流程要經過1,2,3,4四個步驟。
如果引入程序內快取,
如上圖,整個訪問流程只要經過1,2兩個步驟。
與程序外快取相比(例如redis/memcache),程序內快取省去了網路開銷,所以一來節省了內網頻寬,二來響應時延會更低。
程序內快取有什麼缺點?
統一快取服務雖然多一次網路互動,但仍是統一儲存。
如上圖,站點和服務中的多個節點訪問統一的快取服務,資料統一儲存,容易保證資料的一致性。
而程序內快取,如上圖,如果資料快取在站點和服務的多個節點內,資料存了多份,一致性比較難保障。
如何保證程序內快取的資料一致性?
保障程序內快取一致性,有幾種方案。
第一種方案,可以通過單節點通知其他節點。如上圖:寫請求發生在server1,在修改完自己記憶體資料與資料庫中的資料之後,可以主動通知其他server節點,也修改記憶體的資料。
這種方案的缺點是:同一功能的乙個集群的多個節點,相互耦合在一起,特別是節點較多時,網狀連線關係極其複雜。
第二種方案,可以通過mq通知其他節點。如上圖,寫請求發生在server1,在修改完自己記憶體資料與資料庫中的資料之後,給mq發布資料變化通知,其他server節點訂閱mq訊息,也修改記憶體資料。
這種方案雖然解除了節點之間的耦合,但引入了mq,使得系統更加複雜。
前兩種方案,節點數量越多,資料冗餘份數越多,資料同時更新的原子性越難保證,一致性也就越難保證。
第三種方案,為了避免耦合,降低複雜性,乾脆放棄了「實時一致性」,每個節點啟動乙個timer,定時從後端拉取最新的資料,更新記憶體快取。在有節點更新後端資料,而其他節點通過timer更新資料之間,會讀到髒資料。
為什麼不能頻繁使用程序內快取?
分層架構設計,有一條準則:站點層、服務層要做到無資料無狀態,這樣才能任意的加節點水平擴充套件,資料和狀態盡量儲存到後端的資料儲存服務,例如資料庫服務或者快取服務。
可以看到,站點與服務的程序內快取,實際上違背了分層架構設計的無狀態準則,故一般不推薦使用。
什麼時候可以使用程序內快取?
以下情況,可以考慮使用程序內快取。
情況一,唯讀資料,可以考慮在程序啟動時載入到記憶體。
畫外音:此時也可以把資料載入到redis / memcache,程序外快取服務也能解決這類問題。
情況二,極其高併發的,如果透傳後端壓力極大的場景,可以考慮使用程序內快取。
例如,秒殺業務,併發量極高,需要站點層擋住流量,可以使用記憶體快取。
情況三,一定程度上允許資料不一致業務。
例如,有一些計數場景,運營場景,頁面對資料一致性要求較低,可以考慮使用程序內頁面快取。
末了,再次強調,程序內快取的適用場景並不如redis/memcache廣泛,不要為了炫技而使用。
更多的時候,還是老老實實使用redis/mc吧。
快取預熱,快取穿透,快取擊穿,快取雪崩是怎麼回事?
快取預熱 系統啟動前,提前將相關的快取資料直接載入到快取系統 避免在使用者請求的時候,先查詢資料庫,然後再將資料快取 快取穿透 查詢乙個不存在的資料,由於快取未命中,最終去查資料庫 當高併發時,資料庫可能崩潰 解決 對查詢結果為null的資料進行快取,並設定乙個短暫過期時間 key加密,問題出現後,...
持久化快取(伺服器到底要怎麼設定快取)
這個問題最初是8月初qq 現場面試的時候有問到過,當我打算流暢的從瀏覽器快取策略到快取位置大談特談的時候,面試官打斷了我,直接問 伺服器怎麼設定各種資源的快取,快取多久?那如果專案已經上線還在強快取範圍內的時候頁面出現bug,該怎麼替換這個頁面?q 伺服器怎麼設定各種資源的快取,快取多久?首先是靜態...
nginx memcache快取服務
目標 利用memcache實現nginx對頁面 資源的快取,提高響應速度。前提 1 nginx lua模組。搭建nginx lua環境參見nginx lua redis構建高併發應用 ubuntu 和nginx lua redis構建高併發應用 centos rehat 2 memcache服務已啟...