緩存的五種設計模式

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"利用緩存來加速系統已經成爲很常見的一種操作。這種方式有效率、簡單,而且成本也在可控的範圍內。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"說到緩存,通常會下意識的想到緩存是用來加速讀的,實際上,讀數據和寫數據都可以使用緩存。總的來說,緩存的使用模式可分成五種。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這五種方式就是從是讀緩存還是寫緩存的角度來進行劃分的。需要注意,這裏的緩存是廣義上的緩存,不僅僅指 Redis 這些常用作緩存的軟件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這些緩存模式並不是新技術,而是伴隨在計算機體系結構演進中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Cache-Aside"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果從緩存中找到數據,稱之爲"},{"type":"text","marks":[{"type":"strong"}],"text":"命中緩存"},{"type":"text","text":",如果沒有找到數據,稱爲之"},{"type":"text","marks":[{"type":"strong"}],"text":"未命中緩存"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Cache-Aside 應該是使用最爲廣泛的一種模式。應用直接去緩存中找數據,命中緩存則直接返回,如果未命中緩存,則需要先去數據庫中查詢數據,並將查詢到的數據存儲到緩存中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b1/b1c76278c84a0e436ba17ad741f03663.png","alt":null,"title":"圖1: Cache-Aside","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種方式會讓緩存中的數據與數據庫中的數據不一致,所以一般會給緩存中的數據設置過期時間(TTL),數據過期之後就去數據庫中取最新的數據。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在數據更新時,應該和下文的 Write-Around 配合,而不要使用 Write-Through。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Read-Through Cache"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Read-Through 的方式與 Cache-Aside 的方式很接近,區別在於,Cache-Aside 是通過應用程序來更新緩存中的數據,而 Read-Through 則是通過緩存自身來更新數據,也就是說應用和數據庫之間不直接進行連接。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/84/84ba2d2293705b4d174905e2d5fff9ca.png","alt":null,"title":"圖2: Read-Through","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種模式也存在緩存中數據與數據庫中數據不一致的情況,但是相比於給緩存設置過期時間,它只需要和 Write-Through 搭配使用就可以解決這個問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Write-Through Cache"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面說了兩種以讀爲主的緩存。Write-Through 會先將數據寫入到緩存中,然後由緩存將數據存入到數據庫中。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/88/88b0d1f81fe31706fd1e10904e48853f.png","alt":null,"title":"圖3: Write-Through","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Write-Through 與 Read-Through 相結合可以很好的解決緩存和數據庫中數據不一致的問題,Write-Through 每次都會先更新緩存中的數據,所以每次讀到的數據也是最新的。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/79/791c0af28a1558d1be88365c866a045a.png","alt":null,"title":"圖4: Read-Through + Write-Through","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Write-Around"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Write-Around 其實本身並不會用到緩存,而是會直接寫入到數據庫中。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ba/ba4fe57ee28d1d20e6683e4f916d2778.png","alt":null,"title":"圖5: Write-Around","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Cache-Aside 爲什麼要配合 Write-Around 而不能和 Write-Through 一起使用呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲 Write-Through 會先更新緩存,而如果這時剛好有另外一個線程將數據庫中舊的數據讀取出來將緩存中新的數據覆蓋,就會造成數據錯誤,而使用 Write-Around 就不會出現這個問題。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/61/61f83718b7d7526d9c680449fa972b7c.png","alt":null,"title":"圖6: Cache-Aside + Write-Around","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Write-Around 在某些場景下與 Read-Through 搭配使用也很有用,對於某些只需要寫一次並且讀多次的情況,比如聊天信息的寫入和獲取。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Write-Back"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Write-Back 算是 Write-Through 的改良版,Write-Through 每寫一次緩存,緩存就會寫一次數據庫,而 Write-Back 則是寫了多次緩存後纔會寫一次數據庫,可以大大減輕服務器的壓力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這一模式在 MySQL 等數據庫產品中使用很廣泛。"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/05/051a355fb64939245d3062f63ae247d8.png","alt":null,"title":"圖7:Write-Back","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然, Write-Back 也不是沒有缺點,如果緩存出現了問題,那麼緩存中這部分沒有持久化的數據就會丟失。 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"文 / Rayjun"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[1] https://codeahoy.com/2017/08/11/caching-strategies-and-how-to-choose-the-right-one/"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[2] https://coolshell.cn/articles/17416.html"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章