不曉得大家有沒有遇過一種狀況:當某些資料的快取失效時,需要重新建立,但建立快取需要花費很長的時間;這時如果程式需要讀取這些快取時,就會有一段空窗期。

那麼要如何解決這種問題呢?我想方法應該有很多種,但我個人認為比較容易實作且有效率的方式就是: Content Swap 。

簡單來說, Content Swap 就是「當內容準備好後,就切換過去」,不過前提是我們得先有兩個一模一樣的容器。

使用者一開始只會看到其中一個容器的內容,而當第二個容器的內容有改變時,我們就讓使用者切換到第二個容器上頭;而第一個容器就再重新拿來裝填新的內容,以此類推,讓使用者不會感受到我們在改變容器內容時的延遲。

當然 Content Swap 並不是只適用在程式開發的領域裡,它是一種通用的模式;在硬體、軟體,甚至是生活等方面, Content Swap 模式都可以派上用場。

以下整理一些在我個人的程式開發生涯裡,所遇過使用 Content Swap 的場合供大家參考。

註:因為在程式領域混得不專精,所以 Content Swap 這個名詞是我自己胡編的;如果大家有看過類似的技巧而有更好的命名,還請大家不吝指正。

用於系統升級

雖然通常我們不太喜歡升級正在上線的系統,但有時候因為安全上的考量卻不得不升級它。

所以一般我們會再準備好另一台機器,先行在上面安裝並設定好新的系統;接著再利用切換 IP 的方式 (或是其他能切換機器的方法) ,來達成系統升級的目的。
把時間拉長來看,這樣的系統升級方式就是一種 Content Swap 了。

用於遊戲畫面繪製

以前在我學習開發 DirectX 遊戲時,曾經遇到 sprite 在畫面上閃爍的問題。這是因為我必須在 sprite 移動時,重新建立遮罩來將它繪製到新位置上。

後來我學到了一個新的技巧,叫做 Double Buffer 。它主要的概念是在程式中準備兩個繪圖緩衝區,然後先在第一個緩衝區上面繪製所有的物件並輸出;接著當程式計算完所有物件的互動與位置後,在第二個緩衝區重新繪製所有的物件,然後再把輸出的指標指向第二個緩衝區來呈現畫面。如此一來,用切換緩衝區的方式,就可以得到不閃爍的畫面了。

用於資料庫排程

有時候我們會需要取得資料庫中的某些資訊,但這些資訊的處理通常要耗費很多時間,即時取得的話就會拖垮系統效能;因此在這些資訊的即時性不是很重要時,我們通常會透過排程來將處理好的資訊放在一個暫時的快取資料表中。

不過就如文章一開頭所描述的狀況,我們在快取過期後而需要重建時,在這段時間裡會讓系統無法取得快取,導致系統必須即時去取得資訊,徒然耗費許多時間。

解決的方法很簡單,我們可以準備好兩個一模一樣的快取資料表,只有名稱上不同,例如 table_1 及 table_2 。

假設目前系統讀取的是 table_1 中的內容,而快取即將過期時,系統並不是直接清除 table_1 現有的內容,而是把新的快取先建立到 table_2 中 (當然要先清除 table_2 中的內容) ;然後系統再將設定改為讀取 table_2 ,直到下次快取過期時,再對 table_1 重複相同的動作。

而這樣的動作,也不一定只侷限在兩個資料表上,也可以是兩台主機來執行。這樣一來,在前端的使用者就完全無感了。

小結

相信大家知道這個概念後,一定會發現自己平常已經有使用這個模式處理問題了;因為我們很希望讓使用者無感於我們在內容切換上的延遲,這也是這個模式最主要的目的。

而這個模式最大的特色就是以空間換取時間,因此在資源有限的場合,可能就沒辦法使用了。

希望以我個人淺薄的心得,能讓大家對這個模式有更多不一樣的想法。