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

Манипулатор на грешка в Spring Redis

Имах същия проблем. Разработвам някои услуги за данни спрямо база данни, като използвам Redis като кеш хранилище чрез анотации за Spring Caching. Ако Redis сървърът стане недостъпен, искам услугите да продължат да работят като некеширани, вместо да хвърлят изключения.

Първо опитах персонализиран CacheErrorHandler, механизъм, предоставен от Spring. Не проработи съвсем, защото обработва само RuntimeExceptions и все пак позволява на неща като java.net.ConnectException да раздуват нещата.

В крайна сметка това, което направих, е да разширя RedisTemplate, заменяйки няколко метода execute(), така че да регистрират предупреждения, вместо да разпространяват изключения. Изглежда като хак и може да съм заменил твърде малко методи execute() или твърде много, но работи като чар във всичките ми тестови случаи.

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

По-долу е източникът. Чувствайте се свободни да го използвате. Надявам се да помогне.

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;


/**
 * An extension of RedisTemplate that logs exceptions instead of letting them propagate.
 * If the Redis server is unavailable, cache operations are always a "miss" and data is fetched from the database.
 */
public class LoggingRedisTemplate<K, V> extends RedisTemplate<K, V> {

    private static final Logger logger = LoggerFactory.getLogger(LoggingRedisTemplate.class);


    @Override
    public <T> T execute(final RedisCallback<T> action, final boolean exposeConnection, final boolean pipeline) {
        try {
            return super.execute(action, exposeConnection, pipeline);
        }
        catch(final Throwable t) {
            logger.warn("Error executing cache operation: {}", t.getMessage());
            return null;
        }
    }


    @Override
    public <T> T execute(final RedisScript<T> script, final List<K> keys, final Object... args) {
        try {
            return super.execute(script, keys, args);
        }
        catch(final Throwable t) {
            logger.warn("Error executing cache operation: {}", t.getMessage());
            return null;
        }
    }


    @Override
    public <T> T execute(final RedisScript<T> script, final RedisSerializer<?> argsSerializer, final RedisSerializer<T> resultSerializer, final List<K> keys, final Object... args) {
        try {
            return super.execute(script, argsSerializer, resultSerializer, keys, args);
        }
        catch(final Throwable t) {
            logger.warn("Error executing cache operation: {}", t.getMessage());
            return null;
        }
    }


    @Override
    public <T> T execute(final SessionCallback<T> session) {
        try {
            return super.execute(session);
        }
        catch(final Throwable t) {
            logger.warn("Error executing cache operation: {}", t.getMessage());
            return null;
        }
    }
}


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как да направите основно ГЛЕДВАНЕ със StackExchange.Redis

  2. Има ли нещо като Redis DB, но не ограничено с размера на RAM?

  3. MISCONF Redis е конфигуриран да запазва RDB моментни снимки

  4. Най-добра практика за надграждане на Redis със Sentinels?

  5. Как Redis ще разбере дали трябва да върне кеширани данни или свежи данни от DB