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

от автора

  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

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


ссылка на оригинал статьи https://habr.com/ru/articles/579036/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *