快取伺服器設計與實現(六)
本文講快取中的內容管理–檔案的刪除。
基本原理
快取系統中的檔案,從無到有是被動產生的。初始狀態,快取系統中是空的,請求過來之後,快取會回源取,然後存在本地。而不像web伺服器,檔案是通過其他的手段(傳統的是通過ftp上傳)來建立的,這個建立檔案的過程對web伺服器來說是無感知的,請求到伺服器以後,server會按照url的路徑跟伺服器配置的docroot來到本機的檔案系統裡去定位相應的檔案,如果存在,那麼迴應200 OK,併發送檔案內容,如果不存在,則迴應404 Not Found。相對來說,快取伺服器自身是不會給響應404的,除非它取源取到的就是404迴應。
檔案一旦被快取伺服器建立,將一直存在。在沒有外界干涉的情況下,檔案有兩種消亡方式。第一就是檔案的快取時間到了。因為任何一個被快取的內容,都是有保鮮時間的。保鮮時間要麼是源給指定的(Expires等相關欄位),要麼源沒有指定,由CDN快取伺服器自身策略給指定的預設時間。檔案一旦過期,快取就會回源驗證原始檔案是否被更新了,如果沒有更新,源站會給出304迴應。更新了的話,則會給200 ok,並回傳相應檔案內容。第二就是快取伺服器本身儲存空間達到了上限,這個時候快取就會通過自己的LRU機制來淘汰“較冷”的內容。
除了這兩種情況外,還有一種特殊情況,就是當前快取的檔案還沒有過期,但是此刻源站已經修改了檔案。那麼在cdn快取中的檔案過期之前,使用者都不能訪問到最新的內容,這個時候就需要通過外界來干預。這裡就用到了一種http請求,方法名叫PURGE。這個方法幾乎已經是快取裡的跟GET,HEAD,POST處於相同地位的重要方法。PURGE請求告訴快取伺服器,該url對應的檔案需要從系統裡刪除。刪除以後,再來的請求,就會由於快取裡不存在相應檔案而去取源。
PURGE請求的產生一般來自CDN系統內部,使用者會通過一些CDN提供的任務系統來告知CDN,自己需要刪除哪些檔案。CDN會通過一定的方式來獲取該任務並生成PURGE請求,來向對應快取服務平臺,發起PURGE請求。在快取系統的配置裡,一般都會對PURGE請求的發起方的ip做限制,如果不做限制,那麼後果可想而知。
PURGE請求如果找到了檔案,並執行了刪除,那麼會收到200 OK。如果檔案還不存在,那麼會收到404 Not Found。這是一般快取伺服器預設的行為。
PURGE請求到達快取伺服器之後,處理流程在全半段跟GET類似,也是根據一定的方式去定位檔案(一般是用請求url的不同成分算出一個key),定位到檔案之後,PURGE請求就跟GET不一樣了。它會將檔案標記為deleted(快取裡都是非同步來實現淘汰的,因為當前要刪除的檔案,可能還有人在訪問,不能立即將相關資訊刪除。當檔案引用計數為0,並且狀態為deleted時,檔案自然會被系統幹掉),來淘汰掉一個檔案。
多副本問題
如果僅僅通過url的可以來PURGE檔案,那麼當存在多副本(同一url對應不同形式的檔案,最常見的是壓縮跟非壓縮)的情況下,就存在問題。所以對於快取存在多副本的情況下,有兩種處理方式,一種就是隻刪除特定副本(例如壓縮和非壓縮的某一種),一種情況就是刪除所有的副本。在實際運作過程中,第二種是預設的。如果處理第二種,那麼就需要在key匹配的基礎上做進一步的處理。在很多的簡單快取實現裡,多副本存放在某個hash表槽位的衝突鏈上(因為key相同),那麼在處理時就需要遍歷整個鏈,每個副本都需要刪除。
nginx的第三方purge模組在處理多副本的問題上存在缺陷,導致單純的使用url來purge會導致不同的副本不能被刪除乾淨。當然出現這個情況的前提是,nginx的快取開啟了vary功能,而該purge模組又沒有對vary提供必要的支援。對於nginx出現的情況,很多小夥伴在發PURGE請求時,都加入了相應的Accept-Encoding頭。這樣就可以清理相應的壓縮副本了。
關於多副本和Vary頭的問題,後面單獨來講吧
分散式問題
這個算是,更廣義上的多副本問題。一般CDN都存在多層結構,使用者直接訪問到的快取伺服器,叫做邊緣層,邊緣層到源站之間一般還有一到兩級的父層。層級越多,回源量就越少,隨之latency會增加。那麼當我們要刪除一個檔案,如果先PURGE了邊緣cache,那麼後續請求就會穿過邊緣cache到達父層,這時由於父層的舊檔案還存在,那麼邊緣又會將舊檔案取走,白忙活。所以面對這種帶有層級的快取架構,一般都是從父層往邊緣逐級PURGE檔案。
那麼所有的問題都解決了?不是。很多CDN的快取節點,邊緣也好,父層也好。都是有叢集的。比如幾臺機器做的叢集,假設有A,B,C,D四臺。一般快取伺服器都會做基於七層的一致性hash,來保證增刪叢集內的機器不會帶來過大的內容遷移。我們看一種情形,如果檔案1.html存在C機器,當C重啟下線,那麼這時你通過http向叢集(往往只是一個vip)發起PURGE請求來刪除1.html,由於C機器的下線,檔案在叢集內就不存在了。你收到404 Not Found,PURGR請求處理完成。隨後,C機器又活過來,重新加入了叢集。那麼舊的1.html檔案,又再次出現在系統內,便帶來了嚴重的問題。
上面討論的這個情景,在http協議下是無解的。必須引入其他的手段來處理。解決方案有很多,首先不能針對VIP發PURGE請求,要對每一個叢集機器內搜有機器的真實IP發PURGE。這樣就不會受叢集架構的影響,每個機器的執行情況可以得到。對應執行結果要有監控,狀態無非三種,成功(200 OK或者404 Not Found),失敗(其他非預期的響應碼),無響應(宕機了)。上層需要收集這些執行情況,並做彙總。這樣才可以保證檔案被徹底處理乾淨。
那麼,PURGE任務的下發和消費,比較好的方案,應該就是訊息隊列了。大家可以自行去研究。
相關推薦
快取伺服器設計與實現(六)
本文講快取中的內容管理–檔案的刪除。 基本原理 快取系統中的檔案,從無到有是被動產生的。初始狀態,快取系統中是空的,請求過來之後,快取會回源取,然後存在本地。而不像web伺服器,檔案是通過其他的手段(傳統的是通過ftp上傳)來建立的,這個建立檔案
模型類的設計與實現(四)
介紹 傳遞數據 規則 添加 play using ota 實體類 重要 實體類是現實實體在計算機中的表示。它貫穿於整個架構,負擔著在各層次及模塊間傳遞數據的職責。 一般來說,實體類可以分為“貧血實體類”和“充血實體類”,前者僅僅保存實體的屬性,而後者還包含一些實體間的關系與
Redis 設計與實現 (三)
check 就會 鍵值 鍵值對 是否 second 變化 write 次數 RDB 持久化 一、生成RDB cmd:SAVE --阻塞進程,執行完,才能有效接收客戶端命令。 cmd: BGSAVE --非阻塞,開啟子進程保存。 客
hadoop雲盤client的設計與實現(一)
white 下一跳 -c 文件 。。 edi track ++ ava 近期在hadoop雲盤client項目。在做這個項目曾經對hadoop是一點都不了解呀,在網
Redis 設計與實現 (五)--多機數據庫的實現
緩沖 所有 moved 啟動 tin 當前 body ica red 多機數據庫的實現 一、復制 slaveof 主服務器ip地址。形成主從關系。 1、同步 從向主服務器發送sync命令。 主服務器收到sync命令執行bgsav
Redis 設計與實現 (七)--事務
實現 標識 AC redis 服務 監視 不執行 get 狀態切換 事務 *ACID,指數據庫事務正確執行的四個基本要素的縮寫。包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability) redis
Redis 設計與實現 (八)--排序、慢查詢日誌、監視器
監視 strong add 2.4 bsp log 格式 sadd 請求 一、排序 SORT <key> 對一個數字值的key進行排序 1、alpha 對字符串類型的鍵進行排序 2、asc / desc redis 默認升序排序asc
認證鑑權與API許可權控制在微服務架構中的設計與實現(四)
引言: 本文系《認證鑑權與API許可權控制在微服務架構中的設計與實現》系列的完結篇,前面三篇已經將認證鑑權與API許可權控制的流程和主要細節講解完。本文比較長,對這個系列進行收尾,主要內容包括對授權和鑑權流程之外的endpoint以及Spring Security過濾器部分踩坑的經歷。歡迎閱讀本系列
認證鑑權與API許可權控制在微服務架構中的設計與實現(三)
引言: 本文系《認證鑑權與API許可權控制在微服務架構中的設計與實現》系列的第三篇,本文重點講解token以及API級別的鑑權。本文對涉及到的大部分程式碼進行了分析,歡迎訂閱本系列文章。 1. 前文回顧 在開始講解這一篇文章之前,先對之前兩篇文章進行回憶下。在第一篇 認證鑑權與AP
Linux核心設計與實現(1)--核心開發的特點
1. 核心程式設計時既不能訪問C庫也不能訪問標準的C標頭檔案 其中的原因有很多種。其一,C標準庫的很多函式實現都是基於核心實現的,這核心編譯的時候都還沒有核心,所以就不存在這些函式,這個就是先有雞還是先有蛋這個悖論。其二,其主主要的的
中小型園區網路的設計與實現 (二)
寫論文第二天 想要用心去寫一篇論文,首先要讀懂論文的要求 根據論文指導找出詳細的思路(論文的基本要求) 思路:①中小型區域網,500-1000臺計算機組成的一個網路。 ②網路型別是“園區網”,包括企業網、校園網等多種形式。園區網有一定的地理分佈範圍,不要簡單的一個辦
中小型園區網路的設計與實現 (一)
在職本科臨近畢業,論文是躲不掉的。 謹此來記錄畢業論文的完成過程。 論文大綱 部分雖然已經交上去很多日了。但是個人覺得有必要寫到第一篇裡,以示論文過程的完整。 先聊一下寫論文大綱的思路。 第一,首先論文是需要有專案背景的,就像做一件事情要有個目的。說仔細點就是某項工作需要交
演算法設計與分析(六)(上週第五週的寫錯標題,這才是真正的第六週)
Merge k Sorted Lists 題目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example:
lua設計與實現(二)資料型別
lua中的資料型別 //lua.h /* ** basic types */ #define LUA_TNONE (-1) #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERD
OpenStack設計與實現(四)訊息匯流排(AMQP)
在西方有一句諺語,叫做“Don’t Reinvent the Wheel!”。直譯過來就是不要在重新發明輪子了。也就是說我們應該避免做一些重複性的工作,如果一個東西別人已經做過了,那麼我們拿來直接用就行了,沒有必要重新制作,這一點在軟體開發裡尤為突出。所以在Op
OpenStack設計與實現(五)RESTful API和WSGI
在上一篇部落格中我們提到過,OpenStack每個專案內部的服務程序之間是通過訊息匯流排來通訊的,而在各個專案之間則是通過RESTful API來進行通訊的,在這一篇部落格中,我們就來詳細的討論一下OpenStack各個專案之間的通訊。 一、什麼是RESTfu
OpenStack設計與實現(一)虛擬化
雲端計算的一個核心思想就是在伺服器端提供集中的物理計算資源,這些計算資源可以被分解成更小的單位去獨立地服務於不同的使用者,也就是在共享物理資源的同時,為每個使用者提供隔離、安全、可信的虛擬工作環境,
【棋牌遊戲】JAVA伺服器設計與開發(一)
####開篇語 大概在16年時候,新型房卡模式開啟棋牌遊戲新里程,整個棋牌行業迅速改變模式,出現近兩三年激烈的競爭景象,據統計全國大大小小棋牌遊戲公司,專職棋牌公司近兩萬多家,這都不算後起大大小小遊戲公司加緊棋牌研發行列。新型棋牌模式有一個很明顯的特點,那就是地
自動升級系統OAUS的設計與實現(續) (附最新原始碼)
private void button1_Click(object sender, EventArgs e) { int changedCount = 0; int addedCount = 0; List<FileUnit&g
自動升級系統的設計與實現(原始碼)
對於PC桌面應用程式而言,自動升級功能往往是必不可少的。而自動升級可以作為一個獨立的C/S系統來開發,這樣,就可以在不同的桌面應用中進行復用。基於的檔案傳送功能,我實現了一個可直接複用的自動升級系統OAUS,現在將其分享給大家。這篇文章將著重介紹OAUS的相關背景、使用方法,至於詳細的實現細節,大家可