跳到主要内容

Redis 概览

为什么 Redis 很重要

Redis(Remote Dictionary Server)是现代后端系统中的关键组件:

  • 性能:内存操作,微秒级延迟(vs 基于磁盘数据库的毫秒级)
  • 多功能性:丰富的数据结构(字符串、哈希、列表、集合、有序集合)
  • 特性:发布/订阅、事务、Lua 脚本、集群
  • 使用场景:缓存、会话存储、排行榜、限流、消息队列

实际影响

  • 缓存频繁访问的数据可以减少 90% 的数据库负载
  • Redis 中的会话存储实现了 Web 服务器的水平扩展
  • 有序集合支持数百万用户的实时排行榜

示例

# 设置缓存(微秒级延迟)
SET user:123:name "Alice"
GET user:123:name # 返回 "Alice"

# 对比 MySQL:每次查询 10-100ms

Redis 一览

核心特性

  • 内存存储:所有数据存储在 RAM 中(快速)
  • 键值存储:通过键访问数据
  • 单线程:避免并发问题(但可通过集群使用多 CPU)
  • 数据结构:丰富的数据类型(不仅仅是字符串)
  • 持久化:可选(可以纯缓存或持久化)

常见使用场景

1. 缓存

目的:减少数据库负载,提升响应时间

# 缓存用户资料
HSET user:123 name "Alice" email "alice@example.com" age 25
HGET user:123 name # 返回 "Alice"

# 带 TTL 的缓存(1 小时后过期)
SETEX user:123:profile 3600 "Alice,alice@example.com,25"

优势

  • 比 MySQL 快 1000 倍(微秒 vs 毫秒)
  • 减少数据库负载(更少连接、更少 CPU)
  • 改善用户体验(更快的页面加载)

2. 会话存储

目的:存储用户会话(登录状态、购物车)

# 登录时设置会话数据
HSET session:abc123 user_id 123 login_time "2024-02-14T10:00:00Z"
EXPIRE session:abc123 3600 # 1 小时后过期

# 后续请求时检查会话
HEXISTS session:abc123 user_id # 返回 1(存在)
HGET session:abc123 user_id # 返回 123

优势

  • 跨多个 Web 服务器的共享会话存储(水平扩展)
  • 快速会话查找(微秒级延迟)
  • 自动过期(TTL)

3. 排行榜

目的:实时排名(游戏、社交媒体)

# 添加分数
ZADD leaderboard 1000 "alice" 950 "bob" 1200 "charlie"

# 获取前 10 名
ZREVRANGE leaderboard 0 9 WITHSCORES

# 获取用户排名
ZREVRANK leaderboard "alice" # 返回 2(从 0 开始)

# 增加分数
ZINCRBY leaderboard 50 "alice" # Alice 的分数变为 1050

优势

  • 实时更新(微秒级延迟)
  • 高效排名(插入/排名 O(log N))
  • 范围查询(前 N 名、用户排名)

4. 限流

目的:限制 API 请求频率(防止滥用)

# 递增计数器
INCR ratelimit:user:123:2024-02-14:10:00

# 首次请求时设置过期
EXPIRE ratelimit:user:123:2024-02-14:10:00 60

# 检查是否超限
GET ratelimit:user:123:2024-02-14:10:00
# 如果 > 100,返回 429 Too Many Requests

5. 发布/订阅

目的:实时消息传递(通知、聊天)

# 发布者
PUBLISH notifications:123 "New message from Alice"

# 订阅者
SUBSCRIBE notifications:123
# 收到:"New message from Alice"

快速参考

数据结构

类型描述使用场景
String二进制安全字符串缓存、计数器、会话
Hash字段-值对对象存储、用户资料
List链表(有序)队列、栈、时间线
Set无序唯一元素标签、关注者、唯一访客
ZSet带分数的有序集合排行榜、排名、优先队列

常用命令

# String
SET key value
GET key
INCR key # 原子递增
SETEX key seconds value # 带 TTL 的设置

# Hash
HSET key field value
HGET key field
HGETALL key

# List
LPUSH key value # 从左边推入(头部)
RPUSH key value # 从右边推入(尾部)
LPOP key # 从左边弹出
RPOP key # 从右边弹出
LRANGE key 0 -1 # 获取所有元素

# Set
SADD key member
SMEMBERS key
SISMEMBER key member

# Sorted Set
ZADD key score member
ZREVRANGE key start stop WITHSCORES
ZRANK key member

持久化

方法描述优点缺点
RDB定时快照紧凑、备份快上次快照后的数据丢失
AOF追加文件(记录每次写入)持久、最小数据丢失文件大、较慢

Redis vs MySQL

特性RedisMySQL
存储内存(RAM)磁盘
延迟微秒(μs)毫秒(ms)
数据结构丰富(String, Hash, List, Set, ZSet)表(行、列)
查询语言键值命令(无 SQL)SQL(复杂查询、JOIN)
事务有限(无回滚)完整 ACID
持久化可选(RDB、AOF)始终持久(InnoDB)
使用场景缓存、实时主数据存储

何时使用 Redis

  • 缓存(减少数据库负载)
  • 实时功能(排行榜、通知)
  • 会话存储(水平扩展)
  • 消息队列(发布/订阅、流)

何时使用 MySQL

  • 主数据存储(用户账户、订单)
  • 复杂查询(JOIN、聚合)
  • ACID 事务(金融数据)
  • 数据关系(外键)

架构

单实例

优点:简单、低延迟 缺点:单点故障、受单台服务器 RAM 限制

主从复制

优点:读扩展、高可用(故障转移) 缺点:写扩展受限于主节点、最终一致性

Redis Cluster

优点:水平扩展(分片)、高可用 缺点:配置复杂、不支持跨槽操作

性能技巧

1. 使用合适的数据结构

# ❌ 差:在 String 中存储 JSON
SET user:123 '{"name":"Alice","age":25}'
GET user:123 # 应用层需要解析 JSON

# ✅ 好:使用 Hash
HSET user:123 name "Alice" age 25
HGET user:123 name # 无需解析

2. 批量操作

# ❌ 差:每条命令一次往返
SET key1 value1
SET key2 value2
SET key3 value3

# ✅ 好:Pipeline(发送所有命令,接收所有响应)
# 或使用 MSET
MSET key1 value1 key2 value2 key3 value3

3. 使用过期时间(TTL)

# 防止内存泄漏:始终为缓存数据设置 TTL
SETEX session:abc123 3600 "user data" # 1 小时后过期
EXPIRE cache:user:123 300 # 5 分钟后过期

4. 监控内存使用

# 检查内存使用
INFO memory

# 设置最大内存(淘汰策略)
CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lru

文档结构

本 Redis 文档涵盖:

  1. 数据结构 - String、Hash、List、Set、ZSet 详细指南
  2. 持久化 - RDB vs AOF、持久性配置
  3. 集群 - Redis Cluster、Sentinel、高可用
  4. 缓存模式 - 缓存策略、失效、最佳实践

面试题清单

基础

  • Redis 是什么,何时使用?
  • Redis 有哪些数据结构?
  • Redis 与 MySQL 有什么区别?
  • RDB 和 AOF 持久化有什么区别?

数据结构

  • 如何在 Redis 中实现排行榜?
  • List 和 Set 有什么区别?
  • 如何在 Redis 中存储用户资料?
  • 如何实现限流?

架构

  • Redis 复制如何工作?
  • 什么是 Redis Cluster,它如何分片数据?
  • Redis Sentinel 如何提供高可用?
  • 为什么 Redis 是单线程的?

缓存

  • 常见的缓存策略有哪些?
  • 如何处理缓存失效?
  • 什么是缓存雪崩,如何防止?
  • 如何避免缓存穿透?

下一步

深入了解 Redis: