Redis
 sql >> база данни >  >> NoSQL >> Redis

Как да деактивирате Redis кеширането по време на изпълнение, ако връзката с redis е неуспешна

Нека да сварим това малко. Вашето приложение използва кеширане (реализирано с Redis). Ако връзката Redis е остаряла/затворена или по друг начин, тогава искате приложението да заобиколи кеширането и (вероятно) да отиде директно към основното хранилище на данни (например RDBMS). Логиката на услугата на приложението може да изглежда подобно на...

@Service
class CustomerService ... {

    @Autowired
    private CustomerRepository customerRepo;

    protected CustomerRepository getCustomerRepo() {
        Assert.notNull(customerRepo, "The CustomerRepository was not initialized!");
        return customerRepo;
    }

    @Cacheable(value = "Customers")
    public Customer getCustomer(Long customerId) {
        return getCustomerRepo().load(customerId);
    }
    ...
}

Всичко, което има значение в абстракцията за кеширане на ядрото на Spring, за да се установи „пропускане“ на кеша, е, че върнатата стойност е нула. Като такава, Spring Caching Infrastructure ще продължи с извикването на действителния метод на услугата (т.е. getCustomer). Имайте предвид, че при връщането на извикването getCustomerRepo().load(customerId) трябва да се справите и със случая, когато инфраструктурата за кеширане на Spring се опитва да кешира стойността.

В духа на просто , ние ще направим без AOP, но трябва да можете да постигнете това и с AOP (по ваш избор).

Всичко, от което (трябва) се нуждаете, е „персонализиран“ RedisCacheManager, разширяващ реализацията на SDR CacheManager, нещо като...

package example;

import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCacheManager;
...

class MyCustomRedisCacheManager extends RedisCacheManager {

    public MyCustomerRedisCacheManager(RedisTemplate redisTemplate) {
        super(redisTemplate);
    }

    @Override
    public Cache getCache(String name) {
        return new RedisCacheWrapper(super.getCache(name));
    }


    protected static class RedisCacheWrapper implements Cache {

        private final Cache delegate;

        public RedisCacheWrapper(Cache redisCache) {
            Assert.notNull(redisCache, "'delegate' must not be null");
            this.delegate = redisCache;
        }

        @Override
        public Cache.ValueWrapper get(Object key) {
            try {
              delegate.get(key);
            }
            catch (Exception e) {
                return handleErrors(e);
            }
        }

        @Override
        public void put(Object key, Object value) {
            try {
                delegate.put(key, value);
            }
            catch (Exception e) {
                handleErrors(e);
            }
        }

        // implement clear(), evict(key), get(key, type), getName(), getNativeCache(), putIfAbsent(key, value) accordingly (delegating to the delegate).

        protected <T> T handleErrors(Exception e) throws Exception {
            if (e instanceof <some RedisConnection Exception type>) {
                // log the connection problem
                return null;
            }
            else if (<something different>) { // act appropriately }
            ...
            else {
                throw e;
            }
        }
    }
}

Така че, ако Redis не е наличен, може би най-доброто, което можете да направите, е да регистрирате проблема и да продължите, за да оставите извикването на услугата. Ясно е, че това ще попречи на производителността, но поне ще повиши осведомеността, че съществува проблем. Ясно е, че това може да бъде обвързано с по-стабилна система за уведомяване, но е груб пример за възможностите. Важното е, че вашата услуга остава достъпна, докато другите услуги (напр. Redis), от които зависи услугата на приложението, може да са се провалили.

В тази реализация (в сравнение с моето предишно обяснение) избрах да делегирам на основната, действителна реализация на RedisCache, за да позволя на изключението да се случи, след което знаейки добре, че съществува проблем с Redis и за да можете да се справите с изключението по подходящ начин. Въпреки това, ако сте сигурни, че изключението е свързано с проблем с връзката при проверка, можете да върнете "null", за да позволите на Spring Caching Infrastructure да продължи, сякаш е "пропускане" на кеша (т.е. лоша връзка с Redis ==пропускане на кеш, в този случай).

Знам, че нещо подобно трябва да помогне на проблема ви, тъй като създадох подобен прототип на "персонализирана" реализация на CacheManager за GemFire ​​и един от клиентите на Pivotal. В този конкретен UC „пропускането“ на кеша трябваше да бъде задействано от „неактуална версия“ на обекта на домейна на приложението, където производството имаше смесица от по-нови и по-стари клиенти на приложения, свързващи се с GemFire ​​чрез абстракцията за кеширане на Spring. Обектните полета на домейна на приложението биха се променили в по-новите версии на приложението например.

Както и да е, надявам се това да ви помогне или да ви даде повече идеи.

Наздраве!



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Разбиране на кеширането на Laravel:Cache фасада и Redis

  2. Използване на jedis как да пишете в конкретен слот/възел в редис клъстер

  3. Да използвате множество DB с един Redis Lua скрипт?

  4. Twisted:защо предаването на отложено обратно извикване към отложена нишка прави нишката блокирана изведнъж?

  5. Как да получите DIFF на сортиран набор