1. keys
格式:keys pattern
功能:查找所有符合给定模式 pattern 的 key,pattern 为正则表达式。
说明:KEYS 的速度非常快,但在一个大的数据库中使用它可能会阻塞当前服务器的服务。所以生产环境中一般不使用该命令,而使用 scan 命令代替。
2. exists
格式:exists key
功能:检查给定 key 是否存在。
说明:若 key 存在,返回 1 ,否则返回 0 。
3. del
格式:del key [key …]
功能:删除给定的一个或多个 key 。不存在的 key 会被忽略。
说明:返回被删除 key 的数量。
4. rename
格式:rename key newkey
功能:将 key 改名为 newkey。
说明:当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。当 newkey 已经存在时, RENAME 命令将覆盖旧值。改名成功时提示 OK ,失败时候返回一个错误。
5. move
格式:move key dbID
功能:将当前数据库的 key 移动到给定的数据库 db 当中。
说明:如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果。移动成功返回 1,失败则返回 0 。
6. type
格式:type key
功能:返回 key 所储存的值的类型。
说明:返回值有以下六种
- none (key 不存在)
- string (字符串)
- list (列表)
- set (集合)
- zset (有序集)
- hash (哈希表)
7. expire 与 pexpire
格式:expire key seconds
功能:为给定 key 设置生存时间。当 key 过期时(生存时间为 0),它会被自动删除。expire 的时间单位为秒,pexpire 的时间单位为毫秒。在 Redis 中,带有生存时间的 key 被称为“易失的”(volatile)。
说明:生存时间设置成功返回 1。若 key 不存在时返回 0 。rename 操作不会改变 key 的生存时间。
8. ttl 与 pttl
格式:ttl key
功能:TTL, time to live,返回给定 key 的剩余生存时间。
说明:其返回值存在三种可能:
- 当 key 不存在时,返回 -2 。
- 当 key 存在但没有设置剩余生存时间时,返回 -1 。
- 否则,返回 key 的剩余生存时间。ttl 命令返回的时间单位为秒,而 pttl 命令返回的时间单位为毫秒。
9. persist
格式:persist key
功能:去除给定 key 的生存时间,将这个 key 从“易失的”转换成“持久的”。
说明:当生存时间移除成功时,返回 1;若 key 不存在或 key 没有设置生存时间,则返回 0。
10. randomkey
格式:randomkey
功能:从当前数据库中随机返回(不删除)一个 key。
说明:当数据库不为空时,返回一个 key。当数据库为空时,返回 nil。开发中也常用此命令判断数据库是否为空。
11. scan
格式:scan cursor [MATCH pattern] [COUNT count] [TYPE type]
功能:用于迭代数据库中的数据库键。其各个选项的意义为:
- cursor:本次迭代开始的游标。
- pattern :本次迭代要匹配的 key 的模式;keys 和 pattern 命令支持 3 个通配符:
- *:通配任意多个字符
- ?:通配单个字符
- [ ]:通配括号内的某一个字符
- count :本次迭代要从数据集里返回多少元素,默认值为 10 。
- type:本次迭代要返回的 value 的类型,默认为所有类型。
说明:
- 使用间断的、负数、超出范围或者其他非正常的游标来执行增量式迭代不会造成服务器崩溃。
- 当数据量很大时,count 的数量的指定可能会不起作用,Redis 会自动调整每次的遍历数目。
- 由于 scan 命令每次执行都只会返回少量元素,所以该命令可以用于生产环境,而不会出现像 KEYS 命令带来的服务器阻塞问题。
- 增量式迭代命令所使用的算法只保证在数据集的大小有界的情况下迭代才会停止,换句话说,如果被迭代数据集的大小不断地增长的话,增量式迭代命令可能永远也无法完成一次完整迭代。即当一个数据集不断地变大时,想要访问这个数据集中的所有元素就需要做越来越多的工作, 能否结束一个迭代取决于用户执行迭代的速度是否比数据集增长的速度更快。
实验:
# 先使用命令生成1万个keyfor i in {1..10000}; do redis-cli SET user:$i "value_$i" >/dev/null; done# 测试key的个数redis-cli DBSIZE体验 cursor
127.0.0.1:6379> scan 01) "2560"2) 1) "user:3497" 2) "user:8149" 3) "user:6340" 4) "user:2036" 5) "user:4305" 6) "user:1322" 7) "user:6208" 8) "user:4851" 9) "user:9411" 10) "user:2960"127.0.0.1:6379> scan 25601) "256"2) 1) "user:9374" 2) "user:1061" 3) "user:6207" 4) "user:1179" 5) "user:1121" 6) "user:3139" 7) "user:1165" 8) "user:4551" 9) "user:8848" 10) "user:721"127.0.0.1:6379> scan 2561) "7424"2) 1) "user:7" 2) "user:9137" 3) "user:6924" 4) "user:4645" 5) "user:459" 6) "user:236" 7) "user:8500" 8) "user:5473" 9) "user:9021" 10) "user:2615"# 一直重复下去,直到出现:1) "0"使用 count
127.0.0.1:6379> scan 0 count 101) "2560"2) 1) "user:3497" 2) "user:8149" 3) "user:6340" 4) "user:2036" 5) "user:4305" 6) "user:1322" 7) "user:6208" 8) "user:4851" 9) "user:9411" 10) "user:2960"# 返回了10个key# 使用scan 0 count 9000 大概返回9000个key# 注意:COUNT只是Hint(建议值),不是严格保证。# Redis官方文档原话:COUNT is just a hint.Redis 底层有一个 hash table 用来管理所有的 key,当出现大量 key 的增长的时候,hash table 会进行扩容,可能会导致 scan 出现漏扫或者重复扫描的情况。
- Redis 的 key 实际存储在一个 hash table 里:
bucket[0] -> 一些 key
bucket[1] -> 一些 key
bucket[2] -> 一些 key
…
每个 key 会通过 hash 算法算一个位置:index = hash(key) % bucket_size
所以:每个 key 会被放进对应的 bucket index 的位置 - 渐进式 rehash
Redis 扩容/缩容不是一次性完成,而是:old table → new table(逐步迁移)
期间同时存在:ht[0](旧表)和 ht[1](新表) - SCAN 会同时扫描两个 table
- key 被搬迁(导致重复)
key 从:ht[0] → ht[1],如果 SCAN 已扫描 ht[0],后来该 key 被搬到 ht[1],又被 scan 到一次,就会出现重复扫描。 - bucket 重映射(导致漏扫)
rehash 会改变:bucket index 的分布,导致某些 bucket 在 scan 路径中被“错过”,这就会导致漏扫。
12. 其他
另外还有 3 个 scan 命令用于对三种类型的 value 进行遍历。
hscan:属于 Hash 型 Value 操作命令集合,用于遍历当前 db 中指定 Hash 表的所有 field-value 对。
sscan:属于 Set 型 Value 操作命令集合,用于遍历当前 db 中指定 set 集合的所有元素。
zscan:属于 ZSet 型 Value 操作命令集合,用于遍历当前 db 中指定有序集合的所有元素(数值与元素值)