我構建了一個自定義數據實體存儲庫,其工廠根據類型(例如絕對或滑動過期)定義了保留策略。該策略還將緩存類型指定爲httpcontext請求,會話或應用程序。 MemoryCache由所有3種緩存類型中的緩存代理維護。無論如何,我有一個數據實體服務綁定到存儲庫,它負責爲我們的主數據實體進行加載和保存。這個想法是你使用實體庫,並不需要關心實體是否緩存或從它的數據源(在這種情況下,數據庫)中檢索。使用MemoryCache的數據存儲庫
一個明顯的假設是您需要同步加載/保存事件,因爲您需要在從其數據源加載實體之前保存緩存實體。
所以我在今天生產的調查數據完整性問題... :)
我今天看了就不可能有實體之間的良好的長期差距從的MemoryCache和CacheItemRemovedCallback事件觸發(默認20被移除秒)。我在加載和保存數據操作時遇到的簡單鎖定不足。此外,CacheItemRemovedCallback在HttpContext之外的自己的上下文中使事情變得有趣。這意味着我需要使回調函數成爲靜態的,因爲我可能會將事件置於實例中。
因此,一旦我意識到存在差距的可能性,即我的數據實體不再存在於緩存中,但可能未保存到其數據源中,可能會解釋5000中的3個損壞訂單。從主要數據實體的政策20分鐘滑動到期之後執行工作很容易。這意味着,如果它們碰巧在相同的時刻提交,則會出現加載(通過請求上下文)和保存(通過緩存過期回調)之間的有趣競爭條件。
簡單的鎖定是擲骰子,會保存或加載勝利?顯然,我們需要在數據源(db)的下一次加載之前進行保存。理想情況下,當一個項目從緩存到期時,它會原子地寫入其數據源。當實體從緩存中消失但過期回調尚未觸發時,加載操作可能會滑入。在這種情況下,實體將無法在緩存中找到,因此將默認從數據源加載。但是,由於保存操作可能尚未開始,導致數據完整性損壞,並可能會破壞您現在保存的緩存數據。
爲了實現同步,我需要一個命名的信號鎖,因此我決定使用EventWaitHandle。爲每個用戶創建一個命名鎖,它是< 5000.這允許Load等待來自過期事件的信號,該事件保存實體(其線程存在於其自己的上下文之外的HttpContext中)。因此,在保存完成後,很容易獲取現有的名稱句柄併發信號通知Load以繼續。
我也有一個冗餘,它超時並通過保存操作記錄每個10秒的塊。正如我所說的,默認的意思是在從MemoryCache被移除的實體和它意識到它觸發事件並進而保存實體之間的20秒之間。
謝謝任何通過我所有的追隨我的漫步者。鑑於同步要求的性質是EventWaitHandle鎖定最佳解決方案?
也許使用MemoryCache這種方式不是一個很好的設計。 –
把一些糟糕的設計稱爲超過一定的複雜程度總是很誘人。但是,我會爭辯說,跨線程處理緩存並非不合理,也不需要同步所述線程是不合理的。關於MemoryCache,我懷疑它是值得嘗試創造一個更好的。我很樂意聽到相反的論點,或者選擇,或者更好的同步機制。 – codinglifestyle
也許[redis](https://redis.io/topics/introduction)可以幫助你。 –