redis常见数据类型

发布时间:2023年12月23日

目录

1.基本全局命令

2.数据结构和内部编码

3.单线程架构


1.基本全局命令

Redis有5种数据结构,但它们都是键值对种的值,对于键来说有一些通用的命令。

KEYS
返回所有满足样式(pattern) 的key。支持如下统配样式。
h?llo 匹配 hello,? hallo和hxllo
h*llo匹配hllo和heeeello
h[ae]llo 匹配hello和hallo但不匹配hillo
h[^e]llo匹配hallo, hb1lo ....但不匹配heLlo
h[a-b]llo 匹配hallo和hbllo
语法:

KEYS pattern?

命令有效版本:1.0.0之后
时间复杂度:O(N)
返回值:匹配pattern的所有key。

实例:

redis> MSET firstname Jack lastname Stuntman age 35
"OK"
redis> KEYS *name*
1) "firstname"
2) "lastname"
redis> KEYS a??
1) "age"
redis> KEYS *
1) "age"
2) "firstname"
3) "lastname"

EXISTS
判断某个key是否存在。
语法:

EXISTS key [key ...]

命令有效版本: 1.0.0 之后.
时间复杂度: 0(1)
返回值: key 存在的个数。
示例:

redis> SET key1 "Hello"
"OK"
redis> EXISTS key1
(integer) 1
redis> EXISTS nosuchkey
(integer) 0
redis> SET key2 "World"
"OK"
redis> EXISTS key1 key2 nosuchkey
(integer) 2

DEL
删除指定的key。
语法:

DEL key [key ...] 

命令有效版本: 1.0.0之后
时间复杂度: 0(1)
返回值:删除掉的key的个数。
示例:

redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> DEL key1 key2 key3
(integer) 2

EXPIRE
为指定的key添加秒级的过期时间(Time To Live TTL)
语法:

EXPIRE key seconds 

命令有效版本: 1.0.0之后
时间复杂度: 0(1)
返回值:1表示设置成功。0表示设置失败。
示例:

redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10

TTL
获取指定key的过期时间,秒级。
语法:

TTL key

命令有效版本: 1.0.0 之后
时间复杂度: 0(1)
返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示key不存在。
示例:

redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10

EXPIRE和TTL命令都有对应的支持毫秒为单位的版本: PEXPIRE和 PTTL

键的过期机制:

TYPE
返回key对应的数据类型。
语法:

TYPE key 

命令有效版本: 1.0.0之后
时间复杂度: 0(1)
返回值:none , string,list, set, zset, hash and stream 。
示例:

redis> SET key1 "value"
"OK"
redis> LPUSH key2 "value"
(integer) 1
redis> SADD key3 "value"
(integer) 1
redis> TYPE key1
"string"
redis> TYPE key2
"list"
redis> TYPE key3
"set"

2.数据结构和内部编码

type命令实际返回的就是当前键的数据结构类型,它们分别是: string (字符串)、list (列表)、hash (哈希) 、set (集合)、zset (有序集合),但这些只是Redis对外的数据结构

Redis的5种数据类型

实际上Redis针对每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样Redis会
在合适的场景选择合适的内部编码,如表2-1所示。

表2-1Redis数据结构和内部编码

可以看到每种数据结构都有至少两种以上的内部编码实现,例如list数据结构包含了linkedlist 和
ziplist两种内部编码。同时有些内部编码,例如ziplist,可以作为多种数据结构的内部实现,可以通
过object encoding命令查询内部编码:

127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> lpush mylist a b c
(integer) 3
127.0.0.1:6379> object encoding hello
"embstr"
127.0.0.1:6379> object encoding mylist
"quicklist"

可以看到hello对应值的内部编码是embstr,键mylist对应值的内部编码是quicklist。
Redis这样设计有两个好处:
1) 可以改进内部编码,而对外的数据结构和命令没有任何影响,这样一 旦开发出更优秀的内部编码,无需改动外部数据结构和命令,例如Redis 3.2提供了quicklist,结合了ziplist 和linkedlist两者的优势,为列表类型提供了-种更为优秀的内部编码实现,而对用户来说基本无感知。
2)多种内部编码实现可以在不同场景下发挥各自的优势,例如ziplist比较节省内存,但是在列表元素
比较多的情况下,性能会下降,这时候Redis会根据配置选项将列表类型的内部实现转换为
linkedlist,整个过程用户同样无感知。

3.单线程架构

Redis使用了单线程架构来实现高性能的内存数据库服务,本节首先通过多个客户端命令调用的例
子说明Redis单线程命令处理机制,接着分析Redis单线程模型为什么性能如此之高,最终给出为什
么理解单线程模型是使用和运维Redis的关键。

1.引出单线程模型
现在开启了三个redis-cli客户端同时执行命令。
客户端1设置一个字符串键值对:

127.0.0.1:6379> set hello world 

客户端2对counter做自增操作:

127.0.0.1:6379> incr counter 


客户端3对counter做自增操作:

127.0.0.1:6379> incr counter 

我们已经知道从客户端发送的命令经历了:发送命令、执行命令、返回结果三个阶段,其中我们重点关注第2步。我们所谓的Redis是采用单线程模型执行命令的是指:虽然三个客户端看起来是同时要求Redis去执行命令的,但微观角度,这些命令还是采用线性方式去执行的,只是原则上命令的执行顺序是不确定的,但- -定不会有两条命令被同步执行,如图2-3、2-4、 2-5 所示,可以想象Redis内部只有一个服务窗口,多个客户端按照它们达到的先后顺序被排队在窗口前,依次接受Redis的服务,所以两条incr命令无论执行顺序,结果一定是2,不会发生并发问题,这个就是Redis的单线程执行模型。

宏观上同时要求服务的客户端:

微观上客户端发送命令的时间有先后次序的:

Redis的单线程模型

2.为什么单线程还能这么快
通常来讲,单线程处理能力要比多线程差,例如有10 000公斤货物,每辆车的运载能力是每次
200公斤,那么要50次才能完成;但是如果有50辆车,只要安排合理,只需要依次就可以完成任
务。那么为什么Redis使用单线程模型会达到每秒万级别的处理能力呢?可以将其归结为三点:
a.纯内存访问。Redis 将所有数据放在内存中,内存的响应时长大约为100纳秒,这是Redis达
到每秒万级别访问的重要基础。
b.非阻塞I0。Redis 使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型,
将epoll中的连接、读写、关闭都转换为事件,不在网络I/O.上浪费过多的时间,如图2-6所示。
c.单线程避免了线程切换和竞态产生的消耗。单线程可以简化数据结构和算法的实现,让程序模
型更简单;其次多线程避免了在线程竞争同一份共享数据时带来的切换和等待消耗。

redis使用IO多路复用模型:

虽然单线程给Redis带来很多好处,但还是有-个致命的问题:对于单个命令的执行时间都是有要求的。如果某个命令执行过长,会导致其他命令全部处于等待队列中,迟迟等不到响应,造成客户端的阻塞,对于Redis这种高性能的服务来说是非常严重的,所以Redis是面向快速执行场景的数据库

文章来源:https://blog.csdn.net/qq_65307907/article/details/134439736
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。