Redis基础(1)--基本全局指令与架构
1. 基本全局命令
Redis有5种数据结构,但它们都是键值对中的值,对于键来说有⼀些通用的命令。
1.1KEYS
返回所有满足样式(pattern)的key。支持如下统配样式。
- h?llo 匹配 hello , hallo 和hxllo
- h*llo 匹配 hllo 和 heeeello
- h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo
- h[^e]llo 匹配 hallo , hbllo ,…但不匹配 hello
- h[a-b]llo 匹配 hallo 和 hbllo
语法:KEYS pattern
命令有效版本:1.0.0之后
时间复杂度:O(N)
返回值:匹配pattern的所有key。
1.2 EXISTS
判断某个key是否存在。
语法:EXISTS key [key ...]
命令有效版本:1.0.0之后
时间复杂度:O(1)
返回值:key存在的个数。
注意:exists能够同时查看多个key是否存在,为什么要这样做?
因为Redis是客户端服务器模式的,每条指令会封装成网络请求发给服务端,服务端在接收到请求后解包,处理并将结果封装发回给客户端,封装和解包必然是要消耗性性能的。
1.3 DEL
删除指定的key。
语法:DEL key [key ...]
命令有效版本:1.0.0之后
时间复杂度:O(1)
返回值:删除掉的key的个数。
1.4 EXPIRE
为指定的 key 添加秒级的过期时间(Time To Live TTL)
语法:EXPIRE key seconds
命令有效版本:1.0.0之后
时间复杂度:O(1)
返回值:1表示设置成功。0表示设置失败
PEXPIRE
:设置毫米级到期时间
1.5 TTL
获取指定 key 的过期时间,秒级。
TTL key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示 key 不存在。
注意:IP协议首部也有TTL,这个TTL本质上是一个计数器,当IP报文被路由器转发后,就会减一,减到0丢弃IP报文
键的过期机制
Redis主要用两种策略去处理过期的数据
- 定期删除:定期查看一部分键是否应该被删除,保证速度足够快,因为redis是单线程程序,不能够阻塞工作线程
- 惰性删除:访问时查看是否已经到期
注意:有了上面两种方案,还是有过期数据不会被删除的,redis还有内存淘汰机制去解决这个问题
定时器的两种高效实现
- 优先级队列:用优先级队列及堆来维护key的到期时间,到期时间最近的key放入堆顶,专门创建一个线程来维护这个堆,当有新的key被设置了到期时间,就将其加入到堆中,并且查看堆顶的到期时间,用其减去当前时间,得到需要等待的时间,让线程休眠等待的时间,有新的key被设置了到期时间,就唤醒线程
- 时间轮
1.6 TYPE
返回 key 对应 value 的数据类型。
语法:TYPE key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值: none
, string
,list
, set
,zset
,hash
and stream
.。
其中stream是消息队列用的
2. 单线程架构
Redis 使用了单线程架构来实现高性能的内存数据库服务,此处的单线程是只有一个线程来处理命令请求,并不是整个进程都只有一个线程,会有其他线程去处理IO。
2.1 单线程模型
当三个客户端同时访问Redis服务器时,看似是同时到达并处理请求,实际请求到达一定有先有后,由于Redis是单线程的,一个时间段只能处理一个请求,其他的请求即使来了也只能排队等着。不会有多线程场景下的线程安全问题。
这也能解释了Redis为什么能这么快~
这个快是和数据库相比的
- Redis访问内存,而数据库访问磁盘
- Redis处理网络请求用的是IO多路转接方案
- Redis的核心功能比数据库的核心功能要简单,数据库对于数据的插入删除查询都有更复杂的功能支持,这样必然会造成额外的开销,比如:约束,要做额外的工作
- 单线程模型避免了没必要的线程竞争开销
redis操作都是短平快的,就是简单操作一下内存数据,不特别消耗cpu,使用多线程效率提升也不大