当我们需要遍历Redis所有key或者指定模式的key时,首先想到的是KEYS命令:

KEYS pattern

 

官网对于KEYS命令有一个提示: KEYS 的速度非常快,例如,Redis在一个有1百万个key的数据库里面执行一次查询需要的时间是40毫秒 。但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的 KEYS, 你最好还是用 Redis 的集合结构 SETS 来代替。

KEYS命令使用很简单。
 
  1.  
    redis> MSET one 1 two 2 three 3 four 4
  2.  
    OK
  3.  
    redis> KEYS *o*
  4.  
    1) "four"
  5.  
    2) "one"
  6.  
    3) "two"
  7.  
    redis> KEYS t??
  8.  
    1) "two"
  9.  
    redis> KEYS *
  10.  
    1) "four"
  11.  
    2) "three"
  12.  
    3) "one"
  13.  
    4) "two"
  14.  
    redis>

但由于KEYS命令一次性返回所有匹配的key,所以,当redis中的key非常多时,对于内存的消耗和redis服务器都是一个隐患,

对于Redis 2.8以上版本给我们提供了一个更好的遍历key的命令 SCAN 该命令的基本格式:
 
SCAN cursor [MATCH pattern] [COUNT count]

SCAN 每次执行都只会返回少量元素,所以可以用于生产环境,而不会出现像 KEYS 或者 SMEMBERS 命令带来的可能会阻塞服务器的问题。

SCAN命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程

SCAN命令的游标参数(即cursor)被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。

简单的迭代演示:

  1.  
    redis 127.0.0.1:6379> scan 0
  2.  
    1) "17"
  3.  
    2) 1) "key:12"
  4.  
    2) "key:8"
  5.  
    3) "key:4"
  6.  
    4) "key:14"
  7.  
    5) "key:16"
  8.  
    6) "key:17"
  9.  
    7) "key:15"
  10.  
    8) "key:10"
  11.  
    9) "key:3"
  12.  
    10) "key:7"
  13.  
    11) "key:1"
  14.  
    redis 127.0.0.1:6379> scan 17
  15.  
    1) "0"
  16.  
    2) 1) "key:5"
  17.  
    2) "key:18"
  18.  
    3) "key:0"
  19.  
    4) "key:2"
  20.  
    5) "key:19"
  21.  
    6) "key:13"
  22.  
    7) "key:6"
  23.  
    8) "key:9"
  24.  
    9) "key:11"

在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。第二次迭代使用的是第一次迭代时返回的游标 17 ,作为新的迭代参数 。

显而易见,SCAN命令的返回值 是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则又是一个数组, 这个数组中包含了所有被迭代的元素。

注意:返回的游标不一定是递增的,可能后一次返回的游标比前一次的小。

在第二次调用 SCAN 命令时, 命令返回了游标 0 , 这表示迭代已经结束, 整个数据集已经被完整遍历过了。

full iteration :以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历。

SCAN增量式迭代命令并不保证每次执行都返回某个给定数量的元素,甚至可能会返回零个元素, 但只要命令返回的游标不是 0 , 应用程序就不应该将迭代视作结束。

不过命令返回的元素数量总是符合一定规则的, 对于一个大数据集来说, 增量式迭代命令每次最多可能会返回数十个元素;而对于一个足够小的数据集来说,可能会一次迭代返回所有的key

COUNT选项

对于增量式迭代命令不保证每次迭代所返回的元素数量,我们可以使用COUNT选项, 对命令的行为进行一定程度上的调整。COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。使用COUNT 选项对于对增量式迭代命令相当于一种提示, 大多数情况下这种提示都比较有效的控制了返回值的数量。

注意:COUNT选项并不能严格控制返回的key数量,只能说是一个大致的约束。并非每次迭代都要使用相同的 COUNT 值,用户可以在每次迭代中按自己的需要随意改变 COUNT 值, 只要记得将上次迭代返回的游标用到下次迭代里面就可以了。

 

MATCH 选项

类似于KEYS 命令,增量式迭代命令通过给定 MATCH 参数的方式实现了通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素。

MATCH 选项对元素的模式匹配工作是在命令从数据集中取出元素后和向客户端返回元素前的这段时间内进行的, 所以如果被迭代的数据集中只有少量元素和模式相匹配, 那么迭代命令或许会在多次执行中都不返回任何元素。

以下是这种情况的一个例子:

  1.  
    redis 127.0.0.1:6379> scan 0 MATCH *11*
  2.  
    1) "288"
  3.  
    2) 1) "key:911"
  4.  
    redis 127.0.0.1:6379> scan 288 MATCH *11*
  5.  
    1) "224"
  6.  
    2) (empty list or set)
  7.  
    redis 127.0.0.1:6379> scan 224 MATCH *11*
  8.  
    1) "80"
  9.  
    2) (empty list or set)
  10.  
    redis 127.0.0.1:6379> scan 80 MATCH *11*
  11.  
    1) "176"
  12.  
    2) (empty list or set)
  13.  
    redis 127.0.0.1:6379> scan 176 MATCH *11* COUNT 1000
  14.  
    1) "0"
  15.  
    2) 1) "key:611"
  16.  
    2) "key:711"
  17.  
    3) "key:118"
  18.  
    4) "key:117"
  19.  
    5) "key:311"
  20.  
    6) "key:112"
  21.  
    7) "key:111"
  22.  
    8) "key:110"
  23.  
    9) "key:113"
  24.  
    10) "key:211"
  25.  
    11) "key:411"
  26.  
    12) "key:115"
  27.  
    13) "key:116"
  28.  
    14) "key:114"
  29.  
    15) "key:119"
  30.  
    16) "key:811"
  31.  
    17) "key:511"
  32.  
    18) "key:11"
  33.  
    redis 127.0.0.1:6379>

可以看出,以上的大部分迭代都不返回任何元素。在最后一次迭代, 我们通过将 COUNT 选项的参数设置为 1000 , 强制命令为本次迭代扫描更多元素, 从而使得命令返回的元素也变多了。

 
基于SCAN的这种安全性,建议大家在生产环境都使用SCAN命令来代替KEYS,不过注意,该命令是在2.8.0版本之后加入的,如果你的Redis低于这个版本,则需要升级Redis。
 
 
下面用PHP代码演示SCAN命令的使用:
 
  1.  
    <?php
  2.  
     
  3.  
    $redis = new Redis();
  4.  
     
  5.  
    $redis->connect('127.0.0.1', 6379);
  6.  
     
  7.  
     
  8.  
    /* 设置遍历的特性为不重复查找,该情况下扩展只会scan一次,所以可能会返回空集合 */
  9.  
    $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_NORETRY);
  10.  
     
  11.  
    $it = NULL;
  12.  
    $pattern = '*';
  13.  
    $count = 50; // 每次遍历50条,注意是遍历50条,遍历出来的50条key还要去匹配你的模式,所以并不等于就能够取出50条key
  14.  
     
  15.  
    do
  16.  
    {
  17.  
    $keysArr = $redis->scan($it, $pattern, $count);
  18.  
     
  19.  
    if ($keysArr)
  20.  
    {
  21.  
    foreach ($keysArr as $key)
  22.  
    {
  23.  
    echo $key . "\n";
  24.  
    }
  25.  
    }
  26.  
     
  27.  
    } while ($it > 0); //每次调用 Scan会自动改变 $it 值,当$it = 0时 这次遍历结束 退出循环
  28.  
     
  29.  
     
  30.  
    echo '---------------------------------------------------------------------------------' . "\n";
  31.  
     
  32.  
     
  33.  
    /* 设置扩展在一次scan没有查找出记录时 进行重复的scan 直到查询出结果或者遍历结束为止 */
  34.  
    $redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);
  35.  
     
  36.  
    $it = NULL;
  37.  
    $pattern = '*';
  38.  
    $count = 50; // 每次遍历50条,注意是遍历50条,遍历出来的50条key还要去匹配你的模式,所以并不等于就能够取出50条key
  39.  
     
  40.  
    //这种用法下我们只需要简单判断返回结果是否为空即可, 如果为空说明遍历结束
  41.  
    while ($keysArr = $redis->scan($it, $pattern, $count))
  42.  
    {
  43.  
    foreach ($keysArr as $key)
  44.  
    {
  45.  
    echo $key . "\n";
  46.  
    }
  47.  
    }
 
执行结果:

  1.  
    [root@localhost php]# /usr/local/php/bin/php scan.php
  2.  
    bm
  3.  
    bm2
  4.  
    h1
  5.  
    name
  6.  
    bit
  7.  
    bm1
  8.  
    places
  9.  
    cities
  10.  
    hhl
  11.  
    ---------------------------------------------------------------------------------
  12.  
    bm
  13.  
    bm2
  14.  
    h1
  15.  
    name
  16.  
    bit
  17.  
    bm1
  18.  
    places
  19.  
    cities
  20.  
    hhl
 
注意:如果php执行报错 请升级到较新版本的Redis扩展
 
更多请参考:
 
 
 

Redis遍历所有key的两个命令 -- KEYS 和 SCAN的更多相关文章

  1. Redis系列之key操作命令与Redis中的事务详解(六)

    序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...

  2. 如何解决Redis中的key过期问题

    最近我们在Redis集群中发现了一个有趣的问题.在花费大量时间进行调试和测试后,通过更改key过期,我们可以将某些集群中的Redis内存使用量减少25%. Twitter内部运行着多个缓存服务.其中一 ...

  3. Redis批量删除key的小技巧,你知道吗?

    在使用redis的过程中,经常会遇到要批量删除某种规则的key,但是redis提供了批量查询一类key的命令keys或scan,没有提供批量删除某种规则key的命令,怎么办?看完本文即可,哈哈. 本文 ...

  4. redis的hash, list, set类型相关命令

    hash相关命令: 1. hset HSET key field value 将哈希表key中的域field的值设为value.如果key不存在,一个新的哈希表被创建并进行hset操作.如果域fiel ...

  5. Redis进阶实践之十五 Redis-cli命令行工具使用详解第二部分(结束)

    一.介绍           今天继续redis-cli使用的介绍,上一篇文章写了一部分,写到第9个小节,今天就来完成第二部分.话不多说,开始我们今天的讲解.如果要想看第一篇文章,地址如下:http: ...

  6. Redis实战 - 4.Key

    Redis 键(key) Redis 键命令用于管理 redis 的键. DEL key 该命令用于在 key 存在时删除 key. 127.0.0.1:6379> set w3ckey red ...

  7. redis 中的key值过期后,触发通知事件

    1.创建springboot工程,创建监听类 maven配置 <dependencies> <dependency> <groupId>org.springfram ...

  8. Redis进阶实践之十四 Redis-cli命令行工具使用详解

    转载来源:http://www.cnblogs.com/PatrickLiu/p/8508975.html 一.介绍 redis学了有一段时间了,以前都是看视频,看教程,很少看官方的东西.现在redi ...

  9. redis push/pop(List)的17条命令

    一.Blpop 命令移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止.redis 127.0.0.1:6379> BLPOP LIST1 LIST2 .. ...

随机推荐

  1. 水晶报表导出完美EXCEL表格

    水晶报表自带的导出Excel不太完美(这一点与SQL的SSRS相比就差太远了),导出的文件没有网格线,而且非常容易出现跨行跨列的现象,要做一个符合要求的报表还真要花不少的时间与精力去调试. 下面我简单 ...

  2. Texygen文本生成,交大计算机系14级的朱耀明

    文本生成哪家强?上交大提出基准测试新平台 Texygen 2018-02-12 13:11测评 新智元报道 来源:arxiv 编译:Marvin [新智元导读]上海交通大学.伦敦大学学院朱耀明, 卢思 ...

  3. 数据挖掘算法之聚类分析(二)canopy算法

    canopy是聚类算法的一种实现 它是一种快速,简单,但是不太准确的聚类算法 canopy通过两个人为确定的阈值t1,t2来对数据进行计算,可以达到将一堆混乱的数据分类成有一定规则的n个数据堆 由于c ...

  4. Spark Streaming揭秘 Day2-五大核心特征

    Spark Streaming揭秘 Day2 五大核心特征 引子 书接上回,Streaming更像Spark上的一个应用程序,会有多个Job的配合,是最复杂的Spark应用程序.让我们先从特征角度进行 ...

  5. [TypeScript] Custom data structures in TypeScript with iterators

    We usually think of types as something that can define a single layer of an object: with an interfac ...

  6. Android Exception 17(database or disk is full)

    android.database.sqlite.SQLiteFullException: database or disk is full delete some app,or clear cache

  7. android:ellipsize实现跑马灯效果总结

    最近无意间看到了涉及到跑马灯效果的代码,于是在网上查阅了很多资料,在这里对自己看的一些文章进行一下总结,顺便加上自己的一些体会. 让我们一步步逐渐向下. 首先我们要实现走马灯这样一个效果,通常来说都是 ...

  8. java集合类简单思维导图

  9. oracle10g安装,卸载

    一.安装 1.因为oracle的特殊性,笔者选择通过虚拟机安装windows7旗舰版安装数据库,大家的系统假设是windows xp.windows 7,windows 8能够直接安装,windows ...

  10. 执行”spark-shell –master yarn –deploy-mode client”,虚拟内存大小溢出,报错

    在Hadoop 2.7.2集群下执行如下命令: spark-shell  --master yarn --deploy-mode client 爆出下面的错误: org.apache.spark.Sp ...