2013-03-11 107 views
0

請記住,示例我在這裏展示只是爲了儘可能明確,沒有任何實際實施或生產代碼說明問題。飼養緩存與後端

而且,我們假設如果有什麼被存儲或從後端返回,它會被緩存。我從代碼中省略的例子和發生的地方。

對於這個問題的範圍,我們還必須假設,MyType集合總是很小,相當靜態,當應用程序啓動時,它將從後端獲取一切,並重用緩存副本,直到應用程序關閉。這就是爲什麼GetCached(id)GetBackend(id)實際上來說是ListCachedListBackend的包裝。

假設我們有以下一種簡單的存儲庫:

public class MyRepository : IRepository<MyType> 
{ 
    public IEnumerable<MyType> GetAll() 
    { 
     // Will return cached items if present 
     return ListCached ?? ListBackend; 
    } 

    public MyType Get(int id) 
    { 
     return GetCached(id) ?? GetBackend(id); 
    } 


    private MyType GetBackend(int id) 
    { 
     return ListBackend.FirstOrDefault(type => type.Id == id); 
    } 

    private MyType GetCached(int id) 
    { 
     return ListCached.FirstOrDefault(type => type.Id == id); 
    } 

    protected IEnumerable<MyType> ListBackend 
    { 
     get { return Backend.GetAll<MyType>(); } 
     set { Backend.StoreAll<MyType>(value); } 
    } 

    public IEnumerable<MyType> ListCached 
    { 
     get { return Cache.GetAll<MyType>(); } 
     set { Cache.StoreAll<MyType>(value); } 
    } 

    public void Store(MyType value) 
    { 
     Backend.Store(value); 
    } 
} 

而這裏的挑戰:

class Program 
{ 
    static void Main(string[] args) 
    { 
     #region Handling Missing Objects in Cache 
     // We have a repository 
     var rep = new MyRepository(); 

     // Into which we put stuff (3 for the demo) 
     rep.Store(new MyType { Id = 1 }); 
     rep.Store(new MyType { Id = 2 }); 
     rep.Store(new MyType { Id = 3 }); 

     // And the repository, after this, returns 3 items 
     // The items are returned from cache 
     var count = rep.GetAll().Count(); // Returns 3 

     // However, somewhere else in the application, it happens so, 
     // for any reason, bug, programmer error, photon from sun hitting the cpu 
     // or tinfoil-hat left home in rush, 
     // that one item gets removed from the cache 
     Cache.Remove(new MyType { Id = 2 }); 

     // After which, only 2 items are returned from the repository 
     // since the cache exists, it won't even try to hit the database 
     count = rep.GetAll().Count(); 

     // Now count = 2, while WE know the backend has now 3 items 
     // how would the program detect it and get a fresh copy from backend? 
     #endregion 
    } 
} 

,你會在這種情況下怎麼辦?是否有模式可以幫助檢測情況並從後端獲取新鮮收集。最佳實踐是什麼?

回答

1

恕我直言,

1 - 如果不加之間在到數據庫中,那麼你可以保留一個計數器並填充它,當你啓動應用程序。

2-如果您可以將List更改爲Observable Collection,它會在更新時報告以便刪除某個項目時,您將收到通知,並且您可以檢查計數器,如果它不相同,您可以重新加載它。

3-如果無法使用觀察到的集合,那麼你可以使用CacheExpiray政策,在其中您可以模擬一個緩存一些時間後,將自動重新加載從源代碼的概念。

0

有可能一些可用的選項。

首先,使用過期的緩存。只是爲當前緩存設置特定的過期時間。如果時間已過,則刷新數據。然而,這種模式不能

if(cacheExpiry){ 
    cacheList = GetListFromDatabase(); 
} 

但是,如果你想確保獲得最新的數據,通常我用這個方法:

1,生成緩存時設置當前的時間戳。一些插圖:

DateTime lastCache = DateTime.Now 

然後在你的sql中,有一個最新修改日期時間(例如UPDATE_STAMP)的表。然後每次修改所需的緩存表時,將UPDATE_STAMP表中的記錄更新爲當前日期。例如:

Update MyTable set //your code here 
Update UPDATE_STAMP set DATE_TIME = GETDATE() 

然後每次你得到ListCached,比較最新的緩存時間與UPDATE_STAMP表記錄。例如:

public IEnumerable<MyType> ListCached 
{ 
    get { 
     DateTime latestModified = GetLatestModifiedDate(); 
     if(lastCache<latestModified) Cache = GetListFromDatabase(); 
     latestModified = DateTime.Now; 
     return Cache.GetAll<MyType>(); 
    } 
} 
+0

每次你需要得到緩存列表,你去數據庫檢查它是否同步,你不覺得它是以某種方式破壞緩存概念。 – TalentTuner 2013-03-11 08:17:38