【Redis】常用命令

在学习命令之前,我们一定要参考Redis的官网,能够看英文官方文档,是每个程序员的"基操".

🐼Redis最核心的命令

我们说过,Redis是按照键值对的方式来存储数据的。

GET

cpp 复制代码
GET key

通过key获取value, 如果 key 不存在,返回 nil。如果 value 的数据类型不是 string,会报错。时间复杂度O(1)

SET

cpp 复制代码
SET key value 

设置键值对[key, value], 将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此 key 的 TTL 也全部失效。时间复杂度O(1)

不管是set还是get,其中key和value都是字符串

Redis不区分大小写,和MySQL一样。

为什么他俩是最核心的两个命令吗,不就是一个读,一个写,与Redis通过网络进行IO,通过这两个O(1)时间复杂度的操作,我们就能完成绝大部分操作了。


🐼Redis全局命令

我们说了,Redis是键值对结构,其中key是固定字符串,其中value表示很多数据结构类型,Redis 有 5 种数据结构,不过对于键来说有⼀些通用的命令,而value对于不同的容器我们到时候再去看。

而全局命令就是,能够搭配任何一个数据结构去使用的命令

✅KEYS

返回所有满足样式(pattern)的 key,该命令可以看到的是每一个key的模样,同时也可以允许存在通配符等,当我们不确定我们的redis中有哪些key时,可以试着来查找

cpp 复制代码
KEYS pattern

来看一下官网给的pattern的介绍,主要是一些通配符的匹配规则,忘记了去官网查即可。

cpp 复制代码
h?llo matches hello, hallo and hxllo  # ?表示匹配任意一个字符。
h*llo matches hllo and heeeello # *表示可以匹配一个或者多个任意个字符。
h[ae]llo matches hello and hallo, but not hillo # [....]表示可以从中匹配这些字符,不再[]中的字符不行。
h[^e]llo matches hallo, hbllo, ... but not hello # 表示除e的字符其他都行
h[a-b]llo matches hallo and hbllo # 表示匹配 [a, b]之间的字符,包括边界

注意事项:

keys的时间复杂度为O(N),因此,不建议使用keys,在生产环境上,明确禁止使用keys,尤其是像keys * 这样的导致Redis挂掉的命令

🚩为啥嘞,首先生产环境就是线上环境,就是和用户交互的环境,你在线上环境搞个这,因为Redis是基于网络的,是客户端服务器的模式,而且Redis是单线程的,又不单单是服务你一个客户端,如果你这个客户端发一个key*,导致Redis只为你一个人服务了,导致其他用户的访问都去MySQL那里了,MySQL它又很"娇气",一不小心就挂了,所以,强烈禁止,不要让站在MySQL背后的哪个男人-Redis阻塞住!它在为MySQL负重前行嘞!

**✅**EXISTS

判断KEY是否存在

cpp 复制代码
EXISTS key [key ...]

返回值为Key存在的个数,也就是我们可以一次性判断多个key是否存在,存在几个就返回几!

时间复杂度为O(1),官网写的是O(N)其中这个N就是key的个数,这个N是多少,不好说,但你一次性要判断的KEY不能特别多对吧,所以就是O(1).

注意下面这两种写法的区别:

🚩第一种写法和第二种分两次写,有啥区别吗?

其实,有本质的区别,我们知道我们的redis是客户端服务器通信的,我们每操控的一条命令,都是基于网络发给redis-server的,然后redis-server处理完再发给我们。相比于操控在内存,是很慢的,走网络就有开销,比如os什么时候刷新网卡?网卡IO效率还慢,还得封装分用。那么你说一次命令完成的事情,走两次,哪个好?

redis也意识到了这一点,所以redis支持一次性一个命令来操作多个key完成多种操作。

✅DEL

删除指定的 key

cpp 复制代码
DEL key [key ...]

返回值依旧是成功删除掉key的个数。时间复杂度为O(1)

🚩这里需要注意一下,就是之前学的MySQL,是很忌讳你去删除东西的,这里Redis呢?在Redis中删除东西,要看你Redis是缓存还是被当做数据库使用了,如果你仅仅是一个热点数据,全量数据在MySQL中,那么删除几个key,问题不大,不过删多了,可能导致热点数据命中率不高,进而导致MySQL挂掉。但是如果Redis被当做数据库使用,那么此时就不敢随意删除了,一旦删除,可能不能进行回滚操作,导致数据丢失了~归根结底,还是不要乱删数据!

✅EXPIRE

为已经存在指定的 key 添加秒级的过期时间(Time To Live TTL)

返回1表示设置成功。0 表示设置失败。时间复杂度为O(1)

cpp 复制代码
EXPIRE key seconds

怎么理解这个过期时间,就是如果你的key超过这个过期时间,就会被自动删除~

✅TTL

全称为time to live

获取已经存在的指定 key 的过期时间,秒级

返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示key 不存在。时间复杂度为O(1)

cpp 复制代码
 TTL key

通长这个命令配合expire来使用,来查看过期时间的。

✅TYPE

返回 key 对应value的数据类型

时间复杂度为O(1)

cpp 复制代码
TYPE key

返回值包括: returned are: string, list, set, zset, hash, stream, and vectorset.

对于以上value的操作,操作差别很大, 命令是完全不同的,但是我们都可以使用type来看看对应的key的value到底是啥~


🐼扩展知识(面试题)

Redis中的key的过期时间是怎么实现的?Redis中的key那么多,你怎么知道哪些key要被删除,哪些key不被删除,哪些key还没过期?如果我们直接遍历所有的key,那么"杀伤力"不亚于key *

主要有两种方式:

✅定期删除

每次抽取一部分,进行验证过期时间,保证这个抽取过程是足够快的!为什么要保证足够快呢?或者说为什么要进行抽取呢?原因是Redis是单线程程序,主要任务是执行每个命令的任务,如果抽取过程占用的时间太久,导致其他客户端的连接是阻塞的,就类似与执行key*咯

✅惰性删除

假设这个key已经过期,但是暂时还没删它,key还存在,紧接着,redis-cli后面又再一次访问到了这个key,然后再将它删除,并返回给客户端nil。

虽然上述两种操作可以删除过期的key,但是效果一般,并不能保证所有key及时删除。不过redis进行了一写淘汰策略的机制。


这里有一个有意思的故事:

为什么没有使用定时器?

网上有人说,Redis的删除key的策略如果是根据定时器来完成的,那么不靠谱。真的是这样吗?

其实不然,Redis的作者并没有实现定时器,猜测因为Redis完全就是一个线程的基调,引入定时器,就意味着引入了多线程。为了不打破作者的初衷,这里并没有引入多线程。也没有引入定时器了!

定时器真的不靠谱吗?我们来看一下常用的两种定时器:

⌚️根据优先级队列实现的定时器

优先级队列就是按照指定的优先级进行先入先出的,啥叫优先级高,自定义的~

在redis删除key的场景中,就可以通过"过期时间越早,优先级越高的方式",那么队首元素,就是最早的key,最先过期的,所以我们只需要分配一个线程,取出队首元素,看看是不是需要删除即可,如果队首都没过期,那么所有key都没过期~此时,我们就不需要遍历key了

⌚️根据时间轮来实现定时器

把时间划分为一个个小段,就是一个小格子,小段的粒度,看具体的场景。比如,将时间段为每100ms一次,而每一个格子上挂接这一个个链表,这一个个链表的节点,可能是 一个任务,每隔100ms,小格子都移动一格,尝试把对应任务执行一下,如图:

如果删除key操作使用定时器看起来是高效的,而没有使用定时器也不是网上所说的,还是Redis的初衷就是单线程的基调~

相关推荐
柱子jason1 分钟前
使用IOT-Tree对接工业现场PLC并把采集数据记录到关系数据库中
数据库·物联网·plc·工业物联网·工业自动化·iot-tree·生产线配套
2301_822375444 分钟前
Python虚拟环境(venv)完全指南:隔离项目依赖
jvm·数据库·python
2301_790300965 分钟前
Python类型提示(Type Hints)详解
jvm·数据库·python
一路向北⁢20 分钟前
Spring Boot 3 整合 SSE (Server-Sent Events) 企业级最佳实践(二)
java·数据库·spring boot·sse·通信
远方160923 分钟前
112-Oracle database 26ai下载和安装环境准备
大数据·数据库·sql·oracle·database
2401_8384725124 分钟前
Python多线程与多进程:如何选择?(GIL全局解释器锁详解)
jvm·数据库·python
光影少年39 分钟前
非关系数据库和关系型数据库都有哪些?
数据库·数据库开发·非关系型数据库
2301_8223636040 分钟前
Python单元测试(unittest)实战指南
jvm·数据库·python
麦兜*1 小时前
深入解析分布式数据库TiDB核心架构:基于Raft一致性协议与HTAP混合负载实现金融级高可用与实时分析的工程实践
数据库·分布式·tidb
m0_561359671 小时前
Python面向对象编程(OOP)终极指南
jvm·数据库·python