和你們同樣,我有天天逛逛博客園的習慣,今天在博客園看到了「一隻攻城獅」寫的《初遇 Asp.net MVC 數據庫依賴緩存那些事兒》。該朋友利用.Net的SqlCacheDependency緩存依賴,解決了緩存數據什麼時候更新的問題。html
可是該思路具備必定的侷限性,如:要利用數據庫的存儲過程,來通知客戶端更新緩存,這就離不開微軟的Sql Server那套體制,若是利用別的數據庫,恐怕就沒有那麼好實現了。且存儲過程須要在數據庫中執行,不利於將業務向服務程序轉移。程序員
程序員比較忌諱造輪子,相信程序員寫博客也是如此,所以,我仍是想站在巨人的肩膀上,借用「一隻攻城獅」在《初遇 Asp.net MVC 數據庫依賴緩存那些事兒》寫的背景,來引出我想說的內容,若是「一隻攻城獅」以爲有何不妥之處,請聯繫我作下架處理。ajax
--------------------------------------------------------------引用開始-----------------------------------------------sql
最近作一個很是簡單的功能,就是使用ajax請求的方式從服務端請求一段下拉表的數據。數據庫
之前也有作過這個功能,只不過此次作這個功能的時候冒出了一個想法:瀏覽器
我請求的這段數據它是一段相對比較固定的數據,也就是說它不怎麼改變,也許幾個月纔會改變一次。因爲這種數據的變化週期很長,因此之前作這種功能的時候,會使用緩存進行優化,能夠直接從緩存中讀取數據,避免每一次接收了ajax請求後都要向數據庫要數據,減小服務器與數據庫之間的交互,減輕數據庫服務器的壓力。可是問題來了,數據的變化週期再長終究是要變化的,當數據庫中的數據變化的時候你就要對舊有的緩存內容進行移除(remove)操做。緩存
.......................{中間省略XXX字,中間做者大體講訴了設置了緩存按期過時}.................................安全
緩存按期過時有一個壞處:在還沒到達過時時間的這段時間裏,請求的數據依然是原來的緩存中數據,若是數據庫數據在這期間進行了更新,那麼緩存數據和數據庫中的數據並不一致。服務器
其中設置的絕對過時時間點要根據實際的數據刷新的可容忍度來進行設定,而剛好在個人這個應用場景中的可容忍度最不能把握,它要求的是 當數據庫中的數據改變之後,緩存中對應的數據在下一次請求結束後必定要立刻跟着改變,固然你也能夠把過時時間儘量的調小,調到一秒。固然,這樣的話仍是要頻繁的向數據庫進行請求,那不是背離了咱們本來使用緩存優化的目的了嗎?post
因此如今的問題是:有沒有一種方法能讓數據庫和服務器程序創建一種聯繫,這種聯繫比如是一種「心靈感應」,當數據庫表中的數據發生變化的時候,立刻就能讓服務器中的對應的緩存項「感應」到這個變化,從而讓原來的緩存項失效呢?
--------------------------------------------------------------引用結束------------------------------------------
綜上所述,客戶端(或瀏覽器)緩存數據的痛點在於,數據什麼時候更新?如何讓客戶端知道,服務端數據變了?
分四步走。
客戶端在初次請求數據時,會把客戶端想要的數據連同數據的版本號(數據上次的更新時間)一塊兒發送給客戶端,數據版本號時存在Redis數據庫中的,咱們知道,Redis中的數據存儲在內存中且讀取數據比關係型數據庫快的不是一點點。
客戶端收到數據後,會把收到的數據和數據版本號緩存下來。
當數據庫數據更新時,服務端在更新關係型數據庫的同時會把Redis的數據版本號更新爲當前時間。
客戶端須要使用緩存數據時,會向服務端索要數據版本號(也就是數據上次的更新時間),若是該數據版本號與客戶端緩存的數據版本號一致,那麼,客戶端緩存的數據時安全可用的,若是不一致,那麼說明數據已經更新了,客戶端把新的版本號緩存下來並從新獲取。那麼,執行第四步。
從新獲取數據時,就不用攜帶版本號了,客戶端在第三步時已經獲取並緩存下來了。
好處:
1.當請求的數據量交大可是變更又不頻繁時,客戶端與服務端沒必要頻繁地交換大型數據,只需交換數據版本號便可。
2.數據版本號存儲在Redis數據庫中,不只讀取速度快,並且數據量小,因此響應快,交換成本低。
3.該思路通用性強,適合任何類型的關係型數據庫與Nosql數據庫搭配使用。
弊端:
1.客戶端在每次使用數據前,都要與服務端進行一次通信進行校驗數據版本號。
好與壞不是絕對的,適合的纔是最好的,以上是個人解決思路,你們有不一樣觀點,歡迎留言討論,也感謝「一隻攻城獅」提供討論背景!