【redis】全局命令exists、del、expire、ttl(惰性删除和定期删除)
exists——判定 key 是否存在
语法:
exists key [key...]
# 返回值:key 存在的个数
- 针对多个
key
来说,是非常有用的 - 时间复杂度
O
(
1
)
O(1)
O(1)
Redis
组织这些key
就是按照哈希表的方式来组织的。Redis
支持很多数据结构指的是value
可以是一些复杂的数据结构
Redis
自身的这些键值对,是通过哈希表的方式来组织的,Redis
具体的值,又可以是一些数据结构
Redis
是一个客户端-服务器结构的程序,客户端和服务器之间通过网络来进行通信- 每次我们敲的命令,都是由
Redis
客户端包装成一个请求,发送给Redis
服务器,服务器再返回响应- 因此最好不要把 key 分开写。分开写会产生更多轮次的网络通信,效率比较低,成本比较高
[!qoute] 封装和分用
- 进行网络通信的时候,发送方发送一个数据,这个数据就要从应用层,到物理层,层层封装(每一层协议都要加上报头或者尾)==>发送一个快递,要包装一下,要包装好多层
- 接收方收到一个数据,这个数据就要从物理层,到应用层,层层分用(把每一层协议中的报头或者尾给拆掉)==>收到一个快递,要拆快递,拆很多层
- 这些过程都是要消耗时间,消耗
CPU
的
Redis
自身也非常清楚上述问题,所以 Redis
的很多命令都支持一次就能操作多个 key
的/多种操作
del——删除指定的 key
可以一次删除一个或者多个
语法:
del key [key...]
- 时间复杂度 O ( 1 ) O(1) O(1)
- 返回值:删除掉的
key
的个数
在
MySQL
中,删除类的操作
drop database
drop table
drop from
…
这些都是非常危险的操作,一旦删除之后,数据就没了。但在 Redis 中,危险程度就小很多了- 因为 Redis 的主要应用场景,就是作为缓存,里面存的只是一个热点数据,而全量数据是在
MySQL
中。如果把Redis
中的key
删除了几个,问题不大,大不了再从MySQL
中读就可以了。- 但是如果把所有的数据,或者一大半数据都干没了,这种影响就会很大。本来是靠
Redis
帮MySQL
负重前行,Redis
没数据了,大部分请求就直接打给MySQL
了,然后就容易把MySQL
搞挂- 相比之下,如果是
MySQL
这样的数据,哪怕误删了一个数据,都可能影响是很大的- 但如果是把
Redis
作为数据库,此时误删数据的影响就大了
expire——给 key 设置过期时间
单位为秒
key
存活时间超过这个 expire
指定的值,就会被自动删除
- 在很多业务场景,都是有时间限制的
- 验证码。要实现验证码一分钟失效的功能,我们就可以把这个验证码信息存储到
Redis
中,将expire
设置为60
,等到一分钟后Redis
里面的验证码信息被删除,就查询不到了 - 点外卖。优惠券,在指定时间有效
- 分布式锁。基于
Redis
实现分布式锁,为了避免出现不能正确解锁的情况,通常都会在加锁的时候设置一下过期事假(所谓的使用Redis
作为分布式锁,就是给Redis
里写一个特殊的key
value
)
- 验证码。要实现验证码一分钟失效的功能,我们就可以把这个验证码信息存储到
语法:
expire key seconds
pexpire key 毫秒
- 对于计算机来说,秒是一个非常长的时间,下面的时间单位是毫秒
ttl——查询过期时间
time to live
在网络原理,
IP
协议报头中,就有一个TTL
字段
IP
中的TTL
不是用时间衡量过期的,而是次数
查询当前 key 的过期时间还剩多少
语法:
ttl key //秒
pttl key //毫秒
- 返回剩余过期时间
- 返回
-1
表示没有关联过期时间 - 返回
-2
表示key
不存在
过期策略是如何实现的
#高频面试
一个 Redis
中可能同时存在很多很多 key
,这些 key
中有很大一部分都有过期时间。此时,Redis
服务器怎么知道哪些 key
已经过期要被删除,哪些 key
还没过期?
- 如果直接遍历所有的 key,显然是行不通的,效率非常低
- Redis 整体的策略是两方面
- 定期删除
- 惰性删除
惰性删除
- 假设这个
key
已经到达过期时间了,但是暂时还没删除它,key
还在 - 紧接着,后面又一次访问,正好用到了这个
key
,于是这次访问就会让Redis
服务器触发删除key
的操作,同时再放回一个nil
- 你去超市买水,正要付钱的时候,看了一眼日期,发现过期了,于是老板就说不卖了,于是就把这瓶水下架了,这就是“惰性删除”
- 老板也不清楚哪些过期了,哪些没过期,就在卖出的时候做一次检查,如果过期了就不卖了,如果还没过期,就继续卖
但显然,单靠惰性删除肯定是不靠谱的,一个超市这么多商品,怎么可能全去靠用户去检查,所以肯定还得要有一个辅助的机制——定期删除
定期删除
这个超市老板,要定期查看超市里面的商品,看是否有过期产品
- 但是如果超市商品很多,那么每次遍历一遍就非常慢
- 所以,每次抽取一部分,进行验证过期时间。保证抽取检查的过程足够快
为什么这对定期删除的时间有明确的要求呢?
- 因为
Redis
是单线程程序,主要的任务是处理每个命令的任务(刚才扫描过期key
…) - 如果扫描过期
key
消耗的时间太多了,就可能导致正常处理请求命令就被阻塞了(产生了类似key *
的效果)
虽然有了上述两种策略结合,但整体的效果仍一般。仍然有可能会有很多过期的 key
被残留了,没有及时删除掉
但是 Redis
为了对上述进行补充,还提供了一系列的内存淘汰策略