天天看點

一種關于緩存資料何時更新的解決思路為什麼寫?我的做法利弊

為什麼寫?

和大家一樣,我有每天逛逛部落格園的習慣,今天在部落格園看到了“一隻攻城獅”寫的《

初遇 Asp.net MVC 資料庫依賴緩存那些事兒

》。該朋友利用.Net的SqlCacheDependency緩存依賴,解決了緩存資料何時更新的問題。

但是該思路具有一定的局限性,如:要利用資料庫的存儲過程,來通知用戶端更新緩存,這就離不開微軟的Sql Server那套體制,如果利用别的資料庫,恐怕就沒有那麼好實作了。且存儲過程需要在資料庫中執行,不利于将業務向服務程式轉移。

程式員比較忌諱造輪子,相信程式員寫部落格也是如此,是以,我還是想站在巨人的肩膀上,借用“一隻攻城獅”在《

》寫的背景,來引出我想說的内容,如果“一隻攻城獅”覺得有何不妥之處,請聯系我做下架處理。

--------------------------------------------------------------引用開始-----------------------------------------------

最近做一個非常簡單的功能,就是使用ajax請求的方式從服務端請求一段下拉表的資料。

  以前也有做過這個功能,隻不過這次做這個功能的時候冒出了一個想法:

  我請求的這段資料它是一段相對比較固定的資料,也就是說它不怎麼改變,也許幾個月才會改變一次。由于這種資料的變化周期很長,是以以前做這種功能的時候,會使用緩存進行優化,可以直接從緩存中讀取資料,避免每一次接收了ajax請求後都要向資料庫要資料,減少伺服器與資料庫之間的互動,減輕資料庫伺服器的壓力。但是問題來了,資料的變化周期再長終究是要變化的,當資料庫中的資料變化的時候你就要對舊有的緩存内容進行移除(remove)操作。

                 .......................{中間省略XXX字,中間作者大緻講訴了設定了緩存定期過期}.................................

  緩存定期過期有一個壞處:在還沒到達過期時間的這段時間裡,請求的資料依然是原來的緩存中資料,如果資料庫資料在這期間進行了更新,那麼緩存資料和資料庫中的資料并不一緻。

  其中設定的絕對過期時間點要根據實際的資料重新整理的可容忍度來進行設定,而恰好在我的這個應用場景中的可容忍度最不能把握,它要求的是 當資料庫中的資料改變以後,緩存中對應的資料在下一次請求結束後一定要馬上跟着改變,當然你也可以把過期時間盡可能的調小,調到一秒。當然,這樣的話還是要頻繁的向資料庫進行請求,那不是背離了我們原本使用緩存優化的目的了嗎?

  是以現在的問題是:有沒有一種方法能讓資料庫和伺服器程式建立一種聯系,這種聯系好比是一種“心靈感應”,當資料庫表中的資料發生變化的時候,馬上就能讓伺服器中的對應的緩存項“感應”到這個變化,進而讓原來的緩存項失效呢?

--------------------------------------------------------------引用結束------------------------------------------

我的做法

  綜上所述,用戶端(或浏覽器)緩存資料的痛點在于,資料何時更新?如何讓用戶端知道,服務端資料變了?

  分四步走。

第一步,初次請求資料時

一種關于緩存資料何時更新的解決思路為什麼寫?我的做法利弊

用戶端在初次請求資料時,會把用戶端想要的資料連同資料的版本号(資料上次的更新時間)一起發送給用戶端,資料版本号時存在Redis資料庫中的,我們知道,Redis中的資料存儲在記憶體中且讀取資料比關系型資料庫快的不是一點點。

用戶端收到資料後,會把收到的資料和資料版本号緩存下來。

第二步,當資料庫資料更新時

一種關于緩存資料何時更新的解決思路為什麼寫?我的做法利弊

當資料庫資料更新時,服務端在更新關系型資料庫的同時會把Redis的資料版本号更新為目前時間。

第三步,用戶端用資料時:

一種關于緩存資料何時更新的解決思路為什麼寫?我的做法利弊

用戶端需要使用緩存資料時,會向服務端索要資料版本号(也就是資料上次的更新時間),如果該資料版本号與用戶端緩存的資料版本号一緻,那麼,用戶端緩存的資料時安全可用的,如果不一緻,那麼說明資料已經更新了,用戶端把新的版本号緩存下來并重新擷取。那麼,執行第四步。

第四步,重新擷取資料

一種關于緩存資料何時更新的解決思路為什麼寫?我的做法利弊

重新擷取資料時,就不用攜帶版本号了,用戶端在第三步時已經擷取并緩存下來了。

利弊

好處:

1.當請求的資料量交大但是變動又不頻繁時,用戶端與服務端不必頻繁地交換大型資料,隻需交換資料版本号即可。

2.資料版本号存儲在Redis資料庫中,不僅讀取速度快,而且資料量小,是以響應快,交換成本低。

3.該思路通用性強,适合任何類型的關系型資料庫與Nosql資料庫搭配使用。

弊端:

1.用戶端在每次使用資料前,都要與服務端進行一次通訊進行校驗資料版本号。

好與壞不是絕對的,适合的才是最好的,以上是我的解決思路,大家有不同觀點,歡迎留言讨論,也感謝“一隻攻城獅”提供讨論背景!