刷新有效期,Redis中没有批量删除特定前缀key的指

2020-01-04 22:39栏目:美高梅网上游戏
TAG:

前言

Keys

新增加了KEYS,MIGRATE,MOVE,OBJECT,PERSIST,PEXPIRE,PEXPIREAT,PTTL,RANDOMKEY,RENAME,RENAMENX命令的翻译

以下为本人学习Redis的备忘录,记录了大部分常用命令

还在用keys命令模糊匹配删除数据吗?这就是一颗随时爆炸的炸弹!

DEL key [key... ]

可用版本: >=1.0.0
时间复杂度:
O(N),N是删除的keys的数量。
删除单个list,set,sorted set 或者hash类型的key时,时间复杂度是O(M),M是其数据集合的元素个数。
删除单个字符串类型的key时,时间复杂度是O(1)。

删除指定的一个或者多个键,不存在的键被忽略

返回值:
删除key的数量。


实例

  • 删除单个key
redis dev.baiduwo.com:6379[4]> set name "wuhuangdi"
OK
redis dev.baiduwo.com:6379[4]> get name
"wuhuangdi"
redis dev.baiduwo.com:6379[4]> del name
redis dev.baiduwo.com:6379[4]> del "name"
(integer) 1
redis dev.baiduwo.com:6379[4]> get name
(nil)
redis dev.baiduwo.com:6379[4]>
  • 删除多个key
redis dev.baiduwo.com:6379[4]> mset name "wuhuangdi" age 30
OK
redis dev.baiduwo.com:6379[4]> mget name age
1) "wuhuangdi"
2) "30"
redis dev.baiduwo.com:6379[4]> del name age
(integer) 2
redis dev.baiduwo.com:6379[4]>
  • 删除一个不存在的key
    操作成功,返回值是0.
redis dev.baiduwo.com:6379[4]> get "name"
(nil)
redis dev.baiduwo.com:6379[4]> del name
(integer) 0
redis dev.baiduwo.com:6379[4]>
  • 删除既有存在又有不存在的key
redis dev.baiduwo.com:6379[4]> mset name "wuhuangdi" age 30
OK
redis dev.baiduwo.com:6379[4]> mget name age
1) "wuhuangdi"
2) "30"
redis dev.baiduwo.com:6379[4]> del name age nickname
(integer) 2
redis dev.baiduwo.com:6379[4]>

1.客户端连接redis服务端:

Redis中没有批量删除特定前缀key的指令,但我们往往需要根据前缀来删除,那么究竟该怎么做呢?可能你一通搜索后会得到下边的答案

DUMP key

可用版本: >=2.6.0
时间复杂度:
查找key的时间复杂度是O(1)
序列化数据时间复杂度是O(NM),其中N是构成值得redis对象的数量,M是平均大小。
对于小的字符串类型,时间复杂度是O(1)+O(1
M),M是字符串长度,M越小,越接近O(1)

序列化的值按照给定的格式,并且返回给用户,可以使用RESTORE命令恢复到Redis系统。
序列化的格式不是标准的,然而有一下几个语义特征:

  • 它包含一个64位校验和,用来检测错误,RESTORE命令在恢复反序列化之前先检查校验和
  • 值得编码方式和RDB是保持一致的
  • RDB的版本会被编码到序列化值当中,所以不同的Redis版本因为RDB格式不兼容的时候,系统会拒绝执行反序列化命令。
    反序列化值不包含任何过期的信息,为了获取值得生命过期时间,应该使用PTTL命令。
    如果key不存在,redis返回一个nil。

返回值
序列化之后的值


实例

  • DUMP一个存在的key
redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> get name
"wuhuangdi"
redis dev.baiduwo.com:6379[4]> dump name
"x00twuhuangdix06x00xdbx11xc5`.n-~"
redis dev.baiduwo.com:6379[4]> get name
"wuhuangdi"
redis dev.baiduwo.com:6379[4]>
  • ===启动Redis服务端
  • redis-server /yourpath/redis.conf
  • ===启动Redis命令行客户端
  • 建立长连接:redis-cli -h 127.0.0.1 -p 6379
  • 若省略参数则将使用默认值连接服务器:redis-cli
  • 如果在后面直接跟其它命令,则为临时连接,返回后即关闭:redis-cli get keyname
  • 关闭服务端:redis-cli shutdown (可选参数:nosave、save)
redis-cli --raw keys "ops-coffee-*" | xargs redis-cli del

EXISTS key [key ...]

可用版本: >=1.0.0.
时间复杂度: O(1)
如果key存在直接返回。
从Redis 3.0.3版本以后,支持了多个key而不是只有一个。所以系统返回的是存在的key的总数数量,返回1或者0是仅仅针对单个key的场景下适用的,所以命令是完全向后兼容的。
使用的时候应该注意到,如果相同存在的key在参数中被多次提交的时候,系统也会计算多次。所以如果某个key存在,EXISTS命令返回是2.
返回值
返回数字,详情如下:

  • key存在返回 1。
  • 可以不存在返回 0。
    redis 3.0.3之后该命令支持多个key,返回的值也是不同的:
  • 返回在参数中指定所有存在的key总数,key在参数中多次提交,如果key存在,也会累计计算。

实例

  • 检查单个key可以是否存在
redis dev.baiduwo.com:6379[4]> exists name
(integer) 1
redis dev.baiduwo.com:6379[4]> exists name1
(integer) 0
redis dev.baiduwo.com:6379[4]>
  • 检查多个key是否存在
redis dev.baiduwo.com:6379[4]> exists name age name1
(integer) 2
redis dev.baiduwo.com:6379[4]>
  • 检查多个key是否存在(key有重复提交)
redis dev.baiduwo.com:6379[4]> exists name age name
(integer) 3
redis dev.baiduwo.com:6379[4]>

2.全局命令(按TAB键可自动补齐命令,多次按TAB可切换)所有命令名不区分大小写

直接在linux下通过redis的keys命令匹配到所有的key,然后调用系统命令xargs来删除,看似非常完美,实则风险巨大

EXPIRE key seconds

可用版本: >=1.0.0
时间复杂度: O(1)

  1. 给key设定有效期,当有效期过期的时候,系统会自动删除这个key。在Redis中,带有有效期的key被称为vlolatile.
  2. 有效期只能通过DEL,SET,GETSET等存储类的命令删除或者覆盖,才能清除。
  3. 那就意味着,所有修改值得操作,而不是使用一个新的key的值代替它的话,key的有效期不会改变。例如,INCR是增加值,对一个list执行LPUSH命令,或者对一个hash执行HSET等所有操作是不会改变其key的有效期。
  4. key的有效期是可以清除的,使用PERSIST命令让key成为持久化的key。
  5. 如果key被RENAME命令重命名了,旧的key的有效期会应用到新的key上。
  6. 如果key被RENAME命令覆盖了,例如这么一种情况,Key_A因为执行了 RENAME Key_B Key_A被覆盖了,不管Key_A是否之前有有效期,Key_A都会继承Key_B的所有特性。

*刷新有效期
调用命令带有参数的EXPIRE能够刷新key的有效期,对于很多应用程序是非常有用的。
Redis 2.1.3版本之前的差别
在2.1.3版本之前,修改一个具有有效期的key会导致整个key删除,这样处理的原因是受到复制层的限制,不过现在修复了。

返回值
返回数字,详细如下:

  • 设置成功返回 1.
  • 如果key不存在或者有效期设置失败,返回 0.

实例

  • 设置有效期
redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> set name1 ches
OK
redis dev.baiduwo.com:6379[4]> expire name 100
(integer) 1
redis dev.baiduwo.com:6379[4]> expire name1 500
(integer) 1
redis dev.baiduwo.com:6379[4]> ttl name
(integer) 92
redis dev.baiduwo.com:6379[4]> ttl name1
(integer) 493
redis dev.baiduwo.com:6379[4]> rename name name1
OK
redis dev.baiduwo.com:6379[4]> ttl name
(integer) -2
redis dev.baiduwo.com:6379[4]> ttl name1
(integer) 70

模式:导航会话
假设你的一个web服务,而且你对你的用户最近访问的N个页面感兴趣,相邻的页面阅读时间不超过60s。我们认为这些页面的集合就是你的用户的导航会话,其中里面包含着用户正在寻找感兴趣的商品的信息,所以你可以推荐相关的商品。
你很容易在redis使用下面的策略完成:每次用户完成阅读一个页面的时候执行以下命令:

MULTI
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
EXEC

如果用户60秒内没有继续阅读,那么用户的导航记录被删除,当用户继续阅读页面不超过60s的时候,导航记录才会继续记录。

  • keys * 遍历并获得所有key(可指定匹配模式字符串),含大量key时不要使用
  • dbsize 返回键总数变量的值
  • exists key 检查key是否存在,存在返回1,否则返回0
  • del key [key …] 删除任意值类型的key,可一次性删除多个,返回删除个数
  • ttl key 查看key的过期时间,返回>=0表示过期时间,返回-1表示未设置,返回-2表示不存在的key
  • type key 返回key的结构类型,不存在返回none
  • object encoding key 返回key的值的内部编码类型
  • SELECT dbindex 选择当前Redis实例中指定编号的数据库(不建议使用多数据库,因为Redis为单线程模型,多数据库将使用的是同一个CPU,应该使用多个Redis实例),Redis的分布式实现Redis Cluster只允许使用0号数据库

  •  FLUSHDB 清除当前数据库(键值对多时,会阻塞,且是危险的命令,可用rename-command配置来规避该危险)

  • FLUSHALL 清除所有数据库

  • ===

因为Redis的单线程服务模式,命令keys会阻塞正常的业务请求,如果你一次keys匹配的数量过多或者在del的时候遇到大key,都会直接导致业务的不可用,甚至造成redis宕机的风险

附录:Redis有效期

  • 带有效期的key
    正常情况,redis创建key的时候,这个key是永久存在的,除非人为显示的使用DEL类似的命令删除了。
    EXPIRE相关的命令都能更新key的有效期,需要额外的内存,一旦key被设置了有效期,redis必须能够在设定的时间之后,能够移除key。
    可以使用EXPIRE更新key的有效期,使用PERSIST命令删除key的有效期限制。
  • 有效期精度
    redis 2.4有效期不是很精确,精确度在0-1秒之间,而2.6版本之后,精确度能达到0-1毫秒。
  • 有效期的key持久化
    key的有效期信息是采用绝对的Unix时间戳存储的(2.6版本或者更高是毫秒级别的),这就意味着,即使redis实例不是激活,时间也会在流逝。
    所以要有效期机制工作的非常好,要求系统时间保证稳定,如果你在两台时钟差异很大的电脑上移动,最后有趣的事情发生了(例如所有的key加载的时候都过期了)
    例如,如果你设置一个key有效期是1000秒,然后设置你的电脑时间是未来的2000秒,即使运行的实例总是检查系统的时钟,那么这个key也会理解过期。
  • Redis怎样让key到期
    redis处理key的过期,采取两种方式:被动的和主动的方式。
    当有客户端访问这个key,如果这个key过期了,那么直接主动让这个key失效。
    当然,这种方式对于从来不被访问的key是不够的,不管怎么样,过期的key必须要处理,所以redis会定时随机在有有效期的key中测试是否过期,所有过期的key会被删除。
    redis每秒做10次,具体工作如下:
  1. 从有效期的key中随机抽取20个key。
  2. 删除所有过期的key。
  3. 如果25%的key是过期的,再重复执行第1步骤。
    这采用的是普通的概率算法,基本可以假设这个样本能代表整个key的空间,而且我们会继续淘汰key,直到失效的key低于25%。
    这意味着,在任何给定的时刻,使用内存的最大数量的key的使用达到最大,等于每秒1/4的写入操作的最大量。
  • 在复制和AOF文件中,有效期怎么处理的
    为了不牺牲一致性,保证正确的结果,如果一个key失效了,会在AOF文件里写入一个DEL的操作命令。相关的从实例都能获得。有效期的处理都是集中在主实例处理的,所以不会发生一致性的错误。
    无论如何,从实例不能独立执行key的有效期操作(除非等待主实例的删除命令),他们会坚持把过期的key的完整状态保持在数据中,当从实例选举出主实例的时候,主实例才能独立的执行key的有效期工作。

所以我们在生产环境中应当避免使用上边的方法,那有什么优雅的方法来解决呢?SCAN!

EXPIREAT key timestamp

可用版本: >=1.2.0
时间复杂度: O(1)
EXPIREAT和EXPIRE作用是一样的,不同的地方是,EXPIREAT接受的参数是绝对的Unix时间戳。
背景
EXPIREAT引进是为了将相对的时间转换成绝对时间,因为AOF持久化模式使用的是绝对时间,当然,它也可以直接用来设置key的某一个指定的时刻的有效期。
返回值
返回数字,详情如下:

  • 设置成功,返回 1.
  • 如果key不存在,或者设置失败,返回 0.

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> expire name 100
(integer) 1
redis dev.baiduwo.com:6379[4]> expireat name 1461446209
(integer) 1
redis dev.baiduwo.com:6379[4]>
  • get key 读取key对应的value
  • mget key [key …] 批量读取
  • mset key value [key value ...] 批量添加、更新
  • set key value [EX seconds] [PX milliseconds] [NX|XX] 添加、更新key value,EX、PX表示过期时间,NX表示只添加未存在的key,XX表示只更新已存在的key,成功返回OK,失败nil
  • setex key seconds value 添加、更新key value,并设置过期时间
  • setnx key value 只添加未存在的key value
  • ===
  • incr key 对key的值自增1,返回自增后的值(若key不存在,则先添加,然后自增),若值为非数字则返回错误
  • incrby key increment 自增指定数值,increment可以是负数
  • incrbyfloat key increment 自增指定浮点数值,increment可以是负数(对于浮点数的value,只能用该命令)
  • decr key 自减
  • decrby key increment 自减指定数值,increment可以是负数
  • ===
  • setbit key offset value
  • setrange key offset value 把字符串索引offset处字符替换为指定value
  • getrange key start end 获取指定索引区域的字符
  • append key value 向字符串尾部追加值,返回追加后的字符串长度
  • strlen key 返回字符串长度
  • getset key value 返回旧值,并设置新值
  • ===

SCAN介绍及使用

KEYS pattern

可用版本: >=1.0.0
时间复杂度:
O(N),N是数据库所有key的数量,前提是假设数据库在给定的pattern长度是有限的。
返回所有给定能匹配pattern的key
时间复杂度基本是O(N),而且这个时间变动可能性很低,在一个低配的个人电脑,redis 40毫秒能扫描100万key。
警告: 如果在生产环境使用keys命令要尤其小心,在一个数据量比较大的数据库中,会极其影响性能,这个命令用来debug或者特定操作使用的,例如调整key的命名空间。不要在你正常的应用代码中使用这个命令,如果你在数据库里寻找key的子集,建议使用SCAN或者sets类似命令。
支持类似的模式:

  • h?llo匹配hello,hallo和hxllo
  • h*llo匹配 hllo和heeeello
  • h[ae]llo匹配hello和hallo,不匹配hillo
  • h[^e]llo匹配hallo,hbllo等等,除了hello
  • h[a-b]llo匹配hallo和hbllo
    如果匹配特殊字符,使用转义。

返回值
返回匹配给定pattern的列表。


实例

redis dev.baiduwo.com:6379[4]> mset name wuhuangdi nbme ddd ncme 223
OK
redis dev.baiduwo.com:6379[4]> keys name*
1) "name"
redis dev.baiduwo.com:6379[4]> keys n?me
1) "ncme"
2) "nbme"
3) "name"
redis dev.baiduwo.com:6379[4]>

RENAME key newkey 重命名键,若newkey已存在,则会被覆盖

Redis从2.8版本开始支持scan命令,SCAN命令的基本用法如下:

MIGRATE host port key|"" destination-db timeout [COPY]...

可用版本: >2.6.0
时间复杂度: 这个命令实际上在源实例上执行了DUMP+DEL命令,而在目标实例上执行了RESTORE命令,去查看这些命令的复杂度可知,它的时间复杂度是O(N).

一个key从源实例传输到目标实例上是一个原子操作,key数据会在源实例能成功删除,而且能保证出现在目标实例上。
当需要迁移key的时候,这个命令是原子的,会同时阻塞两个实例,直到迁移成功或者超时。3.2版本以上,批量的key以一个空字符串作为key来通过管道实现迁移。
源实例会使用DUMP序列化要迁移的key,然后远程连接到目标实例,目标实例使用RESTORE命令反序列化key,并且添加到数据库中,并且返回OK,源实例就使用DEL命令删除当前数据的key。
timeout表示通讯的最大间隔时间,单位是毫秒。这意味着操作不需要在指定的timeout内完成,而是数据传输不能超时。
MIGRATE会在给定的timeout时间完成I/O操作,当在传输的时候发生I/O错误或者发生数据传输超时,那么迁移的操作会被取消,并且返回IOERROR错误,下面这两种情况是可能发生的:

  • 迁移的key可能存在两个实例上
  • 迁移的key可能只存在源实例上
    当发生超时的时候,key不可能丢失。当客户端执行MIGRATE命令的时候,如果发生超时错误,应该检查目标实例key是否存在,当发生错误的时候,MIGRATE肯定能保证key仍然存在源实例上,除非相同的key已经存在目标实例上。
    如果迁移的时候key是缺失的,将返回NOKEY,这种情况是存在的,也许迁移的时候正好key过期了,NOKEY不是错误。
    Redis 3.0.6的 MIGRATE开始支持批量key迁移,而不用一次次的调用MIGRATE命令迁移,增加了不必要的系统成本。
    为了支持这个,KEYS参数是可选的,正常情况下key的参数被设置一个空字符串,实际上传输的key的名字是在后面KEYS参数指定的,例如:
    MIGRATE 192.168.1.34 6379 "" 0 5000 KEYS key1 key2 key3
    可选参数:
  • COPY - 当前实例不删除key。
  • REPLACE - 目标实例如果存在相同key,就直接替换
  • KEYS - 如果key的参数是空字符串,MIGRATE命令将迁移所有keys参数指定的key。
    COPY和REPLACE只在3.0版本才支持,KEYS是3.0.6版本。

返回值
返回字符串:如果迁移成功,返回OK,如果key不存在,返回NOKEY。

RENAMENX key newkey 只在newkey不存在时,重命名才会成功,否则返回0

SCAN cursor [MATCH pattern] [COUNT count]

MOVE key db

可用版本: >1.0.0
时间复杂度: O(1)
移动一个key从当前选择的数据库(查看SELECT)到指定的目标数据库。如果目标数据库存在相同的key,或者源数据库不存在key,这个命令将没有效果。所以因为这个原因,可以用MOVE当做锁


返回值
返回数字,详情如下:

  • 如果移动成功,返回 1.
  • 如果没有移动,返回 0.

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> move name 5
(integer) 1
redis dev.baiduwo.com:6379[4]> move name 5
(integer) 0
redis dev.baiduwo.com:6379[4]> move name1 5
(integer) 0
redis dev.baiduwo.com:6379[4]>

RANDOMKEY 返回一个随机的key

cursor: 游标,SCAN命令是一个基于游标的迭代器,SCAN命令每次被调用之后,都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为SCAN命令的游标参数,以此来延续之前的迭代过程,直到服务器向用户返回值为0的游标时,一次完整的遍历过程就结束了

OBJECT subcommand [arguments [arguments...]]

可用版本: >1.0.0
时间复杂度: 当前所有的实现的子命令都是O(1).
OBJECT命令允许你查看key的内部对象。去debug或者了解为了节约空间,key使用了特定的编码。当使用redis作为缓存的时候,你可以通过OBJECT命令来决定应用应该怎么配置key的淘汰策略。
OBJECT目前支持多种子命令:

  • OBJECT REFCOUNT <key> 返回指定key关联的值的数量,一般用来debug。
  • OBJECT ENCODING <key> 返回指定key关联的值的内部存储结构。
  • OBJECT IDLETIME <key> 返回key存取你以来的空余时间(没有读取,也没有写入),单位是秒.
    对象可以多种方式编码:
  • 字符串可以被编码为 raw (一般字符串)或 int (用字符串表示64位数字是为了节约空间)。
  • 列表可以编码为 ziplist或linkedlist 。 ziplist 是为节约大小较小的列表空间而作的特殊结构
  • 集合可以被编码为 intset或hashtable 。 intset 是只储存数字的小集合的特殊结构。
  • 哈希表可以编码为 zipmap或hashtable 。 zipmap 是小哈希表的特殊结构。
  • 有序集合可以被编码为 ziplist或skiplist 格式。 ziplist 用于表示小的有序集合,而 skiplist 则用于表示任何大小的有序集合。
    假如你做了一个什么操作让redis不能为了节省空间而使用编码,那么左右特定的编码会自动转换成一般编码。

返回值
不同的子命令有不同返回值:

  • refcount 和 idletime返回数字。
  • encoding返回相应编码类型。
    如果检查的key不存在,返回null。

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> object refcount name
(integer) 1
redis dev.baiduwo.com:6379[4]> object idltime name
(error) ERR Syntax error. Try OBJECT (refcount|encoding|idletime)
redis dev.baiduwo.com:6379[4]> object idletime name
(integer) 20
redis dev.baiduwo.com:6379[4]> object encoding name
"embstr"
redis dev.baiduwo.com:6379[4]> lpush namelist 1
(integer) 1
redis dev.baiduwo.com:6379[4]> lpush namelist 2
(integer) 2
redis dev.baiduwo.com:6379[4]> lpush namelist 2
(integer) 3
redis dev.baiduwo.com:6379[4]> obj
(error) ERR unknown command 'obj'
redis dev.baiduwo.com:6379[4]> object refcount namelist
(integer) 1
redis dev.baiduwo.com:6379[4]> object refcount namelist
(integer) 1
redis dev.baiduwo.com:6379[4]> object encoding namelist

下面这个例子当redis不在使用节约空间的编码,编码能自动转换。

redis dev.baiduwo.com:6379[4]> set age 100
OK
redis dev.baiduwo.com:6379[4]> object encoding age
"int"
redis dev.baiduwo.com:6379[4]> append age abc
(integer) 6
redis dev.baiduwo.com:6379[4]> object encoding age

===键过期设置

MATCH: 匹配规则,例如遍历以ops-coffee-开头的所有key可以写成ops-coffee-*,中间包含-coffee-的可以写成*-coffee-*

PERSIST key

可用版本: >=2.2.0
时间复杂度: O(1)
移除key的有效期,将一个key从临时状态转换成持久化状态。

返回值

  • 移除成功返回 1.
  • 如果key不存在或者操作失败,返回 0.

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> expire name 100
(integer) 1
redis dev.baiduwo.com:6379[4]> ttl name
(integer) 97
redis dev.baiduwo.com:6379[4]> persist name
(integer) 1
redis dev.baiduwo.com:6379[4]> ttl name
(integer) -1
  • 设置过期时间命令在redis内部最终都使用的是PEXPIREAT
  • Redis不支持二级数据结构内部元素的过期功能
  • SET key命令默认会清除过期时间!
  • SETEX key seconds value 是原子执行的,相当于set+expire组合,可减少一次网络请求

COUNT: COUNT选项的作用就是让用户告知迭代命令,在每次迭代中应该从数据集里返回多少元素,COUNT只是对增量式迭代命令的一种提示,并不代表真正返回的数量,例如你COUNT设置为2有可能会返回3个元素,但返回的元素数据会与COUNT设置的正相关,COUNT的默认值是10

PEXPIRE key milliseconds

可用版本: >=2.6.0
时间复杂度: O(1)
这个命令和EXPIRE是差不多的,参数支持的是毫秒,不是秒。


返回值

  • 设置成功返回 1.
  • key不存在或者失败返回 0.

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> pexpire name 3500
(integer) 1
redis dev.baiduwo.com:6379[4]> ttl name
(integer) 2
redis dev.baiduwo.com:6379[4]> ttl name
(integer) 0

EXPIRE key seconds 多少秒后过期,过期的key会被自动删除

以下是一个SCAN命令的迭代过程示例:

PEXPIREAT key milliseconds-timestamp

可用版本: >=2.6.0
时间复杂度: O(1)
PEXPIREAT命令和EXPIREAT的作用是一样的,不过PEXPIREAT过期的精度能精确到毫秒。


返回值

  • 设置成功返回 1.
  • key不存在或者失败返回 0.

实例
参见EXPIREAT

PEXPIRE key milliseconds

127.0.0.1:6379 scan 0 MATCH ops-coffee-* 1) "38"2) 1) "ops-coffee-25" 2) "ops-coffee-19" 3) "ops-coffee-29" 4) "ops-coffee-10" 5) "ops-coffee-23" 6) "ops-coffee-5" 7) "ops-coffee-14" 8) "ops-coffee-16" 9) "ops-coffee-11" 10) "ops-coffee-15" 11) "ops-coffee-7" 12) "ops-coffee-1"127.0.0.1:6379 scan 38 MATCH ops-coffee-* COUNT 10001) "0"2) 1) "ops-coffee-13" 2) "ops-coffee-9" 3) "ops-coffee-21" 4) "ops-coffee-6" 5) "ops-coffee-30" 6) "ops-coffee-20" 7) "ops-coffee-2" 8) "ops-coffee-12" 9) "ops-coffee-28" 10) "ops-coffee-3" 11) "ops-coffee-26" 12) "ops-coffee-4" 13) "ops-coffee-31" 14) "ops-coffee-8" 15) "ops-coffee-22" 16) "ops-coffee-27" 17) "ops-coffee-18" 18) "ops-coffee-24" 19) "ops-coffee-17"

PTTL key

可用版本: >=2.6.0
时间复杂度: O(1)
和TTL一样,返回的是具有有效期key的存活时间,不同的是,TTL返回的是以秒单位,PTTL返回的是毫秒为单位。
Redis 2.6以前的版本,如果key不存在或者key没有有效期,返回-1.
Redis 2.8开始返回错误改变了:

  • key不存在返回-2.
  • key存在但是没有有效期返回-1.

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> expire name 222
(integer) 1
redis dev.baiduwo.com:6379[4]> pttl name
(integer) 218192

EXPIREAT key timestamp 到达指定时间戳时过期(单位是秒)

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

RANDOMKEY

可用版本: >=1.0.0
时间复杂度: O(1)
从当前数据库返回一个随机的key。


返回值
返回随机的key,数据库为空返回nil。

PEXPIREAT key milliseconds-timestamp

上面这个例子的意思是扫描所有前缀为ops-coffee-的key

RENAME key newkey

可用版本: >=1.0.0
时间复杂度: O(1)
重命名key为newkey。
如果新的名称和旧的名称相同,或者key不存在,都会返回错误。
如果新的名称已经存在,将会覆盖。这个时候redis会间接执行del操作,所以如果删除的key的数据比较大,那么RENAME将是一个耗时的操作。


返回值
简单字符串


实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> rename name name1
OK
redis dev.baiduwo.com:6379[4]> get name1
"wuhuangdi"

TTL key 查看key的剩余过期时间(秒)

第一次迭代使用0作为游标,表示开始一次新的迭代,同时使用了MATCH匹配前缀为ops-coffee-的key,返回了游标值38以及遍历到的数据

RENAMENX key newkey

可用版本: >=1.0.0
时间复杂度: O(1)
如果新的名称不存在,key才会被重命名newkey,它返回的错误和RENAME是一样的。


返回值

  • 执行成功,返回 1。
  • 如果newkey已经存在,返回 0.

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> set name1 chs
OK
redis dev.baiduwo.com:6379[4]> renamenx name name1
(integer) 0
redis dev.baiduwo.com:6379[4]> renamenx name name3
(integer) 1

PTTL key 毫秒

第二次迭代使用的是第一次迭代时返回的游标,也即是命令回复第一个元素的值38,同时通过将COUNT选项的参数设置为1000,强制命令为本次迭代扫描更多元素

RESTORE key ttl serialized-value [REPLACE]

可用版本: >=2.6.0
时间复杂度:
创建一个key是O(1),反序列化值是O(NM),N是构建redis对象的数量,M是它们的平均大小。对于小字符串时间复杂度是O(1)+O(1M),M要比较小的时候,接近O(1)。可是对于sorted set时间复杂度是O(NMlong(N)),因为向sorted set插入一个值的时间复杂度是O(long(N)).

使用DUMP序列化得到的值,经过反序列化,可以创建键值对。
如果创建的时候没有指定有效期,ttl是0,那么只能指定有效期。
RESTORE命令执行后,如果key已经存在,将返回“Target key name is busy”错误,除非你使用REPLACE修改(Redis 3.0版本)
RESTORE会检查RDB的版本和校验和,如果不匹配,会返回错误。


返回值
如果成功返回“OK”,否则返回相应的错误


实例

redis dev.baiduwo.com:6379[4]> lpush name wuhuangdi chs aaa
(integer) 3
redis dev.baiduwo.com:6379[4]> get name
(error) WRONGTYPE Operation against a key holding the wrong kind of value
redis dev.baiduwo.com:6379[4]> dump name
"n  x00x00x00x14x00x00x00x03x00x00x03aaax05x03chsx05twuhuangdixffx06x00x99xccTxaex04xdb_x9e"
redis dev.baiduwo.com:6379[4]> del name
(integer) 1
redis dev.baiduwo.com:6379[4]> restore name1 0 "n  x00x00x00x14x00x00x00x03x00x00x03aaax05x03chsx05twuhuangdixffx06x00x99xccTxaex04xdb_x9e"
(error) BUSYKEY Target key name already exists.
redis dev.baiduwo.com:6379[4]> restore name_1 0 "n  x00x00x00x14x00x00x00x03x00x00x03aaax05x03chsx05twuhuangdixffx06x00x99xccTxaex04xdb_x9e"
OK
redis dev.baiduwo.com:6379[4]>

PERSIST key 清除过期时间

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

TTL key

可用版本: >=1.0.0
时间复杂度: O(1)
返回key剩下的有效时间。这个命令是的redis客户端具有检查给定的key还有多少有效时间的能力。

redis2.6或者之前的版本,如果key不存在,或者key没有有效期,返回-1.
redis2.8版本之后,发生变化:

  • 如果key不存在,返回 -2.
  • 如果key存在,但是没有有效期,返回 -1.
    跟PTTL命令返回的信息是一样的。

返回值
返回TTL的有效期,如果发生错误,返回负数。


实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> expire name 1000
(integer) 1
redis dev.baiduwo.com:6379[4]> ttl name
(integer) 998
redis dev.baiduwo.com:6379[4]>

3.迁移键

KEYS命令的时间复杂度为O(n),而SCAN命令会将遍历操作分解成m次时间复杂度为O(1)的操作来执行,从而解决使用keys命令遍历大量数据而导致服务器阻塞的情况,使用下边的指令可以达到优雅删除的目的:

TYPE key

可用版本: >=1.0.0
时间复杂度: O(1)
返回存储在redis中key的类型,返回类型有字符串,列表,集合,有序集合和哈希


返回值

  • key存在,返回key的类型
  • key不存在,返回none

实例

redis dev.baiduwo.com:6379[4]> set name wuhuangdi
OK
redis dev.baiduwo.com:6379[4]> lpush name1 wuhuangdi
(integer) 1
redis dev.baiduwo.com:6379[4]> sadd name2 wuhuangdi
(integer) 1
redis dev.baiduwo.com:6379[4]> type name
string
redis dev.baiduwo.com:6379[4]> type name1
list
redis dev.baiduwo.com:6379[4]> type name2
set
redis dev.baiduwo.com:6379[4]>

在源Redis实例的客户端上执行MIGRATE命令即可迁移,该命令是原子性的(组合了dump、restore、del命令),直接在源Redis实例和目标Redis实例直接传输,传输完成返回OK时,表示成功迁移,此时源Redis会根据MIGRATE指定的命令选项决定是否删除自身对应的key

redis-cli --scan --pattern "ops-coffee-*" | xargs -L 2000 redis-cli del

WAIT numslaves timeout(待续))

可用版本: >=3.0.0
时间复杂度: O(1)
在上一个写的命令未被指定数量的从服务器成功接收之前,这个命令会阻塞当前的客户端,如果在指定的时间内超时,指定数量的从服务器没有到达,该命令照样返回。

两种情况下,该命令总是返回从服务器的数量,一种是确实接收到了发送的命令,一种是超时了。
就是说:

  1. 如果WAIT返回后,所有之前当前连接的上下文发送的写命令保证被一定数量的从服务器收到。
  2. 如果这个命令是以事务的方式执行的,那么不会阻塞,而是当从服务器收到之前所有写命令的时候,尽快返回收到的数量。
  3. timeout为0意味着永远阻塞
  4. 从WAIT命令返回收到命令的从服务器数量之后,要么成功,要么失败。客户端应该检查返回的值的数目是否等于或者大于系统所需求的副本的数量。

一致性和阻塞
注意到的是WAIT不是让redis编程强一致性的存储。虽然同步复制是复制状态机器的一部分,但是不是唯一必要的一部分,无论怎么样,在Sentinel和Redis Cluster失效转移的时候,WAIT能改善生产环境的数据安全。
具体的说就是,如果一个写操作被传输到一个或者多个从服务器的时候,当主失效的时候更有意义(但是不能保证),我们将通过选举提拔,建立一个失效转移机制,一个从服务将接收写操作。Sentinel和Redis Cluster将尽可能在从服务器中选出最好的服务器。
尽管如此,同步复制到多个从服务器的时候,还是有可能丢失写操作。

实现细节
自从介绍了从服务的局部同步(PSYNC特性),Redis的从服务器异步ping主服务器,通过数据偏移去执行复制流。这个在多个方面是有用的:

  1. 探测从服务器的超时时间
  2. 断开连接后,可以执行局部同步
  3. 实现WAIT
    牢记redis的WAIT的实现案例,对于每一个客户端,在上下文执行所有写命令的时候,产生的复制流的偏移。指定的或者更多从服务器获知偏移量的操作,叫做Redis检查。

返回值
命令返回在当前连接的上下文执行所有写命令的时候,返回已经接收到的指定从服务器的数量


实例

redis 101.201.222.173:6379[4]> set name wuhuangdi
OK
redis 101.201.222.173:6379[4]> wait 1 1000
(integer) 1
redis 101.201.222.173:6379[4]> wait 2 1000
(integer) 1
(1.69s)

MIGRATE host port key|”” destination-db timeout [COPY] [REPLACE] [KEYS key[key …]]

其中xargs -L指令表示xargs一次读取的行数,也就是每次删除的key数量,一次读取太多xargs会报错

SCAN cursor [MATCH pattern] [COUNT count](待续)

可用版本: >=2.8.0
时间复杂度:
每次调用时O(1),每次遍历是O(N),包括最后返回的结果是0.N是集合的元素的大小。

SCAN命令和相关的SSCAN,HSCAN和ZSCAN命令都是用来增量遍历迭代元素的。

  • SCAN命令迭代当前选择的数据库的所有的key
  • SSCAN迭代集合类型的元素
  • HSCAN迭代HASH类型及其相关的键值对
  • ZSCAN迭代有序集合中的元素和对象的分值
    上面的命令都支持增量迭代,每次调用返回部分数据,这些命令能在生产环境使用,不会出现像KEYS或者SMEMBERS命令遍历大数据的集合的时候,会长时间阻塞服务器。
    尽管如此,阻塞的命令SMEMBERS能够返回所有元素,而SCAN相关的命令由于返回的是增量的结果,当数据出现修改,它们无法保证正确性。
    注意:SCAN,SSCAN,HSCAN和ZSCAN命令使用都很相似,所以所以这篇文档涵盖这四个命令。这个有一个不同的是,SSCAN,HSCAN和ZSCAN第一个参数总是ke,而SCAN命令不需要key的参数,因为它遍历的是当前数据库的所有key。
    SCAN基本使用
    SCAN是一个基于游标的迭代。每次调用的时候,服务端返回一个游标,下次调用的时候,需要将这个游标作为参数带上。
    游标设置为0的时候,代表迭代开始,当返回的游标为0的时候,代表迭代结束。下面是一个SCAN迭代的例子:
redis 101.201.222.173:6379> scan 0
1) "1920"
2)  1) ""13763368691""
    2) ""11024""
    3) ""RELATIVE:FOLLOWED:COUNT:10539""
    4) ""15928562014""
    5) ""lalaa5lfl5ly89a86lflj57fj1al711f""
    6) ""11041""
    7) ""10748""
    8) ""13108923312""
    9) ""11109""
   10) ""634j642a2llyf825lfll519ay9j38187""
   11) ""y431l759l738fl29452yl8yjj56aj545""
   12) ""10646""
redis 101.201.222.173:6379> scan 1920
1) "1472"
2)  1) ""15689734000""
    2) ""ly1556l6ad31lyy6fda81a7fj3748a88""
    3) ""10764""
    4) ""RELATIVE:FOLLOWED:COUNT:11007""
    5) ""18611632029""
    6) ""18710027090""
    7) ""10910""
    8) ""6j9969f67y62yl1l2yl6lf56fya22y1j""
    9) ""10729""
   10) ""6a4j72dj1l22333yll6lly3159ad863l""
redis 101.201.222.173:6379>

在上面的例子,第一次调用cursor设置为0,开始了迭代。第二次迭代游标设置成第一次迭代返回的结果,所以游标是1920.
很容易你就发现,SCAN返回的是两个值得数组,第一值是用于下次迭代的游标值,第二个值是一个元素的数据。
当第二次调用返回游标为0的时候,代表了服务器的迭代结束了。游标从0开始迭代,直到返回的游标为0,称为一次完整的迭代。
SCAN命令的保证
SCAN命令和其他SCAN相关的迭代命令,能够给用户带来一次完整遍历的保证,如下:

  • 一次完整的迭代总是在一些迭代的开始到结束期间总是返回一直存在在集合中所有元素。这就意味着,当迭代开始到迭代结束期间,如果一个元素一直存在集合中,那么在某一次迭代中会返回给用户。
  • 完整迭代从来不会在从迭代开始到迭代结束期间返回不在集合中的元素,也就是说,如果一个元素在迭代开始时候被移除了,但是在迭代结束前没有重新加入到集合中,SCAN能够保证这个元素不会返回。
    然而因为SCAN使用游标记录迭代状态,所以它有一些缺点:
  • 同一个元素可能会返回多次,应用程序需要处理重复元素,可以将返回重复的元素使用在能安全执行重复操作上。
  • 如果一个元素是在迭代期期间加入的或者被删除了,那么这个元素也许会返回,也许不会。
    SCAN命令每次执行返回元素的数量
    SCAN类的命令不能保证每次执行的时候都返回给定的数量。它有可能返回0个元素,如果返回的游标不为0,那么客户端不能就视为迭代结束。
    尽管如此,返回的数量也是有规则的。在实际场景中,迭代一个大的数据集合,SCAN可能返回数十个元素,而对于一个小的集合,如果这个集合的数据结构是(小的集合,哈希和有序集合),就会返回所有元素。
    然而,用户可以在调用的时候,使用COUNT选项,来调整返回的元素的大小。
    COUNT选项
    SCAN不能保证每次迭代能返回给定数量的元素,我们可以使用COUNT选项对SCAN返回的数目进行调整。基本上用户指定COUNT选项是为了每次执行的时候限制返回的数量。这仅仅是用户的一种提示,大多数情况下,能够实现。
  • 默认的COUNT值是10.
  • 当迭代一个key空间,集合,哈希或者有序集合,而这个集合比较大的时候,拿哈希来说,假设没有使用MATCH选项,服务器能返回元素的数量等于指定的COUNT选项,或者比指定的COUNT选项要多些。
  • 当迭代编码为整数集合(由整数构成的集合),或者哈希表,有序集合编码的压缩列表(不同值构成的小hash或者小sets),一般的SCAN执行的时候,返回的数量会忽略COUNT,而返回所有的元素。
    注意:美高梅网上游戏,不是每次迭代都需要相同COUNT值,调用的时候可以根据自己的需要随意指定COUNT的值,还需要下次执行的时候带上上次返回的游标。
    MATCH选项
    类似KEYS的命令,使用给定的glob风格的模式作为参数,SCAN命令返回能与给定MATCH <pattern>匹配的元素,下面是一个使用MATCH的例子:
redis 127.0.0.1:6379[4]> sadd name wuhuangdi wusong wolun chs chenhuanhsn
(integer) 5
redis 127.0.0.1:6379[4]> scan name 0 MATCH wu*
(error) ERR invalid cursor
redis 127.0.0.1:6379[4]> sscan name 0 MATCH wu*
1) "0"
2) 1) "wuhuangdi"
   2) "wusong"
redis 127.0.0.1:6379[4]>

注意的是MATCH过滤是元素是从集合返回数据后,返回到客户端之前进行的。那就意味着如果在集合中,只有少量的元素匹配,SCAN会可能在多次迭代中返回0个元素,下面的例子就是这种情况:

redis 127.0.0.1:6379> scan 0 MATCH *11*
1) "288"
2) 1) "key:911"
redis 127.0.0.1:6379> scan 288 MATCH *11*
1) "224"
2) (empty list or set)
redis 127.0.0.1:6379> scan 224 MATCH *11*
1) "80"
2) (empty list or set)
redis 127.0.0.1:6379> scan 80 MATCH *11*
1) "176"
2) (empty list or set)
redis 127.0.0.1:6379> scan 176 MATCH *11* COUNT 1000
1) "0"
2)  1) "key:611"
    2) "key:711"
    3) "key:118"
    4) "key:117"
    5) "key:311"
    6) "key:112"
redis 127.0.0.1:6379>

你会发现大多返回0个元素,但是最后一次迭代中,为了获得更多的匹配,我们强制指定了COUNT选项为1000.
并发执行多次迭代
允许多个客户端同时迭代同一个数据集合,每次执行返回客户端游标,游标就代表了全部迭代状态,所有服务端无须再记录迭代状态。
迭代中止
因为服务端无须记录迭代状态,迭代的状态保存在游标里面。所以客户端单方面随意中止迭代,而无须通知服务端。即使无数的迭代已经开始而中止,也不不会有问题。
SCAN使用错误游标执行
调用SCAN使用错误的,负数的,超出范围或者无效的游标,将会产生未定义的行为,但是不会导致服务端崩溃。未定义的行为指的是返回的元素不再保证正确。只有一下两种是有效的游标:

  • 开始一个新的迭代的时候,游标值为0.
  • 继续迭代的时候,指定上一次迭代返回的游标值。
    中止的保证
    SCAN迭代的算法,只有当集合的数据的数量是有上限的,才会能被中止,假如迭代的数据总是无限增长,那么迭代将永远不会被中止。
    显而易见,如果一个集合一直在增长,需要更多的工作需要做,能否被中止依赖于SCAN在指定COUNT选项的值得迭代的速度是否比集合数据增长的速度要快。

返回值
SCAN,SSCAN,HSCAN和ZSCAN命令都返回一个包含两个元素的multi-bulk:第一个元素是一个无符号64位的数字(游标),第二个元素是一个包含数据集合元素的数组.

  • SCAN返回每个元素的key。
  • SSCAN返回每个元素都是集合的成员。
  • HSCAN返回都是键值对,一个键值对由一个键和一个值组成。
  • ZSCAN返回的每一个元素都是有序集合的成员,一个有序元素是由一个成员和一个分值组成。
    另外的例子:
    哈希迭代值:
redis 127.0.0.1:6379> hmset hash name Jack age 33
OK
redis 127.0.0.1:6379> hscan hash 0
1) "0"
2) 1) "name"
   2) "Jack"
   3) "age"
   4) "33"

如:MIGRATE 127.0.0.1 6380 "" 0 1000 copy keys 002 005 z2 set1

其他几种数据结构的优雅删除

SORT key [BY pattern] [LIMIT offset count] [GET pattern](待续)

可用版本: >=1.0.0
时间复杂度:
O(N+M*log(M)),N是要排序的list,set的元素的数量,M是返回的元素的数量。如果没有使用排序,时间复杂度就是O(N),下一个版本将避免重复的时间复杂度O(N)的步骤。

返回或者保存给定的list,set或者sorted set中key经过排序的元素。排序默认是数字的,其值被解释为双精度浮点数,然后再比较。
这是一种最简单的形式:
SORT mylist

redis dev.baiduwo.com:6379[4]> lpush chs 1 2 3 4
(integer) 4
redis dev.baiduwo.com:6379[4]> sort chs
1) "1"
2) "2"
3) "3"
4) "4"
redis dev.baiduwo.com:6379[4]> zadd chs2 1 2 3
(error) ERR syntax error
redis dev.baiduwo.com:6379[4]> sadd chs2 1 2 3
(integer) 3
redis dev.baiduwo.com:6379[4]> sort chs2
1) "1"
2) "2"
3) "3"

假设mylist是包含一些数字的列表,这个命令返回从小到大排序的列表。为了排序从大到小,使用DESC限定词:
SORT mylist DESC

redis dev.baiduwo.com:6379[4]> sort chs desc
1) "4"
2) "3"
3) "2"
4) "1"
redis dev.baiduwo.com:6379[4]>

当mylist包含字符串元素,你想按照数字排序,使用ALPHA限定词:
SORT mylist ALPHA

redis dev.baiduwo.com:6379[4]> lpush chs3 wuhuang chehuansheng zhangfangling
(integer) 3
redis dev.baiduwo.com:6379[4]> sort chs3
(error) ERR One or more scores can't be converted into double
redis dev.baiduwo.com:6379[4]> sort chs3 ALPHA
1) "chehuansheng"
2) "wuhuang"
3) "zhangfangling"
(0.51s)

假如你正确设置了!LC_COLLATE变量,redis能识别UTF-8的编码。
使用LIMIT限定词能够限制返回元素的数量,
offset - 指定要跳过的数量
count - 返回元素的数量
SORT mylist LIMIT 0 10

redis dev.baiduwo.com:6379[4]> sort chs limit 0 1
1) "1"
redis dev.baiduwo.com:6379[4]> sort chs limit 0 2
1) "1"
2) "2"
redis dev.baiduwo.com:6379[4]>

几乎所有的限定词都能同时使用,下面的例子返回从大到小,经过数字排序的前5个对象。
SORT mylist LIMIT 0 5 ALPHA DESC

redis dev.baiduwo.com:6379[4]> SORT mchs3 LIMIT 0 2 ALPHA DESC
(empty list or set)
redis dev.baiduwo.com:6379[4]> SORT chs3 LIMIT 0 2 ALPHA DESC
1) "zhangfangling"
2) "wuhuang"
redis dev.baiduwo.com:6379[4]>

使用外部key进行排序
有时候需要用外部的key作为权重代替list,set或者sorted set内部的排序。比如说,列表mylist包含元素1,2,3.这三个元素相对应代表的唯一ID存储在object_1,object_2,object_3。而这些object关联的权重是weight_1,weight_2和weight_3,SORT命令会使用下面的语句这些权重来排序mylist:
SORT mylist BY weight_*
BY的选项带有一个表达式(例如weight_),会用来生成用于排序的key。这些key的名称就是列表中能匹配""的数据

redis dev.baiduwo.com:6379[4]> sort chs3 by weight_*
1) "chehuansheng"
2) "wuhuang"
3) "zhangfangling"

跳过排序
!BY 选项也能传入一个不存在的key,跳过排序操作,一般用来检索key而不需要排序的时候是非常有用的。
SORT mylist BY nosort

redis dev.baiduwo.com:6379[4]> sort chs3 ALPHA
1) "chehuansheng"
2) "wuhuang"
3) "zhangfangling"
redis dev.baiduwo.com:6379[4]> sort chs3 by ss
1) "zhangfangling"
2) "chehuansheng"
3) "wuhuang"

检索外部的key
我们上面的例子仅仅返回排序的ID,有的时候获取真实的值更加有用,在list,set或者sorted set检索外部的key获取元素,可以通过以下命令完成:
SORT mylist BY weight_* GET object_*
GET选项可以重复使用,以便获取更多的值。
如果要查询它自己,要是用特定的模式 #,如下:
SORT mylist BY weight_* GET object_* GET #

redis dev.baiduwo.com:6379[4]> SORT chs BY weight_* GET object_* GET #
1) (nil)
2) "1"
3) (nil)
4) "2"
5) (nil)
6) "3"
7) (nil)
8) "4"

存储排序结果
默认情况下,SORT直接返回已经排序的元素,如果加上STORE选项,排序结果会存储到指定key。
SORT mylist BY weight_* STORE resultkey

使用SORT...STORE联合命令构成一个有效期的key,以便应用程序能够缓存排序结果一段时间。其他客户端如果调用相同SORT请求的时候,会直接返回已经缓存的排序结构。如果key过期了,缓存将在再次调用SORT...STORE的时候更新。
注意的是,尽量避免多个客户端在相同时候同时缓存计算。这个时候需要锁的机制(例如使用SETNX)

hash表使用!BY和!GET
hash表使用!BY和!GET语法如下:
SORT mylist BY weight_*->fieldname GET object_*->fieldname
字符串"->"是key指向hash key的分隔符。这里的key可以代替文档上面的提到的key。

redis dev.baiduwo.com:6379[4]> SORT chs3 alpha BY weight_* STORE chs33
(integer) 3
redis dev.baiduwo.com:6379[4]> sort chs33 by ss
1) "zhangfangling"
2) "chehuansheng"
3) "wuhuang"
redis dev.baiduwo.com:6379[4]>

返回值
排序的元素列表

注意:最近看到很多已经翻译的redis文章,包括新版本的都已经出来了,所以我觉得不能重复造轮子的态度。停止翻译。附上中文redis翻译的文章。
http://redis.cn
http://doc.redisfans.com
接下来,我会针对redis在现实架构中的实用场景做介绍和分析。

  • host port 目标Redis实例地址
  • key|””迁移单个key时就指定该key,多个key时用””
  • destination-db 目标Redis实例数据库编号
  • timeout 执行迁移的过期时间(毫秒)
  • [COPY] 迁移后保留源key
  • [REPLACE] 不管目标Redis实例是否已存在迁移的key,都进行迁移并覆盖目标key的value
  • [KEYS key[key …]] 指定要迁移的多个键

版权声明:本文由美高梅开户送58元官网发布于美高梅网上游戏,转载请注明出处:刷新有效期,Redis中没有批量删除特定前缀key的指