大家好,这篇文章带来的是有关Redis的相关内容讲解,希望各位能够有所收获~
1.set
给指定的键(Key)设置一个值(Value),覆盖已存在的旧值。
set key value
类似哈希表一样设置key和value的映射
2.get
根据键(Key),获取对应的值(Value)
get key
如果key 不存在,返回(nil)(等同于空值)
如果 key 对应的不是字符串类型(比如是列表、哈希),会报错。
值的类型:SET/GET只能存字符串,但字符串可以是:
- 普通文本(名字、描述)
- 数字(年龄、金额)
- JSON 字符串(对象数据)
- 二进制数据(图片、文件)
3.keys
3.1pattern
pattern模式匹配
- * --- 0-n个字符匹配
- ? --- 一个字符匹配
- [^x] --- 除了x的其他 --- [^xy]除了x/y的其他
- [a-z] --- 匹配a-z
- [abc] --- 匹配a/b/c --- [a^b] 匹配a/^/b
3.2风险
keys的时间复杂度:O(N)
如果使用keys *将在生产环境卡住redis服务器(单线程),出现大问题导致其他业务瘫痪
4.环境
办公环境(入职公司之后,公司给你发个电脑)
开发环境(有的时候,开发环境和办公环境是一个,有的时候,开发环境是单独的服务器)
测试环境(测试工程师使用的)
线上环境/生产环境(线上环境则是外界用户能够访问到的,一旦生产环境上出问题,一定会对于用户的使用产生影响)
5.exists
判定key是否存在 exists key [key ...]
返回key存在的个数 - 针对多个key来说
时间复杂度:O(1)
redis组织这些key就是按照哈希表的方式来组织的
redis支持很多数据结构 -> 指的是一个value可以是一些复杂度数据结构
redis自身的这些键值对,是通过哈希表的方式来组织的
redis具体的某个值,又可以是一些数据结构
上面这两种写法
分开的写法,会产生更多轮次的网络通信(和直接操作内存比效率是比较低的,成本是比较高的)
进行网络通信的时候,发送方发送一个数据,这个数据就要从应用层到物理层,层层封装
每一层协议都要加上报头或者尾 -> 发一个快递,要包装一下,要包装多层
接收方收到一个数据,这个数据就要从物理层到应用层层层分用
每一层协议中的报头或者尾拆掉 -> 收到一个快递,要拆快递,要拆很多层
redis 中很多命令都是支持一次就能操作多个key的多种操作
6.del(delete)
删除指定的key,可以一次删除一个或者多个
del key [key ...]
时间复杂度:O(1)
返回值:删除的key的个数
redis主要的应用场景,就是作为缓存
此时redis里面存的只是一个热点数据,全量数据是在mysql数据库中
此时,如果把redis中的key删除了几个,一般来说,问题不大
但是,当然如果把所有的数据或者一大半数据一下都干没了,这种影响就很大了
(大部分请求直接打给mysql容易把mysql搞挂)
如果是把redis作为数据库,此时就很大了
如果redis作为消息队列,这种情况误删数据就要视情况而定
7.expire
expire key seconds
作用是给指定的key设置过期时间
key存活时间超出这个指定的值,就会被自动删除
很多业务场景,是有时间限制的 --- 手机验证码这种
基于redis实现分布式锁,为了避免出现不能正确解锁的情况,通常会在加锁的时候设置一下过期时间。(所谓使用redis作为分布式锁,就是给redis里面写一个特殊的key value)
expire设置的时间单位是秒,如果要毫秒这种可以采用pexpire
expire设置的key是要已经存在的被set的
设置成功返回1,设置失败返回0
8.ttl
time to live 存活时间
IP协议报头中,就有一个字段TTL
IP中的TTL不是用时间衡量过期的,而是用次数的
这里的就单纯是一个时间 ttl 单位s ,pttl 单位 ms
9.redis的key的过期策略
一个redis中可能同时存在很多很多key,这些key可能有很大一部分都有过期时间,此时,redis服务器咋知道哪些key已经过期要被删除,哪些key还没过期??
如果直接遍历所有的key,显然是行不通的,效率非常低~
redis整体策略
1.定期删除 - 每次抽取一部分,进行验证过期时间,保证这个抽取检查足够快(避免出现长时间检查导致正常业务被阻塞)
2.惰性删除 - 假设这个key已经到过期时间了,但是暂时还没删它,key还存在,紧接着,后面有一次访问,正好用到这个key,于是这次访问就会让redis服务器触发删除key的操作,同时再返回一个nil
虽然有上面两种策略结合,整体的效率还是一般,仍然可能会有很多过期的key被残留,没有及时删除掉!
redis为了对于上述进行补充,还提供了一系列的内存淘汰策略。
定时器(了解)
定时器:在某个时间到达之后,执行指定的任务
1.基于优先级队列 / 堆
将多个key设置过期时间
就可以把这些key加入到一个优先级队列中,指定优先级规则是过期时间早的,先出队列
队首元素,就是最早的要过期的key
此时定时器中只要分配一个线程,让这个线程去检查队首元素,看是否过期即可
如果队首元素还没过期,后续元素一定没过期
此时,扫描线程不需要遍历所有key,只盯住这个队首元素即可
另外在扫描检查的时候,不能太频繁,此时做法就是根据当前时刻和队首元素的过期时间设置一个等待,当时间差不多了,再唤醒这个线程
此时,扫描线程不需要高频的扫描队首元素,把cpu的开销节省下来了
万一在线程休眠的时候,来了一个新任务,可以在新任务添加的时候,唤醒一下刚才的线程,重新检查一下队首元素,再根据时间差距重新调整阻塞时间即可。
2.基于时间轮
把时间划分成很多小段(划分粒度,看实际需求)
每个小段都挂着一个链表,每个链表都代表一个要执行的任务
每次隔固定时间间隔走一个格子,到了一个格子就去尝试执行下其中的任务,对于时间轮来说,每个格子是多少时间,一共多少个格子,都是需要根据实际场景,灵活调配的
Tips:此处仅为扩展,redis并未采取上面的方案,但是这两种方案都是属于高效的定时器的实现方式,很多场景都可能用到
在Redis原码中,有一个比较核心的机制是事件循环。(类似时间轮又有不同)
10.type
redis所有的key都是string类型,key对应的value可能会存在多种类型
none, string, list, set, zset, hash 和 stream (redis作为消息队列时,使用这个类型的value)等等
type key
查询对应key的类型
时间复杂度:O(1)
11.查询地址
大家要是想要查询对应更多信息最好的就是去官方网站查询
网址:redis.io
希望大家能够有所收获~