Недавнее собеседование при приеме на работу я начал как обычно. Человек с другой стороны стола начал задавать мне ряд вопросов о моих проектах и ​​моих навыках. В конце концов разговор привел к масштабированию, на которое я обычно не готов ответить. В конце концов я начал рассказывать о том, что я знал о масштабировании и различных технологиях кэширования, таких как Redis. Именно об этом он и надеялся поговорить, но это все еще было за пределами рулевой рубки. После интервью я решил поближе познакомиться с Redis и попытался внедрить его в новостное приложение, над которым работал.

Redis действительно фантастический. Хотя его можно использовать как базу данных, я использовал его как систему кэширования. Вместо того, чтобы извлекать информацию из моей базы данных каждый раз, когда пользователь что-то хочет, я могу кэшировать элементы, которые, как я знаю, будут пользоваться большим спросом для быстрого и легкого доступа для чтения и записи, устраняя необходимость в повторяющихся функциях.

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

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

Лента новостей была немного сложнее, так как она постоянно обновляется. Я не мог просто сделать один большой звонок, преобразовать ответ в строку и сохранить его, чтобы можно было вызывать большой объем информации снова и снова. Если бы я это сделал, мне пришлось бы все время устанавливать и сбрасывать эту большую часть информации.

Еще одна трудность в кэшировании главных новостей заключается в том, что я не могу контролировать этот аспект. Это обновление информации на моей стороне приложения, его информация, которая обновляется в API. Если бы я хотел кешировать информацию о пользователе, например, что пользователь публикует, я мог бы создать структуру списка повторных показов и просто добавлять эту активность каждый раз, когда пользователь что-то делает. Но это не так.

Чтобы установить Redis в проекте node, нам нужно выполнить некоторые настройки.

Для начала вам необходимо установить Redis на свой компьютер, что вы можете сделать здесь: https://redis.io/download.

Затем перейдите в свой проект и установите, нам нужно установить пакет Redis.

npm i redis --save

После того, как все будет установлено, вам нужно загрузить сервер Redis. Перейдите к своему терминалу и введите redis-server. Должно появиться всплывающее изображение, подобное следующему

Это означает, что Redis теперь работает локально на порту 6379.

Внутри Node мы хотим создать наш клиент. И это так же просто, как импортировать Redis и создать клиент в папке конфигурации или в основной папке приложения.

import redis from 'redis'
let client = redis.createClient();
export {
   client
}

Метод createClient использует порт Redis по умолчанию.

Как только это будет сделано, мы готовы к буги-вуги.

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

import { client } from '../config/config'
export const callSources = async (req, res) => {
// below I'm calling my sources
let response = await newsapi.sources({
    language: 'en',
    country: 'us',
    category: "general"
  })
// I think give a response with those sources
res.status(200).send(answer)
// I then stringify those objects and store them with a key pointing to them
let cachedSources = JSON.stringify(answer)
  client.set('sources', cachedSources)
};

Причина, по которой я привожу строки, заключается в том, что Redis не поддерживает объекты JSON. У них есть модуль под названием ReJSON, который вы можете использовать для этого. Я изучил его, но, похоже, он не совсем подходит для моего текущего проекта. Он позволяет вам манипулировать объектом Redis, как если бы вы делали это с объектом JSON, или аналогично их собственному набору хеш-данных.

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

src/routes/sourceRoutes.js
const source = require('../controller/sourceController');
const sourcePath = express();
import { sourceCache } from '../redis'
sourcePath.route('/')
    .get(sourceCache, source.callSources);

src/redis/index.js
export function sourceCache(req, res, next){
  client.get("sources", (err, data) => {
    if(err || !data){
      next()
    } else if(data){
      res.status(200).send(data)
    }
  })
}

Эта функция проверяет, есть ли кеш, и если есть, она возвращает его и вообще обходит необходимость делать этот вызов.

Для новостной ленты мне пришлось немного поумничать. В итоге я вызвал API, когда пользователь впервые запрашивает его, и кэшировал ответ в списке Redis.

export const callArticles = async (req, res) => {
  let articles = await newsapi.topHeadlines({
    language: 'en',
    country: 'us',
    category: "general",
  })

  // res.status(200).send(response)
//  Redis Caching
  response.map(article => {
    let stringed = JSON.stringify(article);
    client.lpush('topStories', stringed)
  })
}

В итоге я добавил в конец функцию, которая сохраняла 5 первых статей из ответа, поскольку они были самыми последними.

for(let i = 0; i < 5; i++){
    let story = response[i].title
    client.sadd('mostRecent', story)
  }

Затем я сделал бы частичный вызов API для первых 5 элементов. С ними я бы сравнил его с самым последним набором, который я создал. Если разница была меньше четырех, я просто добавлял эти элементы в список лучших историй, обновлял свой последний набор и продолжал. Если их было больше 5, я перекэшировал весь список.

Код немного хакерский и, скорее всего, будет немного изменен, поэтому я не буду публиковать его здесь. Если вы хотите увидеть исходный код, вы можете найти его в этом репозитории https://github.com/aebenw/NewsRoom-node-api.

Redis — отличный способ оптимизировать API, и у него так много аспектов. На самом деле я только что дал голое вступление, но многое еще предстоит открыть.