redis常见数据类型

目录

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。

实例:

cpp 复制代码
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是否存在。
语法:

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

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

cpp 复制代码
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。
语法:

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

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

cpp 复制代码
redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> DEL key1 key2 key3
(integer) 2

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

cpp 复制代码
EXPIRE key seconds 

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

cpp 复制代码
redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10

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

cpp 复制代码
TTL key

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

cpp 复制代码
redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10

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

键的过期机制:

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

cpp 复制代码
TYPE key 

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

cpp 复制代码
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命令查询内部编码:

cpp 复制代码
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设置一个字符串键值对:

cpp 复制代码
127.0.0.1:6379> set hello world 

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

cpp 复制代码
127.0.0.1:6379> incr counter 

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

cpp 复制代码
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是面向快速执行场景的数据库

相关推荐
m0_748248027 分钟前
Redis 简介与安装指南
数据库·redis·缓存
Elastic 中国社区官方博客5 小时前
在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
编程爱好者熊浪7 小时前
两次连接池泄露的BUG
java·数据库
cr7xin8 小时前
缓存三大问题及解决方案
redis·后端·缓存
爱怪笑的小杰杰8 小时前
浏览器端缓存地图请求:使用 IndexedDB + ajax-hook 提升地图加载速度
ajax·okhttp·缓存
TDengine (老段)8 小时前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
qq7422349849 小时前
Python操作数据库之pyodbc
开发语言·数据库·python
姚远Oracle ACE9 小时前
Oracle 如何计算 AWR 报告中的 Sessions 数量
数据库·oracle
Dxy12393102169 小时前
MySQL的SUBSTRING函数详解与应用
数据库·mysql
码力引擎10 小时前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节