Caching 可以有效的改善讀取的時間、降低 Server or DB 的負擔。
常見的快取方式有:
- Client Cache
- CDN
- Web Server Cache
- Application Cache
- 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
application 會先向 cache 詢問是否有這一筆資料,如果沒有就轉向 database 索取,當拿到資料之後再寫入 cache,再把結果返回給使用者。Cache aside 其實就是一種 lazy loading 的機制,一般來說我們在思考怎麼使用 cache 的時候,經常會用到的就是 Cache aside ,不過會有幾個缺點:
- 如果資料不在 cache 中,就會比較慢,比直接從 db 拿資料還要慢
- db 中資料被更新了, cache 中的資料就會是無效的,通常必須要設定 TTL 來避免資料失效
- cache 的節點中斷(Failed),就會回到第一點的問題,所有的資料都必須重新建立 cache
Write through
application 把 cache 當作主要的儲存,由 cache 負責把資料同步到DB(synchronous)。
write through 因為要把資料同步寫入 db ,所以 create, update 的操作表現會比較慢,但是讀取很快,而且資料也不會有過時的問題,一般來說大家都習慣寫入的操作會多花一點時間(跟讀取比)所以也不會有太大的問題。
缺點:
- 如果節點 failed ,要重新啟用新的 cache 時,資料就會全部都不見了
- 大多數的資料寫入之後,其實都不太會被讀取,所以會有很多的 cache data 是浪費的,可以透過設定 TTL 來降低這個問題的影響。
Write behind
write behind 跟 write through 很接近,差別在於寫入 db 的時候,使用了 queue 做非同步的處理,改善了寫入的等待時間。
缺點:
- 因為是非同步的,所以如果節點 failed ,資料還沒寫入 DB 就全部遺失了
- 比起 cache aside or write through 是比較複雜的,要考慮的地方也比較多
小結
使用 cache 可以有效的降低使用者的等待時間以及 Server, Database 的負擔,但是如何維持資料的一致性則是一個困難的問題,沒有一個好的 cache invalidation 機制,讓使用者總是拿到過期、無效的資料,還不如不要用 cache,畢竟晚一點拿到資料跟拿到不正確的資料相比,好像就沒這麼嚴重了。