Redis数据结构和单线程

Redis 数据结构和内部编码

type 命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串)、list(列表)、hash(哈希)、set(集合)、zset(有序集合),但这些只是 Redis 对外的数据结构。
实际上 Redis 针对每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样 Redis 会
在合适的场景选择合适的内部编码

|--------|--------------------|
| 数据结构 | 内部编码 |
| string | raw int embstr |
| hash | hashtable ziplist |
| list | linkedlist ziplist |
| set | hashtable intset |
| zset | skiplist ziplist |

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

bash 复制代码
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"

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

单线程架构

现在开启了三个 redis-cli 客户端同时执行命令。

bash 复制代码
客户端 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

Redis 是采用单线程模型执行命令的是指:虽然三个客户端看起来是同时要求 Redis 去执行命令的,但微观角度,这些命令还是采用线性方式去执行的,只是原则上命令的执行顺序是不确定的,但一定不会有两条命令被同步执行。

可以想象 Redis 内部只有一个服务窗口,多个客户端按照它们达到的先后顺序被排队在窗口前,依次接受 Redis 的服务,所以两条 incr 命令无论执行顺序,结果一定是 2,不会发生并发问题,这个就是 Redis 的单线程执行模型。

为什么单线程还能这么快

a. 纯内存访问。Redis 将所有数据存放在内存中,内存的响应时长大约为 100 纳秒,这是 Redis 能够实现高性能访问的重要基础。

b. 非阻塞 IO。Redis 使用 epoll 作为 I/O 多路复用技术的实现,再结合自身的事件处理模型,将 epoll 中的连接、读写、关闭等操作转换为事件,不在网络 I/O 上浪费过多时间,如图所示。

c. 单线程避免了线程切换和竞态产生的消耗。单线程可以简化数据结构和算法的实现,让程序模型更简单;同时避免了多线程环境下,因竞争共享数据而产生的线程切换与等待开销。

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

相关推荐
2601_962297481 小时前
在python3中、下列输出变量a的正确写法是_2020超星大数据Python免费答案
数据结构·python·算法·编程·字符串操作
坐吃山猪1 小时前
【多线程】Lock与Condition
大数据·数据库
互联网叫兽1 小时前
redis深入学习一
redis
Lightpwd2 小时前
Spring Boot 多数据源落地:AbstractRoutingDataSource + 注解切面(附源码)
数据库·后端
LabVIEW开发2 小时前
LabVIEW 64位安装的位深陷阱:工具包、内存与工程兼容
数据库·labview·labview知识·labview功能·labview程序
寺中人2 小时前
MySQL 8.0 Windows 完整安装教程:环境配置、密码重置与常见报错排查
数据库·windows·mysql·环境搭建·mysql 安装
这个DBA有点耶2 小时前
同样48核配置TPS差1倍?高性价比数据库一体机的“软硬协同”才是分水岭
服务器·数据库·架构
shehuiyuelaiyuehao2 小时前
算法29,前缀和,除自身以外的数组的乘积
java·数据结构·算法
这个DBA有点耶2 小时前
MySQL 8.0执行计划分析利器:EXPLAIN ANALYZE到底比EXPLAIN强在哪?
数据库·mysql·代码规范