基本全局命令generic命令通常指的是 generic key commands也就是对 Key 本身进行操作的命令这些命令和存储在 Key 里面的 Value 的具体类型没有关系。Key 永远只是一个字符串名字StringKey 都支持的操作是通用的。Redis有5种数据结构但它们都是键值对中的值(毕竟Redis是键值对、非关系型数据库)对于键来说有一些通用命令下面将介绍一下一些常用的对key使用的通用命令(generic key commands)。KEYS在介绍这个命令之前为了方便理解我们先简单介绍一下string数据结构中的set和get命令具体细节看String的数据结构命令介绍我们可以通过set放入一个key拥有string类型的value值例如:set key1 12306我们同时可以通过get来得到key对应的value值例如get key 结果12306语法KEYS pattern作用Returns all keys matchingpattern.也就是说我们可以通过一些格式来返回所有key值只要其符合pattern的匹配对象。注意Redis 的KEYS pattern使用的是类似 Shell 通配符glob pattern的匹配规则而不是正则表达式。这里具体的Shell通配符匹配规则不细讲网上都可以查询到时间复杂度O(N)返回值所有被匹配到的key例如127.0.0.1:6379 set hello 1 OK 127.0.0.1:6379 set hallo 2 OK 127.0.0.1:6379 set hollo 3 OK 127.0.0.1:6379 keys h[ae]llo 1) hallo 2) helloEXISTS语法EXISTS key [key ...]作用判断一个或多个key是否存在。时间复杂度O(N)N表示本次命令中需要判断的key的数量。当只判断一个key时可以看作O(1)。返回值返回存在的key的数量而不是简单地返回true或者false。例如127.0.0.1:6379 set key1 12306 OK 127.0.0.1:6379 exists key1 (integer) 1 127.0.0.1:6379 exists key1 key2 (integer) 1上面的key1存在而key2不存在因此返回1。如果两个key都存在则返回2如果两个key都不存在则返回0。注意如果在一条命令中重复传入同一个存在的key那么这个key会被重复计算。127.0.0.1:6379 exists key1 key1 (integer) 2为什么通常使用EXISTS key1 key2而不是分别执行两次EXISTSRedis是由客户端和服务端构成的。我们在代码中调用Redis命令时命令并不是直接在客户端本地完成的而是通常需要经过下面的过程客户端将命令按照Redis通信协议编码然后通过网络发送给Redis服务端Redis服务端接收并执行命令Redis服务端将执行结果通过网络返回给客户端客户端接收并解析结果。如果分别执行下面两条命令EXISTS key1 EXISTS key2在没有使用Pipeline管道的情况下通常需要进行两次请求和两次响应也就是两次网络往返。而把它们合并成一条命令EXISTS key1 key2客户端只需要发送一次请求Redis也只需要返回一次响应因此只发生一次网络往返。虽然Redis在服务端仍然需要依次判断两个key服务端的时间复杂度仍然是O(N)但是它减少了网络往返次数、协议解析次数以及请求和响应的数据包开销。在实际开发中网络通信的耗时往往比Redis在内存中判断一个key是否存在的耗时更明显毕竟网络也是IO嘛。因此当我们只关心“一共有多少个key存在”时通常应优先使用EXISTS key1 key2 ...而不是把命令拆开执行。不过批量EXISTS只返回存在的key的总数不能告诉我们具体是哪一个key存在。如果业务需要得到每一个key各自的判断结果可以分别执行EXISTS并使用Pipeline一次性发送从而在获得逐个结果的同时减少网络往返次数。注意命令参数之间使用空格分隔正确写法是EXISTS key1 key2而不是EXISTS key1,key2。在Redis Cluster中多key命令还会受到哈希槽的限制如果key不在同一个哈希槽中可能需要由客户端拆分请求或者使用{}哈希标签让相关key落到同一个槽中。DEL语法DEL key [key ...]作用删除一个或多个key。不存在的key会被忽略不会抛出错误。时间复杂度删除多个key时为O(N)N表示key的数量。对于String类型的值删除单个key通常为O(1)如果值本身包含大量元素例如很大的List、Set、ZSet或者Hash释放值所占用的内存还可能产生额外耗时。返回值实际被删除的key的数量。例如127.0.0.1:6379 set key1 12306 OK 127.0.0.1:6379 set key2 10086 OK 127.0.0.1:6379 del key1 key2 key3 (integer) 2 127.0.0.1:6379 exists key1 key2 (integer) 0因为key1和key2存在而key3不存在所以实际删除了两个key返回2。如果需要删除很大的复杂类型key又不希望释放内存的过程长时间阻塞Redis可以了解一下UNLINK命令。UNLINK会先把key从键空间中移除再由后台线程异步回收相应的内存。EXPIRE语法EXPIRE key seconds [NX | XX | GT | LT]作用为key设置以秒为单位的过期时间。当过期时间到达后Redis会自动删除这个key。时间复杂度O(1)返回值返回1成功为key设置了过期时间。返回0key不存在或者指定的条件没有满足。例如127.0.0.1:6379 set code 1234 OK 127.0.0.1:6379 expire code 60 (integer) 1 127.0.0.1:6379 ttl code (integer) 60上面的命令表示让code在60秒后过期。EXPIRE还支持下面几个条件选项NX只有key当前没有过期时间时才设置过期时间XX只有key当前已经有过期时间时才更新过期时间GT只有新的过期时间大于当前过期时间时才更新LT只有新的过期时间小于当前过期时间时才更新。例如127.0.0.1:6379 expire code 120 GT (integer) 1这表示只有新的120秒大于code当前剩余的过期时间时才进行更新。注意如果seconds为0或者负数key会被立即删除使用SET key value重新设置一个key时通常会清除它原来的过期时间。如果希望保留原来的过期时间可以使用SET命令的KEEPTTL选项如果想使用毫秒作为单位可以使用PEXPIRE命令。TTL语法TTL key作用获取key剩余的生存时间单位为秒。时间复杂度O(1)返回值返回大于等于0的整数key剩余的生存时间单位为秒返回-1key存在但是没有设置过期时间也就是永久有效返回-2key不存在。例如127.0.0.1:6379 set key1 12306 OK 127.0.0.1:6379 ttl key1 (integer) -1 127.0.0.1:6379 expire key1 60 (integer) 1 127.0.0.1:6379 ttl key1 (integer) 60 127.0.0.1:6379 ttl not-exists-key (integer) -2由于命令执行和网络传输都会消耗一点时间所以在实际环境中设置60秒后再查询TTL时也可能看到59等接近60的值这是正常现象。如果需要得到毫秒级的剩余生存时间可以使用PTTL命令。TYPE语法TYPE key作用查看key对应的value是什么数据类型。时间复杂度O(1)返回值返回key对应的数据类型。常见结果包括string字符串list列表set集合zset有序集合hash哈希stream流nonekey不存在。例如127.0.0.1:6379 set key1 12306 OK 127.0.0.1:6379 type key1 string 127.0.0.1:6379 lpush names Tom Jack (integer) 2 127.0.0.1:6379 type names list 127.0.0.1:6379 type not-exists-key noneTYPE命令只能告诉我们value的顶层数据类型不能直接展示value中保存的具体内容。要读取具体内容需要根据对应的数据类型使用GET、LRANGE、SMEMBERS、HGETALL等命令。