走進緩存的世界(二) - 緩存設計


系列文章

 

如何設計緩存

主要考慮三個問題:

  • 緩存哪些數據
  • 如何緩存
  • 如何保證數據一致性

緩存哪些數據

 系統優化時有一句話必須切記:“優化無止境”,所以如果緩存不是必須的,請果斷去掉,要知道越是業務上復雜的系統,對Cache的使用反而越簡單,因為對於一個復雜、多變、歷史悠久的系統,在Cache方面做過度設計會讓人深陷其中;緩存的數據越多,系統的維護成本就越高,所以找准需要緩存的點尤為重要。一般情況下,我們只會緩存給系統帶來巨大瓶頸的IO操作,在普通應用里尤其指由top SQL或者慢 SQL所帶來的DAO查詢;找准需要優化的sql,你可以找DBA幫忙。

如何緩存 

存儲介質的選擇: 你可以直接緩存在JVM內存里,也可以采用阿里雲專門的緩存服務器,如tair、memcache等;

DB、文件其實也可以做緩存,他們一般緩存復雜計算的中間結果,一般很少用到;如果你的緩存是存放在jvm本地,那么通常是用map實現,如果緩存數據更新比較頻繁且對數據正確性比較高,那么你需要考慮為其添加並發控制和失效策略。還有一點比較重要的就是,在集群環境下想要做到數據一致性比較困難,主動更新比較麻煩而且達不到其降低數據庫IO操作的效果,所以本地緩存適用場景一般是在讀訪問非常高,而寫操作極少,對數據一致性要求不是特別高的場景;如果采用專門的緩存服務器則避免了很多麻煩,阿里雲的緩存系統tair,是我們經常使用的緩存中間件,它提供了很好的並發控制和失效機制,另外還提供了不同存儲引擎可以供我們選擇,如mdb,rdb,ldb;普通的緩存可以選擇mdb和rdb,兩者分別有memcache和redis的影子,其響應時間和高QPS的表現都非常好,但沒有提供持久化,如果要確保數據不丟失可以采用ldb引擎存儲,它提供了對數據持久化的支持,相反犧牲了一點點性能。

數據一致性

緩存意味着同樣的數據可能有多份並存,如果你的代碼沒有考慮某種情況導致了兩份數據不一致就會有問題發生。解決方法很簡單,把你的業務邏輯、代碼觸發情況都考慮清楚,不要遺留沒有觸底的地方。

多處使用緩存會導致你的代碼邏輯變得異常復雜,這也是為何說在非必要的時候,建議你不要用緩存的原因。

緩存一致性協議就是為了解決數據一致性問題而發明的。緩存一致性協議有多種,大多數計算機設備使用的都屬於“窺探(snooping)”協議。

“窺探”的基本思想是,內存是共享資源,所有內存I/O傳輸都發生在一條共享的總線上,所有的處理器都能看到這條總線,所有處理器對內存的訪問請求都要經過仲裁(arbitrate):同一個指令周期中,只有一個處理器可以讀寫內存中的被緩存的數據。窺探協議的思想是,緩存不僅僅在做內存傳輸的時候才和總線打交道,而是不停地在窺探總線上發生的數據交換,跟蹤其他緩存在做什么。所以當一個緩存代表它所屬的處理器去讀寫內存時,其他處理器都會得到通知,以此來使自己的緩存保持同步。只要某個處理器執行寫操作,其他處理器馬上就知道這塊內存在它們自己的緩存中對應的段已經失效。

在直寫模式下,這是很直接的,因為寫操作一旦發生,它的效果馬上會被“公布”出去。但是如果混着回寫模式就有問題了。因為有可能在寫指令執行過后很久,數據才會被真正回寫到物理內存中。在這段時間內,其他處理器的緩存可能會去寫同一塊內存地址導致沖突。在回寫模型中,簡單把內存寫操作的信息廣播給其他處理器是不夠的,我們需要做的是,在修改本地緩存之前,就要告知其他處理器。

搞懂了細節,就找到了處理回寫模式這個問題的最簡單方案。當處理器想寫某個緩存段時,如果它沒有獨占權,它必須先發送一條“我要獨占權”的請求給總線,這會通知其他處理器,把它們擁有的同一緩存段的拷貝失效(如果它們有的話)。只有在獲得獨占權后,處理器才能開始修改數據——並且此時,這個處理器知道,這個緩存段只有一份拷貝,在我自己的緩存里,這樣一來就可以巧妙地避免了沖突。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM