2016-11-22 35 views
2

在文檔它說使用MemoryCacheHandle與RedisCacheBackplane但沒有RedisCacheHandle

/// The cache manager must have at least one cache handle configured with <see cref="CacheHandleConfiguration.IsBackplaneSource"/> set to <c>true</c>. 
    /// Usually this is the redis cache handle, if configured. It should be the distributed and bottom most cache handle. 

我知道如何與RedisCacheHandle做到這一點,因爲它是作爲例子給出的CacheManager的網站

var cache = CacheFactory.Build<int>("myCache", settings => 
{ 
    settings 
    .WithSystemRuntimeCacheHandle("inProcessCache") 
    .And 
    .WithRedisConfiguration("redis", config => 
    { 
     config.WithAllowAdmin() 
      .WithDatabase(0) 
      .WithEndpoint("localhost", 6379); 
    }) 
    .WithMaxRetries(1000) 
    .WithRetryTimeout(100) 
    .WithRedisBackplane("redis") 
    .WithRedisCacheHandle("redis", true); 
}); 

的問題是我不想使用Redis作爲緩存資源;我只是想通過Redis Pub/Sub機制的力量製作分佈式緩存。根據我通過代碼進行的調試,通過使用Redis Backplane功能,我可以將消息發送到Redis並從Redis接收消息。那麼爲什麼不使用RedisCacheHandle而是使用SystemRuntimeCacheHandle呢?

所以,我的期望是用下面的緩存配置

var cache = CacheFactory.Build<int>("myCache", settings => 
{ 
    settings 
    .WithSystemRuntimeCacheHandle("inProcessCache") 
    .And 
    .WithRedisConfiguration("redis", config => 
    { 
     config.WithAllowAdmin() 
      .WithDatabase(0) 
      .WithEndpoint("localhost", 6379); 
    }) 
    .WithMaxRetries(1000) 
    .WithRetryTimeout(100) 
    .WithRedisBackplane("redis") 
    .WithSystemRuntimeCacheHandle("inProcessCache", true); 
}); 

的全成執行,但它不工作。你能告訴我一個解決方案嗎?我究竟做錯了什麼?或者,儘管它已經是寫在文檔中的

...通常這是Redis的緩存手柄...

是有什麼辦法可以使用緩存同步功能,而不RedisCacheHandle?

https://github.com/MichaCo/CacheManager/issues/111

回答

0

我想你「也不是工作」你的意思是,其他緩存沒有得到同步,如如果我從cacheA中刪除一個密鑰,它不會從cacheB中刪除? 是的,這是目前預期的行爲。

背板旨在與只有一種狀態的進程外緩存配合使用。 使用系統運行時緩存的兩個緩存實例,在proc緩存中有兩個完全斷開連接。

通常情況下,如果您有Redis圖層,並且從緩存實例A中刪除密鑰,則該項目將從Redis圖層中刪除。該消息被髮送到同一緩存的其他實例,並將從其他任何緩存層(除redis之外)(標記爲背板源的緩存層)中刪除該密鑰。這意味着,我們預計背板源已經同步。

現在如果你有一個進程內緩存作爲背板源。這是行不通的,因爲兩個實例總是不同步。

讓我們看看下面這個例子:

var cacheConfig = ConfigurationBuilder.BuildConfiguration(settings => 
{ 
    settings 
    .WithSystemRuntimeCacheHandle("inProcessCache") 
    .And 
    .WithRedisConfiguration("redis", config => 
    { 
     config.WithAllowAdmin() 
      .WithDatabase(0) 
      .WithEndpoint("localhost", 6379); 
    }) 
    .WithMaxRetries(1000) 
    .WithRetryTimeout(100) 
    .WithRedisBackplane("redis") 
    .WithSystemRuntimeCacheHandle("inProcessCache", true); 
}); 

var cacheA = new BaseCacheManager<string>(cacheConfig); 
var cacheB = new BaseCacheManager<string>(cacheConfig); 

cacheB.Backplane.Removed += (obj, args) => 
{ 
    Console.WriteLine(args.Key + " removed from B."); 
}; 

cacheA.Add("key", "value"); 

var result = cacheB.Get("key"); 
Console.WriteLine("Result should be null:" + result); 

cacheB.Add("key", "value"); 
result = cacheB.Get("key"); 
Console.WriteLine("Result should not be null:" + result); 

// triggers backplane remove event 
cacheA.Remove("key"); 

// lets give redis some time send messages 
Thread.Sleep(100); 

result = cacheB.Get("key"); 
Console.WriteLine("Result should be null again but isn't:" + result); 

Console.ReadKey(); 

如果遇到這種情況,可以看到背板事件實際上觸發,但因爲只有在進程內緩存背板源,該鍵不被刪除。 這就是爲什麼最後,你仍然可以把鑰匙還給你。

正如我所說,這是目前的預期行爲。

雖然您可以通過監聽這些事件來實現自定義邏輯。 (在下一個版本中事件會稍微變化,目前有一些錯誤和不一致)。

此外,不要期望背板將緩存值轉移到其他實例。這不會發生。 CacheManager只發送關鍵事件,而不是數據,因爲數據通常由進程外緩存處理。 意思是說,如果你只有底板的進程緩存,在cacheA中添加一個項目,不會將項目複製到cacheB!儘管您可能會在緩存B上獲取change事件。

我希望是有道理的;)

+0

我尊重您的建議,並發表我的意見,而不是github。 其實這種模式迫使我使用「高速緩存背板源」。那麼,這意味着這個來源是所有其他來源的「來源」:這意味着它是所有其他緩存句柄中的「主要來源」。這就是爲什麼Redis緩存句柄可以很好地用作背板源:因爲它是位於地址的單個緩存。另一方面,MemoryCacheHandle不能處理這個工作。爲什麼? 這是因爲MemoryCacheHandle每次都會創建新的MemoryCache。請檢查MemoryCacheHandle類的構造函數。 – rebulanyum

+0

所以@michac,在另一臺計算機上考慮兩個MemoryCacheHandle。它們不能通過Redis pub/sub同步嗎?一個是主人,另一個是奴隸。那會很酷。作爲一個架構,它也應該是可能的。但它看起來像你的圖書館不支持這種方式。 – rebulanyum

+0

現在聽起來更像是一個功能請求。讓我們把這張貼到gihtub上,並附上鍊接。我仍然不能100%確定你同步的意思是什麼?其實複製新的項目,或只是刪除已被刪除和那些?複製數據並模仿分佈式緩存是100%不是要走的路,因爲這就是爲什麼像Redis這樣的東西存在;) – MichaC

相關問題