Как стать автором
Обновить

Mongoose + Redis. Автоматизация кэширования за 5 минут

Время на прочтение4 мин
Количество просмотров4.3K
  1. Mongoose представляет специальную ODM-библиотеку (Object Data Modelling) для работы с MongoDB, которая позволяет сопоставлять объекты классов и документы коллекций из базы данных. 

  2. Redis (Remote Dictionary Server)- это быстрое хранилище данных типа «ключ‑значение» в памяти, активно используемое в разработке с целью повышения производительности сервисов

  3. В рамках данного гайда мы рассмотрим связку Mongoose + Redis и посмотрим, как обеспечить максимально удобное взаимодействие между ними

Шаг 1. Установка пакетов

yarn add redis mongoose

Шаг 2. Конфигурация Redis.

const redisUrl = process.env.REDIS_CACHE_URL
const client = redis.createClient(redisUrl)
client.get = util.promisify(client.get)

Шаг 3. Формирование ключа

Одна из важных задач кэширования - составление ключа, под которым кэшировать данные. В контексте mongoose мы можем очень эффективно использовать свойства и методы прототипа Query, которые позволяют получить основную структуру запроса:

  1. mongooseCollection.name  - наименование коллекции

  2. getQuery - возвращает список фильтров запроса ( например, where)

  3. op - наименование операции (например, find)

  4. options - опции запроса ( например, limit

const key = JSON.stringify(
  {
    ...this.getQuery(),
    collection: this.mongooseCollection.name,
    op: this.op,
    options: this.options
  }
)

Шаг 4. Основная логика

Теперь, определив паттерн формирования ключей и установив соединение с Redis, можно перейти к имплементации основной логики кэширования:

  1. Пытаемся получить данные по ключу

  2. Если удалось, то возвращаем десериализованные данные

  3. Если же данные еще не были закэшированы, то выполняем запрос в базу данных

  4. Кэшируем полученные данные 

  5. Возвращаем результат

const cacheValue = await client.get(key)
if ( cacheValue ) return JSON.parse(cacheValue)

const result = await exec.apply(this, arguments)
if ( result ) {
  client.set(key, JSON.stringify(result))
}

return result

Шаг 5. Собираем все вместе 

Последним шагом, чтобы собрать весь функционал вместе, будет переопределение метода exec, чтобы кэширование применялось «из коробки»: 

module.exports =
  {
    applyMongooseCache() {

      const redisUrl = process.env.REDIS_CACHE_URL
      const client = redis.createClient(redisUrl)
      client.get = util.promisify(client.get)
      const exec = mongoose.Query.prototype.exec

      mongoose.Query.prototype.exec = async function () {

        const key = JSON.stringify(
          {
            ...this.getQuery(),
            collection: this.mongooseCollection.name,
            op: this.op,
            options: this.options
          }
        )

        const cacheValue = await client.get(key)
        if ( cacheValue ) return JSON.parse(cacheValue)

        const result = await exec.apply(this, arguments)

        if ( result ) {
          client.set(key, JSON.stringify(result))
        }

        return result
      }
    },
  }

Теперь остается только вызвать функцию applyMongooseCache  при старте Вашего приложения. 

Шаг 6. Docker-compose для локального запуска сервисов

Для тестирования данного функционала нам нужны два сервиса:

  1. MongoDB 

  2. Redis

  3. Mongo Express - система администрирования MongoDB

  4. Redis admin - система администрирования Redis

version: '3'
services:
  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: root
    ports:
      - 27017:27017

  mongo-express:
    image: mongo-express:0.54
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: root
    depends_on:
      - mongo

  redis:
    image: redis
    ports:
      - 6379:6379

  redis-admin:
    image: erikdubbelboer/phpredisadmin
    ports:
      - 8085:80
    depends_on:
      - redis
    environment:
      REDIS_1_HOST: redis
      REDIS_1_NAME: redis
      REDIS_1_PORT: 6379

Используя данную базовую конфигурацию, Вы сможете получить к сервисам локальный доступ на 27017(mongo) и  6379 (Redis) портах.

Соответственно, системы администрирования будут доступны на 8081 ( mongo-express) и 8085 (Redis admin) портах. 

Ссылка на репозиторий: https://github.com/IAlexanderI1994/mongoose-redis

Благодарю Вас за прочтение. Буду рад Вашим вопросам и комментариям. 

Теги:
Хабы:
Всего голосов 5: ↑1 и ↓4-3
Комментарии4

Публикации

Истории

Работа

Ближайшие события