☰
Redis 之 【核心特性、全局命令、数据结构与内部编码、单线程模型】
2026/9/27 11:32:33 网站建设 项目流程

目录

1. Redis 概述与核心特性

1.1 什么是 Redis

1.2 8 大重要特性

1.3 为什么 Redis 这么快

1.4 典型应用场景

1.5 Redis 不适合做什么

2. 版本演进关键点

3. 全局命令与键管理

4. 数据结构与内部编码

4.1 对外数据结构 vs 内部编码

4.2 查看内部编码:OBJECT ENCODING key

4.3 为什么要有多种内部编码

5. 单线程模型

5.1 什么是单线程

5.2 为什么单线程能支撑高并发

5.3 单线程的致命弱点

5.4 引入多线程 I/O 后,还是单线程吗


1. Redis 概述与核心特性

1.1 什么是 Redis

  • 基于键值对(key-value)的 NoSQL 数据库
  • 值支持多种数据结构:string、hash、list、set、zset、Bitmaps、HyperLogLog、GEO 等
  • 数据全在内存中
  • 支持持久化(RDB + AOF)、主从复制、哨兵高可用、集群分布式

1.2 8 大重要特性

特性说明
速度快内存存储 + C语言 + 单线程 + 精良源码
基于键值对的数据结构服务器值可以是多种数据结构,开发灵活
功能丰富过期、发布订阅、Lua脚本、事务、Pipeline
简单稳定源码少(早期2万行),单线程模型简单,极少因自身BUG宕机
客户端语言多几乎覆盖所有主流语言(Java、Python、Go、Node…)
持久化RDB 快照 + AOF 日志,保证数据不丢失
主从复制支持多个副本,分布式基础
高可用与分布式Sentinel 故障自动转移,Cluster 真正分布式

Redis 的发布订阅(Pub/Sub)是一种基于频道(channel)的消息广播机制:发布者通过 `PUBLISH` 向指定频道发送消息,所有已通过 `SUBSCRIBE` 订阅该频道的客户端都会实时收到消息,也支持 `PSUBSCRIBE` 按模式订阅;Redis 服务器充当消息中转站,实现发布者与订阅者之间的解耦和一对多通信。其特点是轻量、实时、低延迟,但消息不持久化、不保证可靠投递,订阅者离线或断开期间的消息会丢失,也没有 ACK 和消费组机制,因此更适合实时通知、聊天、广播等允许丢失的场景;若需要可靠消息,通常应使用 Redis Stream 或专业消息队列

1.3 为什么 Redis 这么快

  • 纯内存访问:内存延迟约比磁盘快几个数量级
  • 非阻塞 I/O:基于 epoll 的 I/O 多路复用,将网络事件转化为事件驱动
  • 单线程模型:避免线程切换和竞态消耗,简化数据结构和算法
  • C 语言实现,更“接近”操作系统

1.4 典型应用场景

  • 缓存(键过期 + 淘汰策略)
  • 排行榜(有序集合 zset)
  • 计数器(视频播放数、电商浏览数)
  • 社交网络(赞/踩、粉丝、共同好友)
  • 消息队列(发布订阅 + 阻塞队列)

1.5 Redis 不适合做什么

  • 大规模冷数据:内存成本极高,不适合存储海量不常访问的数据
  • 复杂关系查询:非关系型,不适合 SQL 多表联查
  • 数据量极大且经济敏感:如每天数亿用户行为,用 Redis 存储是“无底洞”

2. 版本演进关键点

Redis 版本号规则:第二位偶数 = 稳定版(如 2.8、3.0、4.0、5.0、6.0、7.0),奇数 = 开发版

版本核心新特性
2.6服务端 Lua 脚本;毫秒级过期;从节点只读
2.8部分主从复制(PSYNC);Sentinel 第二版(生产可用)
3.0Redis Cluster(官方分布式实现);LRU 优化
3.2GEO(地理位置)功能;quicklist 编码
4.0模块系统;LFU淘汰算法;异步删除(unlink);RDB-AOF 混合持久化
5.0Stream数据类型(消息队列增强);redis-cli 集群管理器从 Ruby 移植到 C
6.0多线程 I/O(但命令执行仍是单线程);ACL 权限控制;RESP3 协议;客户端缓存
7.0AOF 多文件存储;RDB 版本升级至 10,不兼容旧版;listpack 替换 ziplist;protected-mode 默认开启

6.0 的多线程仅用于网络读写和协议解析,命令执行仍然单线程,不需要担心并发安全问题

3. 全局命令与键管理

所有数据结构共用的命令,注意其时间复杂度和使用注意事项

命令作用时间复杂度注意
KEYS pattern返回匹配模式的所有 keyO(N)生产环境禁用,会阻塞 Redis
EXISTS key判断 key 是否存在O(1)可同时检查多个,返回存在的个数
DEL key删除指定 keyO(1)删除大 key 时建议用UNLINK(异步)
EXPIRE key seconds设置秒级过期时间O(1)返回 1 成功,0 失败
TTL key查看剩余过期时间(秒)O(1)-1 表示永不过期,-2 表示 key 不存在
TYPE key

返回当前键对应 value 的

对外数据类型

O(1)返回值:string, list, hash, set, zset, stream 等
  • KEYS * 绝对不要在生产使用!它会扫描全库,阻塞所有命令。替代方案:SCAN 游标迭代
  • EXPIRE 和 TTL 还有毫秒版本 PEXPIRE / PTTL

4. 数据结构与内部编码

Redis 对外暴露 5 种数据类型,但底层有多种内部编码,根据场景动态切换

4.1 对外数据结构 vs 内部编码

数据结构可能的内部编码
stringraw,int,embstr
hashhashtable,ziplist(7.0 后改为 listpack)
listlinkedlist,ziplist(3.2 后统一为quicklist)
sethashtable,intset
zsetskiplist,ziplist(7.0 后改为 listpack)

4.2 查看内部编码:OBJECT ENCODING key

4.3 为什么要有多种内部编码

  • 解耦升级:优化内部编码不影响外部命令,如 3.2 引入 quicklist 用户无感知
  • 场景适配:ziplist 节省内存但元素多时性能下降,达到阈值会转为 hashtable 或 skiplist

7.0 重要变化:ziplist 被 listpack 替代,且 RDB 版本升级至 10,旧版 RDB 无法直接读取

5. 单线程模型

5.1 什么是单线程

  • Redis 服务端命令执行是单线程的,所有客户端请求排队依次处理
  • 微观上,命令按到达顺序线性执行,不存在两条命令同时执行

5.2 为什么单线程能支撑高并发

  • 内存操作极快,瓶颈不在 CPU 而在网络 I/O
  • 非阻塞 I/O + 多路复用(epoll),将连接、读写、关闭注册为事件,不浪费 CPU 等待
  • 无上下文切换和无锁竞争,性能更稳定

5.3 单线程的致命弱点

单个命令执行时间过长会阻塞后续所有命令。因此严禁大 key 操作(如 KEYS *、大集合交集等)

5.4 引入多线程 I/O 后,还是单线程吗

命令执行仍为单线程。多线程仅用于网络数据读写和协议解析,所以并发安全性依然由单线程保证

Redis 6.0 引入的多线程机制是一种混合式设计,其核心是将网络 I/O 的读写操作交由多个 I/O 线程并行处理,而命令的解析与执行依然由主线程单线程串行完成。具体来说,主线程负责接收连接并将可读的 socket 通过轮询分发给 I/O 线程进行读取和解析,随后主线程串行执行命令,执行完毕后再由 I/O 线程将结果写回客户端。这一设计旨在解决高并发下网络 I/O 成为瓶颈的问题,通过利用多核 CPU 提升网络数据的读写效率。由于命令执行阶段仍保持单线程,所以它避免了多线程带来的数据竞争和并发安全问题,在提升吞吐量的同时,保留了单线程模型简单、原子性的优点。该特性默认关闭,需通过 io-threads 等参数手动启用

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询