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 是面向快速执行场景的数据库。

相关推荐
小小龙学IT几秒前
Go 语言 database/sql 标准库深度解析:从连接池到驱动抽象
数据库·sql·golang
dtq04246 分钟前
数据结构 - 树的概念
c语言·数据结构·学习·算法
Seraphina3610 分钟前
SQL注入(一)
数据库·经验分享·笔记·sql·网络安全
anew___13 分钟前
《从零手写操作系统 (19):Ext2文件系统实战——从内存到磁盘的跨越》
java·服务器·前端·数据库·算法
Arcai102418 分钟前
SQL Server 备份和恢复完全指南:从入门到精通
数据库·sqlserver·数据恢复·数据备份·备份一体机·杭州智备
H.莓飛20 分钟前
【数据结构】栈
linux·开发语言·数据结构·算法·centos
XS03010625 分钟前
Redis 学习指南
数据库·redis·缓存
FPGA小徐28 分钟前
Qt 5.9 实战:实现一个自动图片轮播器
数据库
l1t33 分钟前
DeepSeek总结的pg_clickhouse 与 chdb 更新:编码、嵌套与类型
数据库·clickhouse·postgresql
傲世仙尊33 分钟前
从HTTPS到MySQL-会话保持的攻防与数据库的真面目
数据库·mysql·https