Redis的命令有上百个,如果纯靠死记硬背比较困难,但是如果理解Redis的一些机制,会发现这些命令有很强的通用性。有些数据结构和命令必须在特定场景下使用,一旦使用不当可能对Redis本身或者应用本身造成致命伤害。
同时我们知道Redis支持很多种数据结构的。整体上来说, Redis是键值对结构。 key固定就是字符串, value 实际上会有多种类型。每种不同的数据结构都会有其对应的操作指令。但是全局命令,就是能够搭配任意一个数据结构来使用的命令!
本篇文章对 Redis 的一些全局通用命令进行详解。主要涉及到的命令有get、set、keys、exists、del、expire、ttl、type。希望本篇文章会对你有所帮助。
文章目录
set(SET KEY VALUE)
get(GET KEY)
keys
exists
del
expire
ttl
type
🙋♂️ 作者:@Ggggggtm 🙋♂️
set(SET KEY VALUE)
get 和 set 是 Redis中最核心的两个命令。我们知道 Redis 是按照键值对(key - value)的方式存储数据的。怎么设置键值对呢?
set 就是用来设置保存键值对的。用法具体如下图:
当我们在redis客户端输入set指令后,会提示我们其用法。key 和 value 都是字符串。下面我们再看一下具体的实例。如下图:
上述演示了使用 set 来设置键值对。其中我们设置了两次keys1,其中只会存储一份。实际上第二次设置key1时,是对原来key1的值进行了修改。查看匹配的 key 所用到了指令是keys,后续会详解。
对于上述这里的 key value,不需要加上引号,就是表示字符串的类型。当然,如果要是给key和value 加上引号,也是可以的(单引号或者双引号都行)。
还有需要注意的一点是Redis命令不区分大小写。
get(GET KEY)
get 就是通过我们所设置的 key 来获取到对应的 value 值。用法如下图:
其用法相当简单,我们直接看如下实例:
get命令直接输入 key 就能得到 value。如果当前key不存在,会返回nil。nil其实代表的就是空,类似于null/NULL。他们两者意思都是相同的,但是使用场景上是有所差别的。具体如下:
keys
keys命令用于查找符合指定模式的所有 key。其用法如下:
其中 pattern 有固定的匹配格式,所支持的匹配格式如下:
- h?llo 匹配 hello , hallo 和 hxllo;
- h*llo 匹配 hllo 和 heeeello;
- h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo;
- h[^e]llo 匹配 hallo,hbllo,...但不匹配 hello
- h[a-e]llo 匹配 hallo,hbllo,hcllo,hello。
我们先设置一些值,具体如下:
然后我们再看一下上述匹配格式的具体用法。具体如下:
- 其中 ?是匹配任意一个字符,* 是匹配任意多个字符(包括0个);
- [ae] 是指匹配 a 或者 e 字符;
- [^e] 是指匹配除了e的任意一个字符;
- [a~e] 是指匹配 a 到 e 其中任意一个字符;
通过上述的学习,我们也就很好的可以理解 keys * 的含义了,就是匹配所有的key值。然而,使用 keys 命令要小心,因为它会遍历所有 key,时间复杂度为O(n)的。这可能会影响 Redis 服务器的性能,特别是在大数据集下。
所以,在生产环境上,一般都会禁止使用keys命令。尤其是大杀器keys * 去查询redis 中所有的key 。生产环境上的 key 可能会非常多,而redis是一个单线程的服务器。执行keys *的时间非常长,就使redis服务器被阻塞了,无法给其他客户端提供服务。这样的后果可能是灾难性的!!!
redis经常会用于做缓存,挡在mysql前面,是替mysql负重前行的人。万一redis被一个keys *阻塞住了,此时其他的查询redis 操作就超时了。此时这些请求就会直接查数据库!!!突然一大波请求过来了,mysql措手不及,就很容易挂了。最终导致整个系统就基本瘫痪了。
exists
exists 是 用于检查给定的key是否存在。语法是:
exists key [key ...]
其返回值:
- 如果键存在,则返回 1。如果检查多个,就会返回多个所存在的个数。
- 如果键不存在或已过期,则返回 0。
其时间复杂度是O(1)的。当检查多个key时,时间复杂度即为O(n),n为所检查key的个数。redis这些key值都是用哈希表来组织的。我们看一下其具体用法如下:
提问:上述的第一、二中方式与第三种方式有区别?具体有哪些区别?
redis是一个客户端服务器结构的程序。客户端和服务器之间通过网络来进行通信!!!分开的写法,会产生更多轮次的网络通信。网络通信的效率比较低的。我们知道进行网络通信的时候,发送方发送一个数据,这个数据就要从应用层到物理层(每一层协议都要加上报头或者尾),要封装好几层。接收方收到一个数据,这个数据就要从物理层,到应用层层层分用。网卡是IO设备,更何况你的客户端和服务器不一定在一个主机上,中间可能隔着很远呢!所以redis自身也非常清楚上述问题,redis的很多命令都是支持一次就能操作多个key的多种操作。
del
Redis 中的 del 命令用于删除指定的 key,其语法为:
del key [key ...]
返回值:
- 被删除 key 的数量。
其时间复杂度为O(1),具体也看删除key的个数。其用法也十分简单。我们直接看具体实例:
之前学mysql的时候,当时强调删除类的操作:drop database、drop table、delete from...都是非常危险的操作!因为一旦删除了之后,数据就没了。redis 主要的应用场景,就是作为缓存。此时redis 里存的只是一个热点数据,全量数据是在mysql数据库中。此时如果把redis 中的 key删除了几个,一般来说问题不大的。但是如果把所有的数据或者一大半数据一下都干没,这种影响会很大。(本来redis是帮mysql负重前行, redis 没数据了,大部分的请求就直接打给mysql,然后就容易把 mysql搞挂)。相比之下,如果是mysql这样的数据,哪怕误删了一个数据,都可能是影响很大的!如果是把redis 作为数据库,此时误删数据的影响就大了。具体情况还要具体分析。
expire
为指定的 key 添加秒级的过期时间(Time To Live TTL)。当到达指定时间后,Redis 会自动删除该 key。expire 命令的语法如下:
expire key seconds
返回值:
- 当 key 存在且设置成功时,返回 1;当 key 不存在或者不能设置过期时间时,返回 0。
其时间复杂度为O(1)的。我们可能想到对于计算机来说,秒是一个非常长的时间,那么能不能设置毫秒级别的呢?答案是有的。具体用法:pexpire key 毫秒。接下来我们先看一下expire的实例:
这里有一个很经典的问题:redis 的 key 的过期策略是怎么实现的? 简单来说一个redis 中可能同时存在很多很多key。这些 key中可能有很大一部分都有过期时间。此时, redis 服务器咋知道哪些key 已经过期要被删除,哪些key还没过期呢?
如果直接遍历所有的key,显然是行不通的,效率非常低。Redis 中的键过期策略整体是通过惰性删除(Lazy-Delete)和定期删除(Eviction)相结合来实现的。
- 惰性删除(Lazy-Delete): 假设这个key已经到过期时间了,但是暂时还没删它,key还存在。当客户端尝试访问一个已经过期的 key 时,Redis 会立即删除该 key,并返回空结果。这个过程是在访问 key 时进行的,因此被称为惰性删除。
- 定期删除(Eviction): Redis 还会以一定的频率扫描部分设置了过期时间的 key,并进行删除操作。定期删除并不是以每个过期键为单位单独进行删除,而是按照算法进行随机化、分散化处理,不会一次性删除太多键。具体的删除策略有两种:
- 定期删除(定时任务): Redis 会每隔一段时间随机选择一些设置了过期时间的 key 进行检查,如果发现过期则删除。使用的是Redis服务器的serverCron函数来执行这个任务。
这里有一个疑问:为什么定期删除会抽取一部分,而不是删除所有的过期key呢?因为redis是单线程的程序。主要的任务是处理每个命令的任务,刚才扫描过期key ....。如果扫描过期key消耗的时间太多了,就可能导致正常处理请求命令就被阻塞了。(产生了类似于执行keys *这样的效果)。而每次抽取一部分,就是为了进行验证过期时间保证这个抽取检查的过程足够快!!
Redis 通过以上的过期策略,可以在保证性能的同时,自动清理过期的键,避免数据的存储空间过大和时间复杂度的增加。需要注意的是,Redis 的过期策略是基于不保证对每个键进行实时删除而设计的,所以在某些情况下,可能会出现过期键暂时未被删除的情况。
ttl
在Redis中,ttl 是一个用于获取Key的剩余生存时间的命令。ttl 代表"Time To Live",它返回的是以秒为单位的整数值,表示Key在Redis中还有多少时间过期。以下是 ttl 命令的使用方式:
TTL key
返回值说明:
- 当键存在且具有生存时间时,返回剩余生存时间的秒数。
- 当键不存在或已过期时,返回-2。
- 当键存在但没有设置生存时间时,返回-1。
具体我们看如下实例:
EXPIRE 和 TTL 命令都有对应的支持毫秒为单位的版本:PEXPIRE和PTTL,详细用法就不再介绍了。
type
在Redis中,type 命令用于获取存储在指定键中的值的数据类型。以下是 type 命令的使用方式:
TYPE key
返回值说明:
- 如果键不存在,返回
none
。- 如果键包含的是字符串类型的值,返回
string
。- 如果键包含的是列表类型的值,返回
list
。- 如果键包含的是集合类型的值,返回
set
。- 如果键包含的是有序集合类型的值,返回
zset
。- 如果键包含的是哈希类型的值,返回
hash
。具体实例如下图: