20 ответов:
начиная с redis 2.6.0, вы можете запускать сценарии lua, которые выполняются атомарно. Я никогда не писал, но я думаю, что это будет выглядеть примерно так
EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:*посмотреть EVAL documentation.
выполнить в bash:
redis-cli KEYS "prefix:*" | xargs redis-cli DELобновление
Ок, я понял. Как насчет этого способа: сохраните текущий дополнительный инкрементный префикс и добавьте его ко всем своим ключам. Например:
у вас есть такие значения:
prefix_prefix_actuall = 2 prefix:2:1 = 4 prefix:2:2 = 10когда вам нужно очистить данные, вы сначала измените prefix_actuall (например, установите prefix_prefix_actuall = 3), поэтому ваше приложение будет записывать новые данные в ключи prefix:3:1 и prefix:3:2. Тогда можно смело брать старые значения из префикса: 2:1 и префикс:2: 2 и очистить старые ключи.
вот полностью рабочая и атомарная версия wildcard delete, реализованная в Lua. Он будет работать намного быстрее, чем версия xargs из-за гораздо меньшей сети взад и вперед, и он полностью атомарен, блокируя любые другие запросы против redis до его завершения. Если вы хотите атомарно удалить ключи на Redis 2.6.0 или выше, это определенно путь:
redis-cli -n [some_db] -h [some_host_name] EVAL "return redis.call('DEL', unpack(redis.call('KEYS', ARGV[1] .. '*')))" 0 prefix:это рабочая версия идеи @mcdizzle в его ответе на этот вопрос. Кредит на идею 100% подходит к нему.
EDIT: в комментарии Кикито ниже, если у вас есть больше ключей для удаления, чем свободной памяти на вашем сервере Redis, вы столкнетесь с "слишком много элементов для распаковки" ошибка. В таком случае сделайте:
for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) endКак Kikito предложил.
отказ от ответственности: следующие решение не обеспечить атомарность.
начиная с v2. 8 вы действительно хочу использовать SCAN команда вместо клавиш[1]. Следующий скрипт демонстрирует удаление ключей по шаблону:
#!/bin/bash if [ $# -ne 3 ] then echo "Delete keys from Redis matching a pattern using SCAN & DEL" echo "Usage: <host> <port> <pattern>" exit 1 fi cursor=-1 keys="" while [ $cursor -ne 0 ]; do if [ $cursor -eq -1 ] then cursor=0 fi reply=`redis-cli -h -p SCAN $cursor MATCH ` cursor=`expr "$reply" : '\([0-9]*[0-9 ]\)'` keys=${reply##[0-9]*[0-9 ]} redis-cli -h -p DEL $keys done[1] ключи это опасная команда, которая потенциально может привести к DoS. Ниже приводится цитата из его страницы документации:
предупреждение: рассматривайте ключи как команду, которая должна использоваться только в производственных средах с особой осторожностью. Это может привести к снижению производительности при выполнении для больших баз данных. Эта команда предназначена для отладки и проведения специальных операций, таких как изменение макета ключей. Не используйте ключи в своем обычном коде приложения. Если вы ищете способ найти ключи в подмножестве вашего пространства ключей, рассмотрите возможность использования наборов.
обновление: a один лайнер для того же основного эффекта -
$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL
для тех, у кого возникли проблемы с разбором других ответов:
eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0заменить
key:*:patternС вашим собственным шаблоном и введите это вredis-cliи вы хорошо идти.Credit lisco от:http://redis.io/commands/del
Я использую ниже команду в redis 3.2.8
redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DELвы можете получить дополнительную помощь, связанную с поиском шаблонов ключей здесь: -https://redis.io/commands/keys. Используйте вашу удобную картину Глоб-стиля согласно вашему требованию как
*YOUR_KEY_PREFIX*илиYOUR_KEY_PREFIX??или любой другой.и если кто-то из вас интегрированы Redis PHP библиотека чем ниже функция поможет вам.
flushRedisMultipleHashKeyUsingPattern("*YOUR_KEY_PATTERN*"); //function call function flushRedisMultipleHashKeyUsingPattern($pattern='') { if($pattern==''){ return true; } $redisObj = $this->redis; $getHashes = $redisObj->keys($pattern); if(!empty($getHashes)){ $response = call_user_func_array(array(&$redisObj, 'del'), $getHashes); //setting all keys as parameter of "del" function. Using this we can achieve $redisObj->del("key1","key2); } }спасибо :)
решение @ mcdizle не работает он работает только для одной записи.
это работает для всех ключей с одинаковым префиксом
EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*Примечание: вы должны заменить 'префикс' с вашим ключевым префиксом...
Если у вас есть пробелы в имени ключей, вы можете использовать это в bash:
redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del
@Итамар ответ отличный, но разбор ответа не работал для меня, esp. в случае, когда в данном сканировании нет ключей. Возможно, более простое решение, непосредственно из консоли:
redis-cli -h HOST -p PORT --scan --pattern "prefix:*" | xargs -n 100 redis-cli DELЭто также использует сканирование, которое предпочтительно для ключей в производстве, но не является атомарным.
вы также можете использовать эту команду для удаления ключей: -
предположим, что в вашем redis есть много типов ключей, таких как -
- 'xyz_category_fpc_12'
- 'xyz_category_fpc_245'
- 'xyz_category_fpc_321'
- 'xyz_product_fpc_876'
- 'xyz_product_fpc_302'
- 'xyz_product_fpc_01232'
Ex -'xyz_category_fpc здесь xyz is а имя_сайта, и эти ключи связаны с продуктами и категориями сайта электронной коммерции и генерируются FPC.
Если вы используете эту команду, а ниже-
redis-cli --scan --pattern 'key*' | xargs redis-cli delили
redis-cli --scan --pattern 'xyz_category_fpc*' | xargs redis-cli delОн удаляет все ключи, как 'xyz_category_fpc' (удалить 1, 2 и 3 клавиши). Для удаления других 4, 5 и 6 цифровых клавиш использовать 'xyz_product_fpc в вышеуказанной команды.
Если вы хотите Удалить Все in Рэдис, затем выполните следующие команды-
С redis-cli:
- FLUSHDB - удаляет данные из текущей базы данных вашего соединения.
- FLUSHALL - удаляет данные из всех баз данных.
например:- в командной строке:
redis-cli flushall redis-cli flushdb
у меня была та же проблема. Я сохранил данные сеанса для пользователя в формате:
session:sessionid:key-x - value of x session:sessionid:key-y - value of y session:sessionid:key-z - value of zтаким образом, каждая запись была отдельной парой ключ-значение. Когда сеанс будет уничтожен, я хотел удалить все данные сеанса, удалив ключи с шаблоном
session:sessionid:*- но Redis не имеет такой функции.что я сделал: хранить данные сессии в хэш. Я просто создаю хэш с идентификатором хэша
session:sessionidа потом я толкаюkey-x,key-y,key-zin этот хэш (порядок не имеет значения для меня) , и если мне больше не нужен этот хэш, я просто делаюDEL session:sessionidи все данные, связанные с этим хэш-код исчез.DELявляется атомарным и доступ к данным / запись данных в хэш-Это O (1).
Я думаю, что может помочь вам-это MULTI / EXEC / DISCARD. Пока нет 100% эквивалент сделок, вы должны быть в состоянии изолировать удаляет из других обновлений.
к вашему сведению.
- только с помощью bash и
redis-cli- не используя
keys(при этом используетсяscan)- работает в режим кластера
- не атомные
может быть, вам нужно только изменить символов столицы.
scan-match.sh
#!/bin/bash rcli=“/YOUR_PATH/redis-cli" default_server="YOUR_SERVER" default_port="YOUR_PORT" servers=`$rcli -h $default_server -p $default_port cluster nodes | grep master | awk '{print }' | sed 's/:.*//'` if [ x"" == "x" ]; then startswith="DEFAULT_PATTERN" else startswith="" fi MAX_BUFFER_SIZE=1000 for server in $servers; do cursor=0 while r=`$rcli -h $server -p $default_port scan $cursor match "$startswith*" count $MAX_BUFFER_SIZE ` cursor=`echo $r | cut -f 1 -d' '` nf=`echo $r | awk '{print NF}'` if [ $nf -gt 1 ]; then for x in `echo $r | cut -f 1 -d' ' --complement`; do echo $x done fi (( cursor != 0 )) do : done doneclear-redis-key.sh
#!/bin/bash STARTSWITH="" RCLI=YOUR_PATH/redis-cli HOST=YOUR_HOST PORT=6379 RCMD="$RCLI -h $HOST -p $PORT -c " ./scan-match.sh $STARTSWITH | while read -r KEY ; do $RCMD del $KEY doneвыполнить в командной строке
$ ./clear-redis-key.sh key_head_pattern
это не прямой ответ на вопрос, но когда я попал сюда, когда искал ответы, я поделюсь этим здесь.
Если у вас есть десятки или сотни миллионов ключей, которые вы должны соответствовать, ответы, приведенные здесь, заставят Redis не реагировать на значительное количество времени (минут?), и потенциально сбой из-за потребления памяти (убедитесь, что сохранение фона начнется в середине вашей операции).
бесспорно, следующий подход некрасиво, но лучшего я не нашел. Атомарность здесь не обсуждается, в этом случае основная цель-поддерживать Redis и реагировать на 100% времени. Он будет работать отлично, если у вас есть все ваши ключи в одной из баз данных, и вам не нужно соответствовать какой-либо шаблон, но не может использовать http://redis.io/commands/FLUSHDB из-за этого блокирует природу.
идея проста: написать скрипт, который работает в цикле и использует O (1) операции, как http://redis.io/commands/SCAN или http://redis.io/commands/RANDOMKEY чтобы получить ключи, проверьте, соответствуют ли они шаблону (если вам это нужно) и http://redis.io/commands/DEL их по одному.
Если есть лучший способ сделать это, пожалуйста, дайте мне знать, я буду обновлять ответ.
пример реализации с randomkey в Ruby, как задача рейка, неблокирующая замена чего-то вроде
redis-cli -n 3 flushdb:desc 'Cleanup redis' task cleanup_redis: :environment do redis = Redis.new(...) # connection to target database number which needs to be wiped out counter = 0 while key = redis.randomkey puts "Deleting #{counter}: #{key}" redis.del(key) counter += 1 end end
Это просто реализовано с помощью функции" удалить ветку " в FastoRedis, просто выберите ветку, которую вы хотите удалить.
версия, использующая сканирование, а не ключи (как рекомендуется для производственных серверов) и
--pipeа не xargs.Я предпочитаю pipe над xargs, потому что он более эффективен и работает, когда ваши ключи содержат кавычки или другие специальные символы, которые ваша оболочка пытается интерпретировать. Подстановка регулярных выражений в этом примере заключает ключ в двойные кавычки и экранирует любые двойные кавычки внутри.
export REDIS_HOST=your.hostname.com redis-cli -h "$REDIS_HOST" --scan --pattern "YourPattern*" > /tmp/keys time cat /tmp/keys | perl -pe 's/"/\"/g;s/^/DEL "/;s/$/"/;' | redis-cli -h "$REDIS_HOST" --pipe
атомная масса бедняги-удалить?
может быть, вы могли бы установить их все, чтобы истечь в ту же секунду - как несколько минут в будущем - а затем ждать до этого времени и увидеть их все "самоуничтожение" в то же время.
но я не совсем уверен, как атомная, что будет.
Я поддерживаю все ответы, связанные с наличием какого-либо инструмента или выполнения выражения Lua.
еще один вариант с моей стороны:
в наших производственных и предпроизводственных базах данных есть тысячи ключей. Время от времени нам нужно удалять некоторые ключи (по какой-то маске), изменять по каким-то критериям и т. д. Конечно, нет никакого способа сделать это вручную из CLI, особенно имея sharding (512 логических dbs в каждом физическом).
для этой цели я пишу java client tool, который выполняет всю эту работу. В случае удаления ключей утилита может быть очень простой, там только один класс:
public class DataCleaner { public static void main(String args[]) { String keyPattern = args[0]; String host = args[1]; int port = Integer.valueOf(args[2]); int dbIndex = Integer.valueOf(args[3]); Jedis jedis = new Jedis(host, port); int deletedKeysNumber = 0; if(dbIndex >= 0){ deletedKeysNumber += deleteDataFromDB(jedis, keyPattern, dbIndex); } else { int dbSize = Integer.valueOf(jedis.configGet("databases").get(1)); for(int i = 0; i < dbSize; i++){ deletedKeysNumber += deleteDataFromDB(jedis, keyPattern, i); } } if(deletedKeysNumber == 0) { System.out.println("There is no keys with key pattern: " + keyPattern + " was found in database with host: " + host); } } private static int deleteDataFromDB(Jedis jedis, String keyPattern, int dbIndex) { jedis.select(dbIndex); Set<String> keys = jedis.keys(keyPattern); for(String key : keys){ jedis.del(key); System.out.println("The key: " + key + " has been deleted from database index: " + dbIndex); } return keys.size(); } }
Spring RedisTemplate сам обеспечивает функциональность. RedissonClient в последней версии устарел функциональность "deleteByPattern".
Set<String> keys = redisTemplate.keys("geotag|*"); redisTemplate.delete(keys);

Comments