Caching 可以有效的改善讀取的時間、降低 Server or DB 的負擔。

常見的快取方式有:

  1. Client Cache
  2. CDN
  3. Web Server Cache
  4. Application Cache
  5. Database Cache

常見的 Client Cache 有 OS cache, browser cache 之類的,可以把一些 static files 儲存在本機端,不需要每次都跟 Server 拿。但是有時候這反而是種麻煩,當我們要更新這些檔案的時候,local cache 會讓用戶覺得沒有更新,如果不想讓 browser caching,可以使用 Header 的 Cache-Control 。

CDN 可以有效的降低對 web server static files 的請求,而且 CDN 會根據使用者的地區來分配同一個區域的機器,可以有效的減少使用者的等待時間,不過CDN 也有 cache invalidation 問題,通常 CDN Provider 都有機制可以解決這個問題,像是設定 expire time 或是提供 api 可以直接強制 refresh。

Web Server Cache 有 Reverse proxy 或是像 varnish 這種專門用來提供 caching 的服務,跟 Client, CDN 不同的是,Web Server Cache 連動態的 request 都可以做 caching,降低對 application layer or DB 的負擔。

Application Cache 最有名的就是 Memcached & Redis ,他們都是 In-Memory Cache,提供了非常高效率且彈性的服務。

Database Cache 本身也有提供 cache,這會跟不同的 DBMS 與設定有關,舉例來說,如果在短時間內使用了相同的 select query ,會發現第二次的時間會明顯地比第一次的短,這代表 DB 沒有真的去執行 query 而選擇使用了 cache。

關於 Cache updating

There are only two hard things in Computer Science: cache invalidation and naming things. Phil Karlton

這一段話指出要讓 cache 失效跟想變數的名稱一樣困難。要怎麼更新 cache 的資料或是判斷某一個資料已經無效,把它從 cache 中移除,是一件不容易的事,無效的 cache 我認為跟 Eventual Consistency 是不同的問題,雖然都是讀取到非最新的資料,但是 Eventual Consistency 在很短的時間內就會恢復正常,而 cache 如果沒有好的更新機制,就一直都是一樣的狀態。

以下有幾個模式可以幫助思考這個問題。

Cache aside

https://i.imgur.com/WwfeBMl.jpg

application 會先向 cache 詢問是否有這一筆資料,如果沒有就轉向 database 索取,當拿到資料之後再寫入 cache,再把結果返回給使用者。Cache aside 其實就是一種 lazy loading 的機制,一般來說我們在思考怎麼使用 cache 的時候,經常會用到的就是 Cache aside ,不過會有幾個缺點:

  1. 如果資料不在 cache 中,就會比較慢,比直接從 db 拿資料還要慢
  2. db 中資料被更新了, cache 中的資料就會是無效的,通常必須要設定 TTL 來避免資料失效
  3. cache 的節點中斷(Failed),就會回到第一點的問題,所有的資料都必須重新建立 cache

Write through

https://i.imgur.com/ANbDIIH.jpg

application 把 cache 當作主要的儲存,由 cache 負責把資料同步到DB(synchronous)。

write through 因為要把資料同步寫入 db ,所以 create, update 的操作表現會比較慢,但是讀取很快,而且資料也不會有過時的問題,一般來說大家都習慣寫入的操作會多花一點時間(跟讀取比)所以也不會有太大的問題。

缺點:

  1. 如果節點 failed ,要重新啟用新的 cache 時,資料就會全部都不見了
  2. 大多數的資料寫入之後,其實都不太會被讀取,所以會有很多的 cache data 是浪費的,可以透過設定 TTL 來降低這個問題的影響。

Write behind

https://i.imgur.com/ct2bHvK.jpg

write behind 跟 write through 很接近,差別在於寫入 db 的時候,使用了 queue 做非同步的處理,改善了寫入的等待時間。

缺點:

  1. 因為是非同步的,所以如果節點 failed ,資料還沒寫入 DB 就全部遺失了
  2. 比起 cache aside or write through 是比較複雜的,要考慮的地方也比較多

小結

使用 cache 可以有效的降低使用者的等待時間以及 Server, Database 的負擔,但是如何維持資料的一致性則是一個困難的問題,沒有一個好的 cache invalidation 機制,讓使用者總是拿到過期、無效的資料,還不如不要用 cache,畢竟晚一點拿到資料跟拿到不正確的資料相比,好像就沒這麼嚴重了。