402 lines
9.8 KiB
Markdown
402 lines
9.8 KiB
Markdown
# Redis 基础概念
|
||
|
||
## NoSQL 数据库概述
|
||
|
||
### NoSQL 数据库的特点和分类
|
||
|
||
NoSQL(Not Only SQL)数据库是一类非关系型数据库的统称,它们不使用传统的表格关系模型来存储数据。NoSQL 数据库具有以下特点:
|
||
|
||
**主要特点:**
|
||
- **灵活的数据模型**:支持多种数据结构,如键值对、文档、列族、图等
|
||
- **水平扩展性**:易于在多台服务器间分布数据
|
||
- **高性能**:针对特定用例优化,读写性能优异
|
||
- **高可用性**:支持分布式部署,具备容错能力
|
||
- **最终一致性**:放宽了 ACID 约束,采用 BASE 理论
|
||
|
||
**NoSQL 数据库分类:**
|
||
|
||
1. **键值存储(Key-Value Store)**
|
||
- 代表产品:Redis、Amazon DynamoDB、Riak
|
||
- 特点:简单的键值对存储,查询速度快
|
||
- 适用场景:缓存、会话存储、购物车
|
||
|
||
2. **文档数据库(Document Database)**
|
||
- 代表产品:MongoDB、CouchDB、Amazon DocumentDB
|
||
- 特点:存储半结构化文档(如 JSON、XML)
|
||
- 适用场景:内容管理、用户配置、产品目录
|
||
|
||
3. **列族数据库(Column Family)**
|
||
- 代表产品:Cassandra、HBase、Amazon SimpleDB
|
||
- 特点:按列存储数据,适合大数据分析
|
||
- 适用场景:时间序列数据、日志分析、IoT 数据
|
||
|
||
4. **图数据库(Graph Database)**
|
||
- 代表产品:Neo4j、Amazon Neptune、ArangoDB
|
||
- 特点:存储节点和关系,擅长处理复杂关联
|
||
- 适用场景:社交网络、推荐系统、知识图谱
|
||
|
||
### 关系型数据库 vs NoSQL 数据库
|
||
|
||
| 特性 | 关系型数据库 (RDBMS) | NoSQL 数据库 |
|
||
|------|---------------------|---------------|
|
||
| **数据模型** | 表格结构,固定模式 | 灵活模式,多种数据结构 |
|
||
| **扩展性** | 垂直扩展(Scale Up) | 水平扩展(Scale Out) |
|
||
| **一致性** | 强一致性(ACID) | 最终一致性(BASE) |
|
||
| **查询语言** | 标准 SQL | 各自专有 API |
|
||
| **事务支持** | 完整的 ACID 事务 | 有限的事务支持 |
|
||
| **性能** | 复杂查询性能好 | 简单操作性能优异 |
|
||
| **成本** | 许可费用高 | 多数开源免费 |
|
||
| **适用场景** | 复杂业务逻辑,强一致性要求 | 大数据,高并发,快速开发 |
|
||
|
||
### NoSQL 数据库的应用场景
|
||
|
||
**1. 大数据处理**
|
||
- 海量数据存储和分析
|
||
- 实时数据处理
|
||
- 数据仓库和数据湖
|
||
|
||
**2. 高并发 Web 应用**
|
||
- 社交媒体平台
|
||
- 电商网站
|
||
- 在线游戏
|
||
|
||
**3. 实时应用**
|
||
- 实时推荐系统
|
||
- 实时监控和告警
|
||
- 实时聊天应用
|
||
|
||
**4. 内容管理**
|
||
- 内容发布系统
|
||
- 数字资产管理
|
||
- 多媒体存储
|
||
|
||
**5. IoT 和传感器数据**
|
||
- 设备数据收集
|
||
- 时间序列数据
|
||
- 地理位置数据
|
||
|
||
## Redis 简介
|
||
|
||
### Redis 的定义和特点
|
||
|
||
**Redis**(Remote Dictionary Server)是一个开源的、基于内存的键值对数据库,由 Salvatore Sanfilippo 于 2009 年开发。Redis 以其卓越的性能和丰富的数据结构而闻名。
|
||
|
||
**核心特点:**
|
||
|
||
1. **内存存储**
|
||
- 所有数据存储在内存中,读写速度极快
|
||
- 支持数据持久化到磁盘
|
||
- 内存使用效率高
|
||
|
||
2. **丰富的数据结构**
|
||
- 支持字符串、列表、集合、有序集合、哈希等
|
||
- 每种数据结构都有专门的操作命令
|
||
- 支持复杂的数据操作
|
||
|
||
3. **高性能**
|
||
- 单线程模型,避免锁竞争
|
||
- 基于事件驱动的 I/O 多路复用
|
||
- 读写性能可达 10 万+ QPS
|
||
|
||
4. **持久化支持**
|
||
- RDB 快照持久化
|
||
- AOF 日志持久化
|
||
- 混合持久化模式
|
||
|
||
5. **高可用性**
|
||
- 主从复制
|
||
- 哨兵模式
|
||
- 集群模式
|
||
|
||
6. **原子性操作**
|
||
- 所有操作都是原子性的
|
||
- 支持事务
|
||
- 支持 Lua 脚本
|
||
|
||
### Redis 的数据结构
|
||
|
||
Redis 支持五种基本数据结构:
|
||
|
||
**1. 字符串(String)**
|
||
```shell
|
||
# 基本操作
|
||
SET key "Hello Redis"
|
||
GET key
|
||
INCR counter
|
||
DECR counter
|
||
```
|
||
|
||
**2. 列表(List)**
|
||
```shell
|
||
# 列表操作
|
||
LPUSH mylist "world"
|
||
LPUSH mylist "hello"
|
||
LRANGE mylist 0 -1
|
||
```
|
||
|
||
**3. 集合(Set)**
|
||
```shell
|
||
# 集合操作
|
||
SADD myset "apple"
|
||
SADD myset "banana"
|
||
SMEMBERS myset
|
||
```
|
||
|
||
**4. 有序集合(Sorted Set)**
|
||
```shell
|
||
# 有序集合操作
|
||
ZADD leaderboard 100 "player1"
|
||
ZADD leaderboard 200 "player2"
|
||
ZRANGE leaderboard 0 -1 WITHSCORES
|
||
```
|
||
|
||
**5. 哈希(Hash)**
|
||
```shell
|
||
# 哈希操作
|
||
HSET user:1 name "John"
|
||
HSET user:1 age 30
|
||
HGETALL user:1
|
||
```
|
||
|
||
### Redis 的应用场景
|
||
|
||
**1. 缓存系统**
|
||
- 数据库查询结果缓存
|
||
- 页面缓存
|
||
- 对象缓存
|
||
- 减少数据库压力,提高响应速度
|
||
|
||
**2. 会话存储**
|
||
- Web 应用会话管理
|
||
- 分布式会话共享
|
||
- 用户状态保持
|
||
|
||
**3. 消息队列**
|
||
- 发布/订阅模式
|
||
- 任务队列
|
||
- 实时消息推送
|
||
|
||
**4. 排行榜和计数器**
|
||
- 游戏排行榜
|
||
- 网站访问统计
|
||
- 点赞数、评论数统计
|
||
|
||
**5. 分布式锁**
|
||
- 防止并发操作冲突
|
||
- 资源访问控制
|
||
- 分布式系统协调
|
||
|
||
**6. 实时分析**
|
||
- 实时数据统计
|
||
- 用户行为分析
|
||
- 业务指标监控
|
||
|
||
### Redis 的优势和局限性
|
||
|
||
**优势:**
|
||
|
||
1. **极高的性能**
|
||
- 内存操作,读写速度快
|
||
- 单线程模型,无锁竞争
|
||
- 支持管道操作,批量处理
|
||
|
||
2. **丰富的数据结构**
|
||
- 多种数据类型满足不同需求
|
||
- 原生支持复杂操作
|
||
- 减少应用层代码复杂度
|
||
|
||
3. **高可用性**
|
||
- 多种部署模式
|
||
- 自动故障转移
|
||
- 数据冗余保护
|
||
|
||
4. **易于使用**
|
||
- 简单的命令接口
|
||
- 丰富的客户端库
|
||
- 详细的文档支持
|
||
|
||
5. **活跃的社区**
|
||
- 开源免费
|
||
- 持续更新
|
||
- 广泛的生态系统
|
||
|
||
**局限性:**
|
||
|
||
1. **内存限制**
|
||
- 数据量受内存大小限制
|
||
- 内存成本相对较高
|
||
- 需要合理的内存管理策略
|
||
|
||
2. **单线程模型**
|
||
- CPU 密集型操作可能阻塞
|
||
- 无法充分利用多核 CPU
|
||
- 大数据量操作需要优化
|
||
|
||
3. **持久化开销**
|
||
- RDB 快照可能丢失数据
|
||
- AOF 日志影响性能
|
||
- 需要权衡性能和数据安全
|
||
|
||
4. **复杂查询支持有限**
|
||
- 不支持复杂的关联查询
|
||
- 没有标准的查询语言
|
||
- 需要在应用层处理复杂逻辑
|
||
|
||
## Redis 架构
|
||
|
||
### Redis 的内存模型
|
||
|
||
Redis 采用内存存储模型,所有数据都保存在内存中,这是其高性能的关键所在。
|
||
|
||
**内存布局:**
|
||
|
||
1. **数据存储区域**
|
||
- 用户数据:存储实际的键值对数据
|
||
- 过期字典:存储键的过期时间信息
|
||
- 数据库字典:存储不同数据库的数据
|
||
|
||
2. **缓冲区域**
|
||
- 输入缓冲区:存储客户端发送的命令
|
||
- 输出缓冲区:存储返回给客户端的结果
|
||
- AOF 缓冲区:存储 AOF 日志数据
|
||
|
||
3. **复制缓冲区**
|
||
- 复制积压缓冲区:主从复制时使用
|
||
- 从服务器输出缓冲区:向从服务器发送数据
|
||
|
||
**内存管理策略:**
|
||
|
||
1. **内存分配**
|
||
- 使用 jemalloc 内存分配器
|
||
- 减少内存碎片
|
||
- 提高内存使用效率
|
||
|
||
2. **内存回收**
|
||
- 过期键删除:定期删除和惰性删除
|
||
- 内存淘汰策略:LRU、LFU、随机等
|
||
- 内存压缩:对小对象进行压缩存储
|
||
|
||
### Redis 的线程模型演进
|
||
|
||
Redis 的线程模型在不同版本中有重要演进,从单线程到混合线程模型。
|
||
|
||
**Redis 6.0 之前:单线程模型**
|
||
|
||
Redis 6.0 之前采用单线程模型处理所有客户端请求:
|
||
|
||
1. **单线程特点**
|
||
- 主线程处理所有网络 I/O 和命令执行
|
||
- 避免锁竞争和上下文切换
|
||
- 保证操作的原子性
|
||
- 简化代码实现和调试
|
||
|
||
2. **单线程优势**
|
||
- 无需考虑线程安全问题
|
||
- CPU 缓存命中率高
|
||
- 减少内存访问延迟
|
||
- 所有操作都是原子性的
|
||
|
||
**Redis 6.0+:混合线程模型**
|
||
|
||
Redis 6.0 引入了多线程 I/O 处理,但保持命令执行的单线程特性:
|
||
|
||
1. **多线程 I/O 处理**
|
||
- 网络 I/O 读写使用多线程
|
||
- 提高网络吞吐量
|
||
- 减少网络延迟
|
||
- 更好地利用多核 CPU
|
||
|
||
2. **单线程命令执行**
|
||
- 命令解析和执行仍在主线程
|
||
- 保持数据操作的原子性
|
||
- 避免复杂的锁机制
|
||
- 确保数据一致性
|
||
|
||
3. **线程模型配置**
|
||
```bash
|
||
# 启用多线程 I/O(默认关闭)
|
||
io-threads-do-reads yes
|
||
|
||
# 设置 I/O 线程数量(建议为 CPU 核心数)
|
||
io-threads 4
|
||
```
|
||
|
||
**为什么 Redis 仍能保持高性能?**
|
||
|
||
1. **内存操作优势**
|
||
- 所有数据在内存中,访问速度快
|
||
- 避免磁盘 I/O 延迟
|
||
- 内存带宽充分利用
|
||
- 高效的内存管理
|
||
|
||
2. **优化的数据结构**
|
||
- 针对不同场景优化的数据结构
|
||
- 减少不必要的内存拷贝
|
||
- 高效的算法实现
|
||
- 内存压缩和优化
|
||
|
||
3. **事件驱动架构**
|
||
- 非阻塞 I/O 模型
|
||
- 事件循环处理
|
||
- 高并发连接支持
|
||
- 异步处理机制
|
||
|
||
4. **多线程 I/O 优化**
|
||
- 网络 I/O 并行处理
|
||
- 减少网络瓶颈
|
||
- 提高整体吞吐量
|
||
- 更好的资源利用
|
||
|
||
### Redis 的事件驱动机制
|
||
|
||
Redis 使用事件驱动模型来处理客户端请求和内部任务。
|
||
|
||
**事件类型:**
|
||
|
||
1. **文件事件(File Event)**
|
||
- 处理客户端连接
|
||
- 读取客户端命令
|
||
- 发送响应数据
|
||
- 基于 I/O 多路复用实现
|
||
|
||
2. **时间事件(Time Event)**
|
||
- 定期执行的任务
|
||
- 过期键清理
|
||
- 统计信息更新
|
||
- 持久化操作
|
||
|
||
**事件处理流程:**
|
||
|
||
```
|
||
1. 等待事件发生
|
||
↓
|
||
2. 处理文件事件
|
||
↓
|
||
3. 处理时间事件
|
||
↓
|
||
4. 返回步骤1
|
||
```
|
||
|
||
**I/O 多路复用:**
|
||
|
||
Redis 根据不同平台选择最优的 I/O 多路复用实现:
|
||
- Linux:epoll
|
||
- macOS/FreeBSD:kqueue
|
||
- Windows:select
|
||
|
||
**事件循环优势:**
|
||
|
||
1. **高并发支持**
|
||
- 单线程处理多个客户端
|
||
- 避免线程创建开销
|
||
- 内存使用效率高
|
||
|
||
2. **响应及时**
|
||
- 事件驱动,实时响应
|
||
- 无阻塞等待
|
||
- 低延迟处理
|
||
|
||
3. **资源利用率高**
|
||
- CPU 利用率高
|
||
- 内存占用少
|
||
- 系统资源消耗低 |