# 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 利用率高 - 内存占用少 - 系统资源消耗低