如何建立有效的快取

3,936 views

Published on

由論壇系統為範例,如何實做快取系統。

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,936
On SlideShare
0
From Embeds
0
Number of Embeds
971
Actions
Shares
0
Downloads
8
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

如何建立有效的快取

  1. 1. 如何建立有效的快取
  2. 2. Who am I <ul>Ricky 是我 <li>http://ricky.ez2.us/
  3. 3. [email_address]
  4. 4. http://www.plurk.com/rickysu </li></ul>
  5. 5. 系統隨著時間資料越來越多
  6. 6. 資料庫越跑越慢
  7. 7. 到了某天再起不能
  8. 8. 怎麼辦 ?
  9. 9. 放乖乖
  10. 10. 解決方法 <ul><li>買台更強壯的機器。 很貴,而且老闆通常拿不出 $$ 。
  11. 11. 改用MySQL Replication。 得先改寫程式讓 sql 讀寫分離, 而且不易維護。 只有解決分流的問題,慢的查詢還是一樣慢。
  12. 12. 改用 NoSQL DB 取代 MySQL 。 只能說心臟很大顆,除非有強力後盾,否則別輕易嘗試。 </li></ul>
  13. 13. 難道沒有其他方法 ?
  14. 14. 建立 Cache 吧
  15. 15. Cache必須滿足以下幾個條件 <ul><li>快。 Cache 系統必須非常快,不然就失去意義了。
  16. 16. 是可有可無的。 在 Cache 失效的情況下,系統還是能正常運作。
  17. 17. Cache 必須易於擴展。 當 Cache 儲存空間滿了,可以透過增加 Server 的方式平行擴展。 </li></ul>
  18. 18. 快取的儲存媒體 <ul><li>Memcached http://memcached.org/
  19. 19. Redis http://redis.io/
  20. 20. TokyoTyrant http://fallabs.com/tokyotyrant/ </li></ul>
  21. 21. 讀取資料 是否存在快取中 傳回資料 由DB中取得資料 寫回快取
  22. 22. 寫入資料 刪除快取 回寫DB
  23. 23. 人生最厲害的就是這個 But
  24. 24. Key Value DB 在不知道 Key 的情況下如何刪除資料 !
  25. 25. 情境模擬 <ul>使用者修改了一篇文章,得同步刪除相關的文章快取。 <li>刪除全部文章的快取。
  26. 26. 刪除分類文章的快取。
  27. 27. 刪除某天發表的文章快取。 </li></ul>
  28. 28. 天阿,這得先統計出一堆 Key ,才能刪除快取。
  29. 29. 幫資料加上 Tag 吧
  30. 30. Ricky 的所有文章的第 2 頁分頁內容快取 key Article:ricky:All/Page:2/RowsPerPage:10 Value 快取內容 Tag Article:ricky:All -> 時間 (2011/10/03 13:10:43) 建立快取資料 Global Tag Article:ricky:All Key Tag:Article:ricky:All Value 2011/10/03 13:10:43 如果Global Tag 不存在時建立
  31. 31. 刪除快取 <ul><li>更新文章時刪除Global Tag $Memcache->delete('Tag:Article:ricky:All'); </li></ul>
  32. 32. 讀取資料 Ricky 的所有文章的第 2 頁分頁內容快取 key Article:ricky:All/Page:2/RowsPerPage:10 Value 快取內容 Tag Article:ricky:All -> 時間 (2011/10/03 13:10:43) Global Tag Article:ricky:All Key Tag:Article:ricky:All Value Not Exist 比對Tag的更新時間
  33. 33. 讀取快取 依序取出Tag 比對Global Tag 更新時間 快取失效 是否還有其他Tag 回傳快取資料
  34. 34. 原理是如此 Zend_Cache 已經實做 Tag 不要再做輪子了
  35. 35. 實際案例 討論區的快取建立
  36. 36. 資料結構 <ul><li>Board 討論版
  37. 37. Topic 討論主題
  38. 38. Message 文章內容 </li></ul>
  39. 39. 將查詢介面統一 別讓 SQL 四散各地
  40. 40. 取得討論版的主題列表 <ul><li>Method: FindTopicsFromBoard Input: $BoardID , $Page , $RowsPerPage Return: $Topics
  41. 41. Key: FindTopicsFromBoard/BoardID: $BoardID /Page: $Pag e/RowsPerPage: $RowsPerPage
  42. 42. Tag: Tag:BoardTopics/BoardID: $BoardID </li></ul>
  43. 43. Example Code static public function FindTopicsFromBoard ( $BoardID , $Pages , $RowsPerPage ){ if( $Topics = $Cache -> get ( ''FindTopicsFromBoard/BoardID: $BoardID /Page: $Page /RowsPerPage: $RowsPerPage '' )){ reutrn $Topics ; } return self:: rebuildFindTopicsFromBoard ( $BoardID , $Pages , $RowsPerPage ); } static public function rebuildFindTopicsFromBoard ( $BoardID , $Pages , $RowsPerPage ){ // do db query $Cache->set( ''FindTopicsFromBoard/BoardID: $BoardID /Page: $Page /RowsPerPage: $RowsPerPage '' , $Topics , //Data array( ''Tag:BoardTopics/BoardID: $BoardID '' //Tag ) ); return $Topics ; }
  44. 44. 取得某個主題的訊息串 <ul><li>Method: FindMessagesFromTopic Input: $TopicID , $Page , $RowsPerPage Return: $Messages
  45. 45. Key: FindMessagesFromTopic/TopicID: $TopicID /Page: $Pag e/RowsPerPage: $RowsPerPage
  46. 46. Tag: Tag:TopicMessages/TopicID: $TopicID if $Page is LastPage Tag:TopicMessages/TopicID: $TopicID /LastPage </li></ul>
  47. 47. 發表新主題 <ul><li>DB動作 topics insert new row message insert new row
  48. 48. 刪除對應的Tag 更新討論版 Tag:BoardTopics/BoardID: $BoardID </li></ul>
  49. 49. 回覆主題 <ul><li>DB動作 message insert new row
  50. 50. 刪除對應的Tag 更新討論版 Tag:BoardTopics/BoardID: $BoardID 更新訊息串 Tag:TopicMessages/TopicID: $TopicID /LastPage </li></ul>
  51. 51. 編輯或刪除訊息 <ul><li>DB動作 update or delete message row
  52. 52. 刪除對應的Tag 更新訊息串 Tag:TopicMessages/TopicID: $TopicID </li></ul>
  53. 53. 刪除整個討論串 <ul><li>DB動作 delete topic row delete all message rows about topic
  54. 54. 刪除對應的Tag 更新討論版 Tag:BoardTopics/BoardID: $BoardID 更新訊息串 Tag:TopicMessages/TopicID: $TopicID </li></ul>
  55. 55. 善用 Key Value DB 的特性 透過多次的查尋取代 join
  56. 56. 情境模擬 連結到第一篇文章 主題發布者 分頁
  57. 57. 使用SQL查詢解決 <ul><li>在主題列表中需要統計文章回覆數量,以及最後更新時間,甚至是分頁。
  58. 58. 解決方法 1. 在取得文章頁表時join message table,取得 回覆文章數量,以及最後更新的時間,和 最新回覆的使用者。 2.在topic table中建立快取欄位。當訊息回覆 時同步更新到topic table。 </li></ul>
  59. 59. 使用快取解決 <ul><li>FindTopicsFromBoard 只回傳Topic ids。
  60. 60. 透過FindMessagesFromTopic取得每個Topic的詳細統計資料。 $Page=1取得第一頁,順便建立快取。 $Page=LastPage 取得最後一頁,也順便建立快取。
  61. 61. 主題發起人=>第一頁的第一篇文章
  62. 62. 最後回覆=> 最後一頁的最後一篇文章
  63. 63. 文章回覆數 => 由最後一頁的頁數就可以推算出來。 </li></ul>
  64. 64. 使用快取解決的好處 <ul><li>更新資料時只需刪除對應的Tag。
  65. 65. 減少寫入DB時必須同步更新快取欄位的問題。
  66. 66. 如果搭配template快取,效果更佳。 </li></ul>
  67. 67. 導入快取前資料庫請先正規化
  68. 68. 如果遇到寫入頻繁的欄位怎麼辦
  69. 69. 利用延遲寫入的方式來解決 <ul><li>在DB中建立一筆延遲寫入Log。
  70. 70. 將資料寫回快取中。
  71. 71. 每隔一段時間由Log中找出延遲寫入的紀錄,回寫DB,並刪除快取。 </li></ul>
  72. 72. Thanks

×