Рубрики
Без рубрики

Простой сервис кэширования с Redis

Как создать службу кэширования с помощью Redis и Java. Помеченный nosql, redis, микросервисами, java.

Одним из наиболее распространенных вариантов использования Redis является использование базы данных в качестве уровня кэширования ваших данных, но Redis может сделать гораздо больше (Я опубликую новые статьи позже) !

В этой статье вы узнаете, используя простой сервис, как кэшировать результат при некоторых вызовах REST API, чтобы ускорить доступ к данным, а также сократить количество обращений к внешним службам.

В этом примере я использую приложение “Redis Movie Database”, приложение на основе микросервиса, которое я создал для демонстрации и объяснения различных функций Redis и Redis Enterprise.

Вы можете увидеть службу кэширования в действии в этом видео:

Обзор архитектуры

Приложение IMDb использует сторонний API, предоставляемый ” Imdb API “, для получения оценок фильма с использованием его идентификатора IMDb. Интерфейсное приложение вызывает службу /кэширования/рейтинга/ , чтобы получить информацию о рейтинге из IMDB.

Эта служба выполняет следующие действия:

  1. Проверьте, уже ли данные рейтинга кэшированы, извлеките их из кэша
  2. Если информация не кэшируется, система вызывает OMDB API с соответствующим ключом и идентификатором фильма
  3. Результат кэшируется в Redis со временем жизни 120 секунд
  4. Оценки возвращаются клиенту.

Предпосылки

  • Redis 5.x или более поздней версии.
  • Java 8 или более поздняя версия
  • Apache Maven 3.6
  • Мерзавец

Реализация

В демонстрационном проекте микросервиса вы можете найти службу кэширования в проекте ниже:

Приложение Spring Boot предоставляет конечную точку REST RestStatusController.java со следующими ключевыми функциями:

  • /api/1.0/кэширование/конфигурация/omdb_api : чтобы сохранить ключ API OMDb в Redis.
  • /api/1.0/кэширование/рейтинги/{id} : для получения информации о рейтинге IMDB.

Структура данных

Служба кэширования довольно проста и использует два набора ключей:

  • ms:config : это хэш Redis, который будет использоваться для хранения всей глобальной конфигурации; для службы кэширования запись OMDB_API_KEY будет содержать ключ API OMDb.
  • ms:кэш:ws:* : одна запись для каждого фильма, просмотренного пользователем, где идентификатор фильма IMDb заменяет * . Хэш содержит рейтинги, и каждый из сайтов с рейтингом фильмов является ключом в хэше (“Internet Movie Database”, “Rotten Tomatoes”, “Metacritic”), а значением является сам рейтинг.

Код

Реализация уровня кэширования проста и находится в классе ниже:

Получение подключения Redis

В этом проекте я не использовал Redis/Spring integration по выбору , я использую только веб-функции Spring injection и Spring Boot.

  • метод after Construct() создает JedisPool из конфигурации Spring
  • затем каждый раз, когда требуется подключение, приложение вызывает Jedis.getResource() , чтобы получить соединение из пула.

Настройка и получение ключа API OMDb

Как вы видели ранее, ключ API OMDb хранится в хэше, связанном с ключом Redis ms: конфигурация .

  • Метод saveOMDBAPIKey используется для сохранения конфигурации с помощью вызова set |/.
    jedis = jedisPool.getResource();
    jedis.hset(KEY_CONFIG, OMDB_API_KEY, key);
    omdbAPIKEY = key;
  • строка 1: получить соединение из пула
  • строка 2: установите ключ в хэше *(как вы можете видеть, приложение использует статические переменные ( KEY_CONFIG и OMDB_API_KEY )
  • строка 3: ключ, полученный в качестве параметра метода, устанавливается на член класса ключ API omdb , чтобы избежать вызова хэша каждый раз.

Вызов OMDb API и кэширование (или нет) результата

Способ получайте оценки получает два параметра:

  • imdbId на IMDb я d
  • с Cache логическое значение для использования или нет Redis. Цель здесь состоит в том, чтобы показать в качестве демонстрации преимущества использования Redis.

Давайте теперь посмотрим на код:

 String restCallKey = KEY_PREFIX + imdbId;

        try (Jedis jedis = jedisPool.getResource()) {

            // Look in the map to see if the value has been cached
            if (withCache) {
                returnValue = jedis.hgetAll(restCallKey);
            }

            if (returnValue.isEmpty()) {
                returnValue.put("imdb_id", imdbId);
                CloseableHttpClient httpClient = HttpClientBuilder.create().build();
                HttpGet getRequest = new HttpGet(url);
                getRequest.addHeader("accept", "application/json");
                ResponseHandler responseHandler = new BasicResponseHandler();

                String WsCall = httpClient.execute(getRequest, responseHandler);

                Map map = jsonMapper.readValue(WsCall, Map.class);
                List> ratings = (List>) map.get("Ratings");

                Map ratingAsMap = new HashMap<>();
                for (Map it : ratings) {
                    ratingAsMap.put(it.get("Source"), it.get("Value"));
                }

                returnValue.putAll(ratingAsMap);

                jedis.hset(restCallKey, returnValue);
                jedis.expire(restCallKey, TTL);
            }

        } catch(HttpResponseException e){
            // Small hack to keep it simple
            returnValue.put("Metacritic", "

Error: OMDBAPI Key is invalid -- see services page

"); omdbAPIKEY = null; } catch (IOException e) { e.printStackTrace(); } } else { // Small hack to keep it simple returnValue.put("Metacritic", "

Error: OMDBAPI Key is not set, please configure it -- see services page

"); } long end = System.currentTimeMillis(); returnValue.put("elapsedTimeMs", Long.toString(end - start) ); return returnValue;

Итак, если вы внимательно посмотрите в код, вы увидите, что только несколько строк связаны с самим кэшем:

  • Строка 1, ключ создается из префикса и идентификатора IMDb.
  • Строка 3, приложение извлекает соединение из пула Jedis.
  • Строка 7, если кэш включен, подключение для получения значения из Redis возвращает значение.hgetAll(restCallKey)
  • Если значение присутствует в кэше, оно возвращается вызывающей стороне
  • Если возвращаемое значение пусто, необходимо вызвать службу IMDB REST (строки с 11 по 25)
  • Результат вызова веб-службы сохраняется в переменной возвращаемое значение и сохраняется в Redis со временем ожидания (TTL) 120 секунд (строки с 27 по 29)
  • Наконец, значение возвращается вызывающему абоненту (строка 47).

Довольно просто, не так ли?

Можно немного оптимизировать приложение/код с небольшими дополнениями:

  • Сделайте TTL настраиваемым, добавив новую запись в ms:config cache
  • Используйте конвейерную обработку для сокращения времени прохождения туда и обратно (RTT)

Запуск приложения

В проекте служба подключается к локальному экземпляру Redis на порту 6379 . Если вы хотите использовать другой экземпляр или настроить пароль/пользователя, вам необходимо отредактировать /redis-microservices-demo/caching-service/application.properties .

Клонирование и создание

> git clone https://github.com/tgrall/redis-microservices-demo.git

> cd redis-microservices-demo/caching-service

> mvn clean package

Запуск приложения

Приложение представляет собой приложение Spring Boot, для его запуска выполните следующую команду:

> mvn spring-boot:run

Затем вы должны сохранить свой ключ API OMDB в Redis, используя следующий вызов:

> curl -X POST http://localhost:8084/api/1.0/caching/configuration/omdb_api\?key\=[YOUR_KEY]

Теперь вы можете позвонить в сам сервис, чтобы получить рейтинги фильма “Военные игры”.

> curl -X GET http://localhost:8084/api/1.0/caching/ratings/tt0086567

Вызовите его несколько раз, и вы увидите, что первый вызов выполняется “медленно” (100 мс или более). Тогда последующие запросы будут выполняться намного быстрее, так как данные поступают из Redis. Через две минуты данные автоматически удаляются из кэша (истечение срока действия), и служба OMDB будет вызвана снова.

Вы также можете заставить службу не использовать кэш, используя следующий вызов:

> curl -X GET http://localhost:8084/api/1.0/caching/ratings/tt0086567?cache=0

Вывод

Шаблон, используемый здесь, называется “Cache-Aside”; и обычно его довольно легко реализовать. Интересно отметить, что многие библиотеки, такие как Spring, предоставляют встроенные функции для реализации таких кэшей.

Тем не менее, это не серебряная пуля, вам все равно нужно обратить внимание на следующие моменты, когда вы внедряете такую службу кэширования:

  • Загрузка кэша: в приведенном примере кэш заполняется при вызове службы. Этот подход с отложенной загрузкой превосходен, поскольку кэш заполняется только теми данными, которые используются приложением. Однако за первый вызов приходится платить более высокой задержкой, поэтому в вашем приложении вам может потребоваться загрузить данные при запуске, чтобы избежать промаха при попадании.
  • Аннулирование кэша и срок службы: При кэшировании данных важно учитывать стратегию аннулирования, когда и как я могу обновить данные в кэше, а также как долго данные будут оставаться в кэше. В приведенном выше примере все данные будут храниться в течение двух минут.

Итак, теперь вы готовы реализовать простой кэш и иметь постоянный быстрый доступ к данным вашего приложения независимо от серверной части.

Оригинал: “https://dev.to/tgrall/simple-caching-service-with-redis-1jbj”