【问题标题】:How to atomically delete keys matching a pattern using Redis如何使用 Redis 以原子方式删除与模式匹配的键
【发布时间】:2011-04-29 17:04:20
【问题描述】:

在我的 Redis 数据库中,我有许多 prefix:<numeric_id> 哈希。

有时我想以原子方式清除它们。在不使用一些分布式锁定机制的情况下如何做到这一点?

【问题讨论】:

  • 嗨,史蒂夫,我的网站有问题,我已将其添加到我的其他博客 mind-geek.net/nosql/redis/delete-keys-specific-expiry-time,希望对您有所帮助。
  • 这是一个很常见的场景,我希望 Redis 团队考虑为其添加原生命令。
  • 现在你可以用 Lua 做到这一点,见下文。
  • @ToddMenier 刚刚建议,得到了为什么它永远不会发生的原因:github.com/antirez/redis/issues/2042
  • 很多人就如何处理大量键、带有特殊字符的键等提出相关问题。我创建了一个单独的问题,因为我们现在遇到了这个问题,我不认为答案张贴在这个问题上。这是另一个问题:*.com/questions/32890648/…

标签: redis


【解决方案1】:

在 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。然后,您可以安全地从 prefix:2:1 和 prefix:2:2 中获取旧值并清除旧键。

【讨论】:

  • 抱歉,这不是原子删除。有人可能会在 KEYS 和 DEL 之间添加新密钥。我不想删除那些。
  • 键,在KEYS命令后创建的不会被删除。
  • 我只需要清除一些坏键,所以凯西的第一个答案是正确的,除了我必须将键移到引号之外:redis-cli KEYS "prefix:*" | xargs redis-cli DEL
  • 第一个答案也帮助了我。如果您的 redis 键包含引号或其他会混淆 xargs 的字符,则另一种变体:redis-cli KEYS "prefix:*" | xargs --delim='\n' redis-cli DEL
  • 如果您有多个数据库(键空间),那么这就是诀窍:假设您需要删除 db3 中的键:redis-cli -n 3 KEYS "prefix:*" | xargs redis-cli -n 3 DEL
【解决方案2】:

从 redis 2.6.0 开始,您可以运行 lua 脚本,这些脚本以原子方式执行。我从来没有写过,但我认为它看起来像这样

EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 prefix:[YOUR_PREFIX e.g delete_me_*]

警告:正如Redis document 所说,由于性能问题,keys 命令不应该用于生产中的常规操作,这个 命令用于调试和特殊操作。 read more

请参阅EVAL documentation

【讨论】:

  • 重要提示:如果您有超过几千个与前缀匹配的键,则会失败。
  • 这个适用于大量密钥:EVAL "local keys = redis.call('keys', ARGV[1]) \n for i=1,#keys,5000 do \n redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) \n end \n return keys" 0 prefix:*
  • 哎呀... redis 被用作简单的键/存储缓存。这似乎del prefix:* 应该是一个基本操作:/
  • @Ray 坦率地说,如果您需要该功能,您应该简单地按 numetic 数据库或服务器对数据进行分区,然后使用 flush / flushdb
  • 是的,如果没有键匹配模式,它会失败。为了解决这个问题,我添加了一个默认密钥:EVAL "return redis.call('del', 'defaultKey', unpack(redis.call('keys', ARGV[1])))" 0 prefix:*
【解决方案3】:

这是在 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% 归功于他。

编辑:根据下面 Kikito 的评论,如果您的 Redis 服务器中要删除的键多于可用内存,您将遇到 "too many elements to unpack" error。在这种情况下,请执行以下操作:

for _,k in ipairs(redis.call('keys', ARGV[1])) do 
    redis.call('del', k) 
end

正如 Kikito 建议的那样。

【讨论】:

  • 如果你有大量的键,上面的代码将会失败(错误是“太多的元素无法解压”)。我建议在 Lua 部分使用循环:for _,k in ipairs(redis.call('keys', KEYS[1])) do redis.call('del', k) end
  • @kikito,是的,如果 lua 无法将堆栈增加到您要删除的键数(很可能是由于内存不足),您需要使用 for 循环来完成。除非你必须这样做,否则我不建议这样做。
  • Lua 的unpack 将表格转换为“自变量列表”(其他语言称之为explode),但最大数量不依赖于系统内存;它通过LUAI_MAXSTACK 常量在lua 中固定。在 Lua 5.1 和 LuaJIT 中为 8000,在 Lua 5.2 中为 100000。IMO 建议使用 for 循环选项。
  • 值得注意的是,lua 脚本仅在 Redis 2.6 以上可用
  • 任何基于 Lua 的解决方案都将违反 EVAL 的语义,因为它没有预先指定它将操作的键。它应该适用于单个实例,但不要指望它适用于 Redis 集群。
【解决方案4】:

免责声明:以下解决方案提供原子性。

从 v2.8 开始,您真的想要使用 SCAN 命令而不是 KEYS[1]。以下 Bash 脚本演示了按模式删除键:

#!/bin/bash

if [ $# -ne 3 ] 
then
  echo "Delete keys from Redis matching a pattern using SCAN & DEL"
  echo "Usage: $0 <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 $1 -p $2 SCAN $cursor MATCH $3`
  cursor=`expr "$reply" : '\([0-9]*[0-9 ]\)'`
  keys=${reply##[0-9]*[0-9 ]}
  redis-cli -h $1 -p $2 DEL $keys
done

[1] KEYS 是一个危险的命令,可能会导致 DoS。以下是其文档页面的引述:

警告: 将 KEYS 视为仅应极其小心地在生产环境中使用的命令。当它针对大型数据库执行时,它可能会破坏性能。此命令用于调试和特殊操作,例如更改键空间布局。不要在常规应用程序代码中使用 KEYS。如果您正在寻找一种在键空间子集中查找键的方法,请考虑使用集合。

更新:具有相同基本效果的单眼线 -

$ redis-cli --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli DEL

【讨论】:

  • 尽管如此,避免使用 KEYS 绝对是最佳实践,因此在非原子删除可行的情况下,这是一个很好的解决方案。
  • 这对我有用;但是,我的密钥恰好在数据库 1 中。所以我必须在每个 redis-cli 调用中添加 -n 1redis-cli -n 1 --scan --pattern "*:foo:bar:*" | xargs -L 100 redis-cli -n 1 DEL
  • 请注意,如果您的密钥包含特殊字符,这将不起作用
  • 有趣且有价值的发现...我想知道是否有办法为 xargs 引用东西...
  • -L 100 有什么作用??
【解决方案5】:

对于那些无法解析其他答案的人:

eval "for _,k in ipairs(redis.call('keys','key:*:pattern')) do redis.call('del',k) end" 0

key:*:pattern 替换为您自己的模式并将其输入redis-cli,您就可以开始了。

信用证来自:http://redis.io/commands/del

【讨论】:

    【解决方案6】:

    我在 redis 3.2.8 中使用以下命令

    redis-cli KEYS *YOUR_KEY_PREFIX* | xargs redis-cli DEL
    

    您可以从这里获得更多与键模式搜索相关的帮助:- https://redis.io/commands/keys。根据您的要求使用方便的 glob 样式模式,例如 *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);
                }
            }
    

    谢谢你:)

    【讨论】:

    • 这对我没有任何作用。
    【解决方案7】:

    您也可以使用此命令删除键:-

    假设你的 redis 中有很多类型的键,比如-

    1. 'xyz_category_fpc_12'
    2. 'xyz_category_fpc_245'
    3. 'xyz_category_fpc_321'
    4. 'xyz_product_fpc_876'
    5. 'xyz_product_fpc_302'
    6. 'xyz_product_fpc_01232'

    Ex- 'xyz_category_fpc' 这里xyz是一个sitename,这些keys与一个电子商务网站的产品和类别有关由 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”。

    如果您想在 Redis删除所有内容,请按照这些命令-

    使用 redis-cli:

    1. FLUSHDB - 从连接的 CURRENT 数据库中删除数据。
    2. FLUSHALL - 从所有数据库中删除数据。

    例如:- 在你的 shell 中:

    redis-cli flushall
    redis-cli flushdb
    

    【讨论】:

    • 谢谢,但是到redis-cli del 的管道输出不是原子的。
    • 如果键有空格或双引号则不起作用。
    【解决方案8】:

    @mcdizle 的解决方案不起作用,它仅适用于一个条目。

    这个适用于所有具有相同前缀的键

    EVAL "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" 0 prefix*
    

    注意:您应该将“前缀”替换为您的密钥前缀...

    【讨论】:

    • 使用 lua 比使用 xargs 快 loooooot,顺序为 10^4。
    • 固体溶液!
    【解决方案9】:

    如果键名中有空格,可以在 bash 中使用:

    redis-cli keys "pattern: *" | xargs -L1 -I '$' echo '"$"' | xargs redis-cli del
    

    【讨论】:

      【解决方案10】:

      @itamar 的回答很棒,但是回复的解析对我不起作用,尤其是。在给定扫描中没有找到密钥的情况下。一个可能更简单的解决方案,直接从控制台:

      redis-cli -h HOST -p PORT  --scan --pattern "prefix:*" | xargs -n 100 redis-cli DEL
      

      这也使用了 SCAN,它在生产中比 KEYS 更可取,但不是原子的。

      【讨论】:

        【解决方案11】:

        如果您的密钥包含特殊字符 - 例如Guide$CLASSMETADATA][1],其他答案可能无效。将每个键包含在引号中将确保它们被正确删除:

        redis-cli --scan --pattern sf_* | awk '{print $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
        

        【讨论】:

        • 此脚本运行良好,已使用超过 25000 个键进行测试。
        • 你也可以使用这个有趣的表达式在 awk 中添加单引号 `awk '{ print "'"'"'" $1 "'"'"'"}'`
        • 上述命令运行良好,但使用扫描和模式需要很长时间才能完成(对于 1600 个键)。为了加快速度,使用:keys 命令 redis-cli keys sf_* | awk '{打印 $1}' | sed "s/^/'/;s/$/'/" | xargs redis-cli del
        【解决方案12】:

        我也遇到了同样的问题。我以以下格式存储用户的会话数据:

        session:sessionid:key-x - value of x
        session:sessionid:key-y - value of y
        session:sessionid:key-z - value of z
        

        因此,每个条目都是一个单独的键值对。当会话被销毁时,我想通过删除模式为session:sessionid:* 的键来删除所有会话数据 - 但redis没有这样的功能。

        我做了什么:将会话数据存储在 hash 中。我只是创建一个哈希ID为session:sessionid的哈希,然后我在那个哈希中推送key-xkey-ykey-z(顺序对我来说并不重要),如果我不再需要那个哈希,我就做DEL session:sessionid 并且与该哈希 id 关联的所有数据都消失了。 DEL 是原子的,访问数据/将数据写入哈希是 O(​​1)。

        【讨论】:

        • 很好的解决方案,但我的值本身就是哈希值。 Redis 将哈希存储在另一个哈希中。
        • 但是,哈希中的字段缺少过期功能,这有时非常有用。
        • 对我来说这是迄今为止最干净/最简单的答案
        • 一组不是更有意义吗?
        【解决方案13】:

        // TODO

        您认为它的命令没有意义,但有时像 DEL 这样的 Redis 命令无法正常工作并解决了这个问题

        redis-cli KEYS "*" | xargs -i redis-cli EXPIRE {} 1 这是生活小窍门

        【讨论】:

        • 这个工作(没有其他工作)除了当一个键有引号时。
        • 添加需要从数据库中删除数据时使用 redis-cli -n KEYS "*" | xargs -i redis-cli EXPIRE {} 1
        • 这不是原子的。
        【解决方案14】:

        使用 SCAN 而不是 KEYS 的版本(推荐用于生产服务器)和 --pipe 而不是 xargs。

        我更喜欢管道而不是 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
        

        【讨论】:

        • 这个解决方案对我来说效果很好,即使在大约 7m 键上!
        【解决方案15】:

        我认为MULTI/EXEC/DISCARD 可能对您有所帮助。虽然不是100% equivalent of transactions,但您应该能够将删除与其他更新隔离开来。

        【讨论】:

        • 但我不知道如何在这里使用它们。 DEL 本身就是原子的(或者我认为)。在执行 EXEC 之前,我无法从 KEYS 获取值,因此我不能在同一个 MULTI 中使用 KEYS 和 DEL。
        【解决方案16】:

        仅供参考。

        • 仅使用 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 $2}' | sed 's/:.*//'`
        if [ x"$1" == "x" ]; then 
            startswith="DEFAULT_PATTERN"
        else
            startswith="$1"
        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
        done
        

        clear-redis-key.sh

        #!/bin/bash
        STARTSWITH="$1"
        
        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
        

        在 bash 提示符下运行

        $ ./clear-redis-key.sh key_head_pattern
        

        【讨论】:

          【解决方案17】:

          请使用此命令并尝试:

          redis-cli --raw keys "$PATTERN" | xargs redis-cli del
          

          【讨论】:

          • 不是原子的,会重复其他答案。
          【解决方案18】:

          这不是问题的直接答案,但由于我是在寻找自己的答案时来到这里的,所以我会在这里分享。

          如果您必须匹配数千万或数亿个键,则此处给出的答案将导致 Redis 在很长一段时间(几分钟?)内无响应,并可能因内存消耗而崩溃(请确保,后台保存将在您的操作过程中启动)。

          以下方法无疑是丑陋的,但我没有找到更好的方法。原子性在这里是毫无疑问的,在这种情况下,主要目标是保持 Redis 100% 的正常运行和响应。如果您在其中一个数据库中拥有所有密钥并且您不需要匹配任何模式,但由于它的阻塞性质而不能使用http://redis.io/commands/FLUSHDB,它将完美地工作。

          想法很简单:编写一个循环运行的脚本,并使用 O(1) 操作,如 http://redis.io/commands/SCANhttp://redis.io/commands/RANDOMKEY 来获取密钥,检查它们是否匹配模式(如果需要)和 http://redis.io/commands/DEL他们一一。

          如果有更好的方法,请告诉我,我会更新答案。

          在 Ruby 中使用 randomkey 的示例实现,作为 rake 任务,是 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
          

          【讨论】:

            【解决方案19】:

            我尝试了上面提到的大多数方法,但它们对我不起作用,经过一些搜索我发现了以下几点:

            • 如果你在redis上有多个数据库,你应该使用-n [number]来确定数据库
            • 如果您有几个键,请使用 del,但如果有数千或数百万个键,最好使用 unlink,因为 unlink 是非阻塞的,而 del 是阻塞的,了解更多信息访问此页面unlink vs del
            • keys 也像 del 并且正在阻塞

            所以我使用此代码按模式删除键:

             redis-cli -n 2 --scan --pattern '[your pattern]' | xargs redis-cli -n 2 unlink 
            

            【讨论】:

              【解决方案20】:

              以下命令对我有用。

              redis-cli -h redis_host_url KEYS "*abcd*" | xargs redis-cli -h redis_host_url DEL
              

              【讨论】:

              • 被否决的任何具体原因?这对我也有用。
              • 我不认为这个答案会原子地删除键并且是不正确的答案。键在多次操作中被删除。
              【解决方案21】:

              我用最简单的 EVAL 命令变体成功了:

              EVAL "return redis.call('del', unpack(redis.call('keys', my_pattern_here*)))" 0
              

              我用我的值替换了my_pattern_here

              【讨论】:

              • 这行得通,但我必须使用单引号。示例:EVAL "return redis.call('del', unpack(redis.call('keys', 'my_pattern_here*')))" 0
              【解决方案22】:

              添加到this答案:

              要查找前 1000 个键:

              EVAL "return redis.call('scan', 0, 'COUNT', 1000, 'MATCH', ARGV[1])" 0 find_me_*
              

              删除它们:

              EVAL "return redis.call('del', unpack(redis.call('SCAN', 0, 'COUNT', 1000, 'MATCH', ARGV[1])[2]))" 0 delete_me_*
              

              【讨论】:

                【解决方案23】:

                这个对我有用,但可能不是原子的:

                redis-cli keys "stats.*" | cut -d ' ' -f2 | xargs -d '\n' redis-cli DEL
                

                【讨论】:

                • 这是非原子的。
                【解决方案24】:

                穷人的原子质量删除?

                也许您可以在同一秒内将它们全部设置为 EXPIREAT(比如几分钟后),然后等到那个时间,同时看到它们全部“自毁”。

                但我不确定这会有多原子性。

                【讨论】:

                  【解决方案25】:

                  我支持所有与使用某些工具或执行 Lua 表达式相关的答案。

                  我这边还有一个选择:

                  在我们的生产和预生产数据库中,有数千个密钥。有时我们需要删除一些键(通过一些掩码),根据一些标准进行修改等。当然,没有办法从 CLI 手动完成,尤其是有分片(每个物理中有 512 个逻辑数据库)。

                  为此,我编写了完成所有这些工作的 java 客户端工具。在删除键的情况下,该实用程序可以非常简单,那里只有一个类:

                  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();
                      }
                  
                  }
                  

                  【讨论】:

                    【解决方案26】:

                    现在,您可以使用 redis 客户端并执行第一次 SCAN(支持模式匹配),然后单独删除每个键。

                    不过redis官方github上有一个问题是创建patter-matching-delhere,觉得有用就点个赞吧!

                    【讨论】:

                      【解决方案27】:

                      如果您的键名中有空格,这将适用于 MacOS

                      redis-cli --scan --pattern "myprefix:*" | tr \\n \\0 | xargs -0 redis-cli unlink
                      

                      【讨论】:

                      • 这不是原子的。
                      【解决方案28】:

                      如果你使用的是低于 4 的 Redis 版本,你可以试试

                      redis-cli -h 127.0.0.1 -p 26379 -a `yourPassword` --scan --pattern data:* | xargs redis-cli del
                      

                      如果你使用的是以上 4 个版本,那么

                      redis-cli -h 127.0.0.1 -p 26379 -a `yourPassword` --scan --pattern data:*| xargs redis-cli unlink
                      

                      要检查您的版本,请使用以下命令输入您的 Redis 终端

                      redis-cli -h 127.0.0.1 -p 26379 -a `yourPassword
                      

                      然后输入

                      > INFO
                      
                      # Server
                      redis_version:5.0.5
                      redis_git_sha1:00000000
                      redis_git_dirty:0
                      redis_build_id:da75abdfe06a50f8
                      redis_mode:standalone
                      os:Linux 5.3.0-51-generic x86_64
                      arch_bits:64
                      multiplexing_api:epoll
                      atomicvar_api:atomic-builtin
                      gcc_version:7.5.0
                      process_id:14126
                      run_id:adfaeec5683d7381a2a175a2111f6159b6342830
                      tcp_port:6379
                      uptime_in_seconds:16860
                      uptime_in_days:0
                      hz:10
                      configured_hz:10
                      lru_clock:15766886
                      executable:/tmp/redis-5.0.5/src/redis-server
                      config_file:
                      
                      # Clients
                      connected_clients:22
                      ....More Verbose
                      

                      【讨论】:

                      • 这不是原子操作
                      • 谢谢@AlexanderGladysh,但我不明白为什么取消链接或删除不是自动的,你愿意解释一下吗。
                      • 键集可能会在第一次和随后的 redis-cli 调用之间发生变化。您必须枚举键并在单个原子操作中删除它们以防止这种情况。请参阅接受的答案以获取示例。
                      • 所以你的意思是如果我使用 EVAL 和 lua 脚本那么它将是原子的?
                      • 是的,如果您在单个脚本调用中枚举和删除键,它应该是原子的。
                      【解决方案29】:

                      如果您使用windows环境,请按照以下步骤操作,一定可以:

                      1. 从这里下载 GOW - https://github.com/bmatzelle/gow/wiki(因为 xargs 命令在 Windows 中不起作用)

                      2. 下载redis-cli for Windows(详细解释在这里-https://medium.com/@binary10111010/redis-cli-installation-on-windows-684fb6b6ac6b

                      3. 运行cmd打开redis-cli存储的目录(例如:D:\Redis\Redis-x64-3.2.100)

                      4. 如果您想删除以“Global:ProviderInfo”开头的所有键,请执行此查询(需要更改粗体参数(主机、端口、密码、键)并写入您的,因为这只是示例):

                        redis-cli -h redis.test.com -p 6379 -a redispassword --raw keys "全局:提供者信息*" | xargs redis-cli -h redis.test.com -p 6379 -a redispassword del

                      【讨论】:

                      • 这不是原子的。
                      【解决方案30】:

                      这是在不使用任何 xargs 魔法的情况下想到的最简单的方法

                      纯粹的狂欢!

                      redis-cli DEL $(redis-cli KEYS *pattern*)
                      

                      【讨论】:

                      • 这不是原子操作