2016-11-22 1 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. Так почему бы не использовать 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); 
}); 

Но это не работает. Не могли бы вы показать мне решение? Что я делаю не так? Или, Eventhough это написано в документации, как

... Обычно это 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 отправляет только ключевые события, а не данные, потому что данные обрабатываются кэшем вне процесса. Смысл, если у вас есть в кэше в proc только с объединительной платой, добавление элемента в cacheA, НЕ будет копировать элемент в cacheB! Однако вы можете получить событие change для ключа на cacheB.

Я надеюсь, что это имеет смысл;)

+0

Я уважаю ваше предложение и размещаю комментарии здесь, а не github. На самом деле шаблон заставляет меня использовать «Source Backplane Source». Ну, это означает, что этот источник является «Источником» всех остальных: это означает «Главный источник» среди всех остальных ручек кэша. Вот почему Redis Cache Handle отлично работает в качестве источника объединительной платы: поскольку это один кэш, расположенный по адресу : адрес. С другой стороны, MemoryCacheHandle не может справиться с этим заданием. Зачем? Это потому, что MemoryCacheHandle создает новый MemoryCache каждый раз. Проверьте конструктор класса MemoryCacheHandle. – rebulanyum

+0

Итак, @michac, рассмотрите 2 MemoryCacheHandle каждый на другом компьютере. Не удается ли синхронизировать их с помощью Redis pub/sub? Один - мастер, а другой - раб. Было бы здорово. И в качестве архитектуры это тоже должно быть возможно. Но похоже, что ваша библиотека не поддерживает этот способ. – rebulanyum

+0

Теперь это больше похоже на запрос функции. Давайте опубликуем это на gihtub со ссылкой на это. Я все еще не уверен на 100%, что вы обычно подразумеваете при синхронизации? На самом деле копировать новые предметы или просто удалять те, которые были удалены и т. Д.? Копировать данные и имитировать распределенный кеш составляет 100%, а не способ, потому что именно поэтому такие вещи, как Redis, существуют;) – MichaC

Смежные вопросы