Redis的一些通用指令

首先我们需要先连接客户端服务器,此时我们需要通过redis-cli和redis服务器进行交互,输入ping来确保通路的流畅

(一)get和set

redis中最核心的两个命令就是get和set,get就是根据key来取出对应value,set就是把key和value给存储进去(redis是根据键值对的方式存储数据的)

如果通过get想要获取的value不存在,就会返回一个nil(跟java中的null类似)

(二)redis全局命令

redis是支持很多数据结构的(value中的数据可以用不同数据结构存储,key是固定的字符串类型),但是不同的数据结构有不同的命令,我们接下来要说的是所有数据结构类型都通用的一些命令。

1.keys

用来查询当前服务器上匹配的key:通过一些通配符来描述key的模样,匹配上述模样的key

?:匹配任意一个字符

*:匹配任意多个字符

[ae]:只匹配ae字符

[a-e]:匹配a到e的字符

[^e]:匹配除了e的字符

keys的复杂度是O(N)因为需要遍历所有key,所以我们在生产环境上一般不使用keys,尤其还有一个keys*,遍历所有key

那为什么我们生产环境一般不适用keys?是因为redis是单线程服务器如果keys*的时间很长,redis就会被阻塞,无法给其他客户端提供服务。

而且redis经常用于缓存来减少服务器的压力,如果redis阻塞,那么服务器的请求量会一瞬间增大,容易把服务器弄挂

2.exists

来判断key是否还存在

返回值是key存在的个数,我们可以同时传输多个key

时间复杂度是O(1)因为redis组织key是按照哈希表的方式来组织的

那上述代码我们可以一次访问多个,也可以一次访问一个,那两者有什么区别?

本质上没有区别,但是我们要知道redis是一个客户端服务器结构的程序,要通过网络来进行通信,但是分开写需要进行多次网络通信,这样就会导致我们的效率降低(所以redis很多命令都可以一次操作多个key或者多种操作)

3.del

删除指定的key

也可以一次删除多个或者一个,返回值是删掉的个数

时间复杂度O(1)

我们之前在mysql数据库中删除操作是drop当时我们说删除操作是很危险的,因为一旦删除了就找不回来了,redis同理,也十分危险,但是比mysql还是好了很多(不同场景)

比如我们redis做缓存,我们放的是热点数据,所有数据都在数据库服务器中有备份,此时删除一两个问题不大(删多了会造成服务器请求量过大),但是如果redis做服务器那么删除数据就也很危险,如果把redis做消息队列,就看我们的是什么数据了,是否重要

4.expire和pexprie

作用是给指定的key设置过期时间,当key存活时间超出这个指定值就会被自动删除(可应用在验证码,分布式锁等等)

expire单位是s,pexpire是ms

我们要设置过期时间是要针对已经有的key设置,设置成功就返回1,失败就返回0,时间复杂度也是O(1)

那此时我们怎么知道是不是10s钟删除了呢?这时我们需要另一条指令

5.ttl和pttl

用来查看当前的key的过期时间还有多少

ttl的单位是s,pttl的单位是ms

如果执行完会返回-2

扩:redis的key过期策略是如何实现?

我们刚才说expire可以给key设置过期时间,到时间就要进行删除,那么一个redis中有很多key,这些大部分有过期时间,我们redis怎么知道那些key要被删除?如果通过遍历,就会导致效率过低,很可能会影响我们的服务器

所以redis是通过

1.定期删除:

我们redis会定期的抽取一部分数据(一般不会很大)来验证过期时间,如果到了会进行删掉,之所以抽取一部分数据,也是为了保证定期删除这个操作的速度。

2.惰性删除:

我们如果时间到了也不删除他,key还存在,如果我们之后访问到了,用到了这个key,就会让redis触发删除操作,删除这个key同时返回nil

但是光凭上述两个删除策略,会导致在内存中仍然有需要删除的数据存在,本来redis就是在内存中存储,空间不大,所以我们引入了内存淘汰策略

3.内存淘汰策略:

这个我们之后会说

在我个人看来,redis是可以通过一个定时器来进行定时删除的,他可以让内存尽快的被释放,但同时引入的问题就是会占用更多cpu资源,而占用更多cpu资源就需要引入多线程,我们redis没有引入定时器,在我个人看来就是因为redis是单线程的,虽然之后改成了支持多线程,但那也是之后的事情

那来说一下我个人会怎么实现这个定时删除

首先我们要引入一个定时器,可以基于优先级队列也可以通过时间轮,如果通过优先级队列,我们可以把过期时间早的,设置成高优先级,过期时间早的就可以先出队列,这时队首元素就是最早要过期的key,我们就不要遍历所有key来判断过期时间,只需要判断队首key的过期时间即可,但是虽然这个要在多线程情况下执行,需要分配一个线程,但是一直判断队首key时间也会导致cpu占用率过高,这时我们需要设置一个等待时间,等时间到了再去唤醒这个线程

如果在等待时来了一个新的线程,就需要先唤醒下刚才的线程,重新检查队首元素,重新设置阻塞时间。

通过时间轮就是把时间划成几个小段每个小段代表不同的时间,类似于哈希表的结构(但是跟名字一样,是一个圈),每个小段里是一个链表,每个链表代表一个要执行的任务,我们每次添加一个key如果有过期时间就会放入对应的小段链表中,每次走到这个各自,就会尝试一下这个链表上的任务

我认为,上述通过优先级队列和时间轮实现定时器的方法可以很好的解决问题

6.type

返回key对应value的数据类型

时间复杂度O(1)

相关推荐
A_cot2 小时前
深入了解 Maven 和 Redis
java·redis·maven
Lojarro2 小时前
后端-navicat查找语句(单表与多表)
数据库·mysql
月泪同学2 小时前
数据库面试题整理
数据库·mysql·面试
寻找09之夏4 小时前
优化Web性能:Varnish中精准识别并缓存移动与桌面请求
缓存·varnish
程序员学习随笔4 小时前
PostgreSQL技术内幕11:PostgreSQL事务原理解析-MVCC
数据库·postgresql
莫叫石榴姐5 小时前
一份热乎的阿里25届数据分析面试题
数据库·数据仓库·sql·算法·数据挖掘·数据分析
cong*5 小时前
数据库提权【笔记总结】
数据库·笔记·adb
没明白白6 小时前
Redis 缓存雪崩、缓存穿透、缓存击穿详解
数据库·redis·缓存
gbase_lmax6 小时前
gbase8s数据库常见的索引扫描方式
数据库