Как работать с большим ключом Redis?

Всем привет, я Сяолинь.

Давайте поговорим сегодня о четырех вопросах о большом ключе Redis.

  • Что такое большой ключ Redis?
  • Какие проблемы могут вызвать большие ключи?
  • Как найти большой ключ?
  • Как удалить большой ключ?

Что такое большой ключ Redis?

Большой ключ означает не то, что значение ключа велико, а то, что значение, соответствующее ключу, велико.

Вообще говоря, следующие две ситуации называются большими ключами:

  • Значения типа String больше 10 КБ;
  • Количество элементов типа Hash, List, Set, ZSet превышает 5000;

Какие проблемы могут вызвать большие ключи?

Большой ключ принесет следующие четыре эффекта:

  • Время ожидания клиента истекло и он заблокирован . Так как Redis выполняет команды в однопоточном процессе, а для работы с большими ключами требуется время, Redis будет заблокирован.С точки зрения клиента ответа нет долгое время.
  • вызвать перегрузку сети . Каждый раз при получении большого ключа сетевой трафик относительно большой, если размер ключа 1 МБ и количество посещений в секунду 1000, то будет генерироваться 1000 МБ трафика в секунду, что катастрофично для сервер с обычной гигабитной сетевой картой.
  • Блокировать рабочие потоки . Если вы используете del для удаления большого ключа, рабочий поток будет заблокирован, чтобы не было возможности обрабатывать последующие команды.
  • Память распределена неравномерно . В модели кластера, когда фрагментация слота равномерна, будет перекос данных и запросов.Некоторые узлы Redis с большими ключами занимают много памяти, а количество запросов в секунду будет относительно большим.

Как найти большой ключ?

1. redis-cli --bigkeys для поиска больших ключей

Вы можете найти большие ключи с помощью команды redis-cli --bigkeys:

redis-cli -h 127.0.0.1 -p6379 -a "password" -- bigkeys

Меры предосторожности при использовании:

  • Лучше всего выбрать выполнение команды на ведомом узле. Потому что при выполнении на главном узле он заблокирует главный узел;
  • Если нет подчиненного узла, вы можете выбрать сканирование и запрос во время низкого пикового периода бизнес-нагрузки экземпляра Redis, чтобы не влиять на нормальную работу экземпляра; или вы можете использовать параметр -i для управления интервал сканирования, чтобы длительное сканирование не снижало производительность экземпляра Redis.

Недостатки этого метода:

  • Этот метод может возвращать только самый большой большой ключ каждого типа и не может получить большой ключ с наибольшим размером в первых N позициях;
  • Для типов коллекций этот метод подсчитывает только количество элементов коллекции, а не фактический объем занимаемой памяти. Однако большое количество элементов в коллекции не обязательно занимает большой объем памяти. Потому что возможно, что каждый элемент занимает небольшой объем памяти, в этом случае, даже если элементов много, общие накладные расходы памяти невелики;

2. Используйте команду SCAN, чтобы найти большой ключ

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

Для типа String вы можете напрямую использовать команду STRLEN, чтобы получить длину строки, то есть количество байтов занимаемой памяти.

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

  • Если средний размер элементов коллекции может быть известен на бизнес-уровне заранее, то можно использовать следующую команду, чтобы получить количество элементов коллекции, а затем умножить на средний размер элементов коллекции, так что объем памяти можно получить. Тип списка: LLENкоманда Тип хэша: HLENкоманда Тип набора: SCARDкоманда Тип сортированного набора: ZCARDкоманда
  • Если вы не можете заранее узнать размер элементов, записанных в коллекцию, вы можете использовать MEMORY USAGEкоманду (требуется Redis 4.0 и выше), чтобы запросить пространство памяти, занимаемое парой ключ-значение.

3. Используйте инструмент RdbTools, чтобы найти большой ключ

Используйте RdbTools, сторонний инструмент с открытым исходным кодом, для анализа файлов моментальных снимков Redis (RDB) и поиска большого ключа.

Например, следующая команда выводит ключи размером более 10 КБ в файл таблицы.

rdb dump.rdb -c memory --bytes 10240 -f redis.csv

Как удалить большой ключ?

Суть операции удаления заключается в освобождении памяти, занимаемой парой ключ-значение.Не стоит недооценивать процесс освобождения памяти.

Освобождение памяти — это только первый шаг.Чтобы более эффективно управлять пространством памяти, когда приложение освобождает память, операционной системе необходимо вставить освобожденный блок памяти в связанный список свободных блоков памяти для последующего управления и перераспределения. Сам процесс занимает некоторое время и блокирует приложение, которое в данный момент освобождает память.

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

Поэтому мы должны быть осторожны при удалении большого ключа. Как это сделать? Здесь приведены два метода:

  • Удалить пакетами
  • Асинхронное удаление (Redis версии 4.0 и выше)

1. Удалить пакетами

Для удаления большого хэша используйте hscanкоманду для получения 100 полей за раз, а затем используйте hdelкоманду для удаления 1 поля за раз.

Код Python:

def del_large_hash():
  r = redis.StrictRedis(host='redis-host1', port=6379)
    large_hash_key ="xxx" #要删除的大hash键名
    cursor = '0'
    while cursor != 0:
        # 使用 hscan 命令,每次获取 100 个字段
        cursor, data = r.hscan(large_hash_key, cursor=cursor, count=100)
        for item in data.items():
                # 再用 hdel 命令,每次删除1个字段
                r.hdel(large_hash_key, item[0])

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

Код Python:

def del_large_list():
  r = redis.StrictRedis(host='redis-host1', port=6379)
  large_list_key = 'xxx'  #要删除的大list的键名
  while r.llen(large_list_key)>0:
      #每次只删除最右100个元素
      r.ltrim(large_list_key, 0, -101) 

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

Код Python:

def del_large_set():
  r = redis.StrictRedis(host='redis-host1', port=6379)
  large_set_key = 'xxx'   # 要删除的大set的键名
  cursor = '0'
  while cursor != 0:
    # 使用 sscan 命令,每次扫描集合中 100 个元素
    cursor, data = r.sscan(large_set_key, cursor=cursor, count=100)
    for item in data:
      # 再用 srem 命令每次删除一个键
      r.srem(large_size_key, item)

Для удаления большого ZSet используйте zremrangebyrankкоманду для удаления первых 100 элементов за раз.

Код Python:

def del_large_sortedset():
  r = redis.StrictRedis(host='large_sortedset_key', port=6379)
  large_sortedset_key='xxx'
  while r.zcard(large_sortedset_key)>0:
    # 使用 zremrangebyrank 命令,每次删除 top 100个元素
    r.zremrangebyrank(large_sortedset_key,0,99) 

2. Асинхронное удаление

Начиная с Redis версии 4.0, вы можете использовать метод асинхронного удаления , используя для удаления команду unlink вместо del .

Таким образом, Redis поместит ключ в асинхронный поток для удаления, чтобы основной поток не был заблокирован.

おすすめ

転載: blog.csdn.net/qq_34827674/article/details/126225192