Как безопасно удалить ключи в Redis по маске

Как безопасно удалить ключи в Redis по маске

Redis — одна из самых популярных in-memory баз данных, широко используемая для кэширования, хранения сессий, очередей и временных данных. Благодаря высокой скорости доступа к данным, она стала неотъемлемым компонентом современных веб-приложений. Однако при активной эксплуатации возникает необходимость управления ключами: очистка устаревших данных, удаление по маске, освобождение памяти. Прямое удаление ключей через команду `KEYS` с последующим `DEL` может привести к серьёзным проблемам — блокировке сервера, падению производительности и даже отказу сервиса.

Для безопасного удаления ключей в Redis по маске используйте комбинацию `SCAN` + `MATCH` + `UNLINK`, а не `KEYS`. Это предотвращает блокировку сервера и позволяет работать с большими наборами данных без риска для стабильности системы.

Проблема массового удаления ключи в Redis

Команда `KEYS *session*` кажется простым решением для поиска и удаления всех ключей, связанных с сессиями. Но на практике это опасный подход. `KEYS` блокирует основной поток выполнения Redis до завершения поиска по всей базе данных. При наличии миллионов ключей эта операция может длиться десятки секунд, делая Redis полностью недоступным для других запросов.
Такое поведение недопустимо в production-средах, где каждая миллисекунда простоя влияет на пользовательский опыт и метрики бизнеса. Кроме того, комбинация `KEYS` + `DEL` усугубляет ситуацию: `DEL` тоже работает синхронно и может «подвесить» сервер при удалении тысяч ключей одновременно.

Полезно знать: В Redis 4.0+ команда UNLINK заменяет DEL для больших объектов. Она освобождает память асинхронно, не блокируя основной поток.

Многие администраторы сталкиваются с этой проблемой после внедрения первых скриптов очистки. Они не учитывают архитектуру Redis — однопоточность и синхронную обработку команд. Результат — аварийные остановки, жалобы от пользователей, необходимость экстренного восстановления.

Безопасный способ удаления ключей по маске

Правильный подход — использовать команду `SCAN` с параметром `MATCH`. В отличие от `KEYS`, `SCAN` не блокирует сервер. Он проходит по базе итеративно, возвращая небольшие порции ключей за один вызов. Это позволяет поддерживать высокую доступность Redis даже во время массовых операций.
Алгоритм выглядит так:

  • Выполняется `SCAN cursor MATCH pattern COUNT N` — получаем часть ключей по маске;
  • Для каждого найденного ключа вызывается `UNLINK`, а не `DEL`;
  • Процесс повторяется, пока `cursor` не вернёт 0 (сканирование завершено).

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

«Никогда не используйте KEYS в продакшене. SCAN — ваш единственный безопасный выбор для перебора ключей.» — Алексей С., DevOps-инженер, более 10 лет опыта в распределённых системах

Как работает SCAN: детали

`SCAN` использует итераторы. Первый вызов начинается с `cursor = 0`, последующие — с возвращённого значения. Redis гарантирует, что при отсутствии изменений в наборе ключей `SCAN` обойдёт все элементы. При модификациях возможны дубли, но пропусков не будет.
Параметр `COUNT` указывает примерное количество возвращаемых элементов. На практике лучше задавать от 100 до 1000. Меньше — медленнее, больше — риск временной нагрузки.

Пошаговое руководство: как удалить ключи по маске

Ниже — проверенный алгоритм безопасного удаления ключей в Redis по маске. Подходит для автоматизации и интеграции в скрипты мониторинга.

  1. Подключитесь к Redis: используйте redis-cli, Python (библиотека redis-py) или любой другой клиент.
  2. Выберите базу данных: если используется не db0, переключитесь через SELECT.
  3. Запустите цикл SCAN: начните с курсора 0, применяйте MATCH с нужной маской (например, *:cache).
  4. Обрабатывайте порции ключей: для каждой порции вызывайте UNLINK по одному или пакетно (через pipeline).
  5. Повторяйте, пока курсор не станет 0.
  6. Проверьте результат: можно сравнить количество ключей до и после через DBSIZE.

Пример на Python

«`python
import redis
r = redis.Redis(host=’localhost’, port=6379, db=0)
def delete_keys_by_pattern(pattern, count=100):
cursor = 0
deleted_count = 0

while True:
cursor, keys = r.scan(cursor=cursor, match=pattern, count=count)
if keys:
r.unlink(*keys)
deleted_count += len(keys)

if cursor == 0:
break

print(f»Удалено {deleted_count} ключей по маске ‘{pattern}'»)
# Использование
delete_keys_by_pattern(«*:temp:*», count=500)
«`

Полезно знать: Всегда тестируйте скрипт на резервной копии или в staging-среде. Даже безопасные операции могут иметь побочные эффекты при неправильной маске.

Пример через redis-cli

Если нужно выполнить удаление вручную:
«`bash
# Запуск scan и unlink через Lua-скрипт (чтобы избежать множества round-trip)
redis-cli —eval script_scan_unlink.lua , ‘pattern*:to:delete’ 100
«`
Где `script_scan_unlink.lua`:
«`lua
local pattern = ARGV[1]
local count = tonumber(ARGV[2]) or 100
local cursor = 0
local deleted = 0
repeat
local result = redis.call(‘SCAN’, cursor, ‘MATCH’, pattern, ‘COUNT’, count)
cursor = tonumber(result[1])
local keys = result[2]
if #keys > 0 then
redis.call(‘UNLINK’, unpack(keys))
deleted = deleted + #keys
end
until cursor == 0
return deleted
«`
Запуск:
«`bash
redis-cli —eval script_scan_unlink.lua , ‘*:old:*’ 500
«`

Распространённые ошибки и как их избежать

Ошибки при работе с Redis часто связаны с непониманием его внутреннего устройства. Ниже — типичные проблемы и пути их решения.

Ошибка 1: Использование KEYS вместо SCAN

Как уже говорилось, `KEYS` блокирует сервер. В Redis 7.0+ команда помечена как deprecated для использования в продакшене. Альтернатива — только `SCAN`.

`DEL` синхронно освобождает память. При удалении большого хэша (например, 100 МБ) это может занять сотни миллисекунд. `UNLINK` делегирует работу фоновому потоку, сохраняя отзывчивость.

Команда
Блокировка
Освобождение памяти
Рекомендация
DEL
Да
Синхронно
Только для маленьких ключей
UNLINK
Нет (после v4.0)
Асинхронно
Всегда при массовом удалении

Ошибка 3: Слишком большой COUNT в SCAN

Значение `COUNT=10000` может вернуть тысячи ключей за раз, создавая нагрузку на сеть и клиент. Оптимально — 100–1000.

Ошибка 4: Отсутствие лимита времени выполнения

Даже безопасный `SCAN` может работать долго при миллионах ключей. В скриптах добавляйте контроль времени или ограничение итераций.

Полезно знать: Для очень больших баз используйте SCAN в фоновом процессе с фиксированным временем выполнения (например, 30 секунд за запуск). Это минимизирует влияние на систему.

Инструменты и скрипты для автоматизации

Ручное управление ключами неэффективно. Лучше использовать готовые решения или написать собственные скрипты.

Redis CLI с Lua

Lua-скрипты выполняются на стороне сервера, что снижает задержку. Пример выше — идеален для регулярной очистки.

Python + redis-py

Библиотека `redis-py` поддерживает `scan_iter()` — удобный генератор для обхода ключей.
«`python
for key in r.scan_iter(match=’*:junk:*’, count=500):
r.unlink(key)
«`
Автоматически обрабатывает курсоры, остаётся только вызвать `UNLINK`.

Go и другие языки

В Go есть библиотека `go-redis`, в Java — `Jedis`, в Node.js — `ioredis`. Все поддерживают `SCAN` и `UNLINK`.

Готовые утилиты

  • redex — CLI-инструмент для массовых операций над ключами;
  • redis-gui — графические интерфейсы, но они не всегда используют безопасные методы;
  • Custom cron-задачи — например, ежедневная очистка старых ключей через Python-скрипт.
«Автоматизируйте очистку, но всегда оставляйте логирование и возможность отката.» — Инна К., SRE-инженер, платформа электронной коммерции

Экспертная практика: советы от разработчиков

Опытные специалисты выработали ряд принципов, которые помогают избежать проблем с Redis.

  • Не храните то, что можно не хранить. Чем меньше ключей — тем проще управление. Используйте TTL по умолчанию.
  • Структурируйте ключи. Используйте разделители: service:type:id. Это упрощает поиск и удаление по маске.
  • Тестируйте на снимках данных. Перед запуском скрипта — сделайте RDB-дамп и проверьте на нём.
  • Мониторьте производительность. Следите за latency, blocked_clients, used_memory.
  • Используйте namespace-ключи. Например, v1:users:* — чтобы легко управлять версиями.
Полезно знать: Вместо удаления часто проще переключиться на новое пространство имён и просто игнорировать старые данные. Со временем они удалятся по TTL.

Вопросы и ответы

Можно ли использовать FLUSHDB вместо удаления по маске?
Да, но только если нужно очистить всю базу. Это быстрее и безопаснее, чем массовое удаление, но не решает задачу частичной очистки.
Как узнать, сколько ключей будет затронуто?
Используйте `SCAN` с `COUNT`, но без удаления. Или примените `redis-cli —scan —pattern «your:pattern:*» | wc -l`, но только в тестовой среде.
Безопасен ли SCAN при записи новых ключей?
Да. `SCAN` гарантирует обход всех существующих ключей. Новые могут быть пропущены или дублироваться — это нормально.
Что делать, если UNLINK недоступен?
Обновите Redis до версии 4.0+. На старых версиях используйте `DEL`, но только пакетно и с небольшим количеством ключей за раз.
Как ускорить удаление миллионов ключей?
Параллельные соединения по разным слотам (в кластере), использование `pipeline`, фоновый режим. Но осторожно — не перегружайте сеть и CPU.

Заключение

Удаление ключей в Redis по маске — обычная, но потенциально опасная операция. Прямое использование `KEYS` и `DEL` может вывести систему из строя. Безопасная альтернатива — комбинация `SCAN` + `MATCH` + `UNLINK`, которая обеспечивает стабильность и производительность даже при работе с миллионами ключей.

Главное правило: никогда не блокируйте основной поток Redis. Выбор правильных инструментов и методов — залог надёжности вашей инфраструктуры.
  • Используйте `SCAN`, а не `KEYS`, для поиска ключей.
  • Применяйте `UNLINK` вместо `DEL` при массовом удалении.
  • Тестируйте скрипты в staging-среде перед запуском в продакшене.
  • Автоматизируйте очистку, но с контролем и логированием.
  • Структурируйте ключи и используйте TTL для упрощения управления.
⚠️ Дисклеймер — нажмите, чтобы развернуть

Материалы, опубликованные в разделе «Блог» на сайте RU DESIGN SHOP (rudesignshop.ru), носят исключительно информационный и ознакомительный характер и не являются руководством к действию, финансовой рекомендацией, медицинской услугой, ветеринарным назначением либо рекламой товаров и услуг, включая азартные игры. Публикации не содержат призывов к участию в азартных играх и не направлены на продвижение соответствующих операторов.

Безопасность применения товаров и веществ: при использовании строительных материалов, бытовой химии, пестицидов и агрохимикатов необходимо строго следовать инструкциям производителя и действующему законодательству Российской Федерации, включая Федеральный закон РФ от 19.07.1997 № 109-ФЗ «О безопасном обращении с пестицидами и агрохимикатами».

Упоминание товарных знаков, брендов и организаций носит исключительно информационный характер и не означает наличие партнёрских отношений или одобрения со стороны правообладателей.

Материалы, содержащие сведения о медицинских, ветеринарных или косметических средствах, представлены в справочных целях и не являются медицинской консультацией или назначением. Перед применением рекомендуется обратиться к врачу, ветеринарному специалисту или иному сертифицированному профессионалу.

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

Правовая ответственность: решения, принятые на основе опубликованной информации, пользователь принимает самостоятельно и на свой риск; редакция и авторы несут ответственность в пределах, установленных законодательством Российской Федерации.

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

Упоминание организаций с ограниченным статусом: компания Meta Platforms Inc. (социальные сети Facebook и Instagram) признана экстремистской организацией решением суда РФ, её деятельность запрещена на территории Российской Федерации; любые упоминания приводятся исключительно в информационных целях.

Авторские права и источники: информация собирается из открытых источников; её актуальность указывается на дату публикации и может изменяться.

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

Персональные данные и cookies: сайт использует cookies и обрабатывает персональные данные пользователей в соответствии с Федеральным законом № 152-ФЗ «О персональных данных» и Политикой конфиденциальности RU DESIGN SHOP.

Мнения авторов могут не совпадать с позицией государственных органов или коммерческих организаций, упомянутых в материалах.