Расскажите о распространенных сценариях использования Redis в проекте.

Node.js Redis

я писалстроительные лесаredisСуществует довольно много сценариев использования, поэтому подведем итоги его распространенных сценариев использования.

тайник

> set User:1:name shanyue EX 100 NX
OK
> get User:1:name
"shanyue"

кэшredisОдин из сценариев использования с самым высоким коэффициентом появления, только с использованиемset/getможет быть достигнуто, но есть некоторые моменты, которые следует учитывать

  • Как лучше настроить кеширование
  • Как поддерживать согласованность кеша с исходными данными
  • Как решить проблему прокачки кеша и поломки кеша

сеанс: логин пользователя и проверочный код

> set 5d27e60e6fb9a07f03576687 '{"id": 10086, role: "ADMIN"}' EX 7200
OK
> get 5d27e60e6fb9a07f03576687
"{\"id\": 10086, role: \"ADMIN\"}"

Это также очень распространенный сценарий, но по сравнению с сеансами с отслеживанием состояния JWT также может быть рассмотрен, каждый со своими преимуществами и недостатками.

очередь сообщений

> lpush UserEmailQueue 1 2 3 4
lpop UserEmailQueue
> rpop UserEmailQueue
1
> rpop UserEmailQueue
2

МожетredisОчередь считается распределенной очередью, так как очереди сообщений, производители данных подключаются, данные потребителей выходят на другом конце: (lpush/rpop, rpush/lpop). Но есть и некоторые недостатки, и эти недостатки могут быть фатальными, но для некоторых это не имеет значения, потеряны несколько сцен сообщений, которые все же можно считать

  1. Без подтверждения сообщения могут быть потеряны
  2. это нужно сделатьredisпостоянная конфигурация

фильтр (дупфильтр)

> sadd UrlSet http://1
(integer) 1
> sadd UrlSet http://2
(integer) 1
> sadd UrlSet http://2
(integer) 0
> smembers UrlSet
1) "http://1"
2) "http://2"

scrapy-redisВ качестве распределенного краулера он используетredisизSetЭта структура данных обрабатывается для URL-адреса, по которому будет осуществляться обход.

# https://github.com/rmax/scrapy-redis/blob/master/src/scrapy_redis/dupefilter.py
def request_seen(self, request):
    """Returns True if request was already seen.
    Parameters
    ----------
    request : scrapy.http.Request
    Returns
    -------
    bool
    """
    fp = self.request_fingerprint(request)
    added = self.server.sadd(self.key, fp)
    return added == 0

Но когдаurlКогда слишком много, будет проблема чрезмерного использования памяти

Распределенная блокировка

set Lock:User:10086 06be97fc-f258-4202-b60b-8d5412dd5605 EX 60 NX

# 释放锁,一段 LUA 脚本
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

Это простейший автономный распределенный замок со следующими пунктами

  • EXУказывает, что срок действия блокировки истечет и будет снят
  • NXГарантированная атомарность
  • При разблокировке сравнивайте UUID, сгенерированный соответствующим ресурсом, чтобы избежать случайной разблокировки.

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

Rate Limit

Текущее ограничение означает, что в единицу времени разрешено проходить только определенное количество запросов.Есть два ключевых параметра.

  • окно, единица времени
  • max, максимальное количество запросов

Наиболее распространенным сценарием: SMS-код подтверждения может отправлять только одну минуту дважды

FUNCTION LIMIT_API_CALL(ip):
current = GET(ip)
IF current != NULL AND current > 10 THEN
    ERROR "too many requests per second"
ELSE
    value = INCR(ip)
    IF value == 1 THEN
        EXPIRE(ip,1)
    END
    PERFORM_API_CALL()
END

Вы можете использовать счетчики, чтобы ограничить поток запросов API, но обратите внимание на несколько моментов.

  1. Удвоение количества запросов в экстремальных случаях во время плавного скользящего окна
  2. Состояние гонки

В настоящее время посредством программирования, согласноTTL keyдля дальнейшего ограничения или использованияLISTЧтобы сохранить отметку времени каждого запроса для фильтрации в реальном времени. Ниже приведеныnodeпонял одинRate Limter. Справочный исходный кодnode-rate-limiter-flexible

this.client
  .multi()
  .set(rlKey, 0, 'EX', secDuration, 'NX')
  .incrby(rlKey, points)
  .pttl(rlKey)
  .exec((err, res) => {
    if (err) {
      return reject(err);
    }

    return resolve(res);
  })

if (res.consumedPoints > this.points) {
  // ...
} else if (this.execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {
  // ...
  setTimeout(resolve, delay, res);
} else {
  resolve(res);
}

Распределенные веб-сокеты

через редисPUB/SUBдля связи между серверами веб-сокетов. Вы можете обратиться к следующим пунктам


Добро пожаловать, чтобы обратить внимание на мой общедоступный номерГорная Луна Путешествие, записывайте сюда мой технический рост, добро пожаловать в общение

欢迎关注公众号山月行,在这里记录我的技术成长,欢迎交流