一、键值模型概述
键值存储(Key-Value Store)是最简单的NoSQL数据模型,以键值对作为基本数据单元。键值存储具有极高的读写性能,适合作为缓存层或存储简单的数据结构。Redis是最流行的键值存储系统之一。
二、键值模型与其他数据模型对比
| 数据模型 | 特点 | 代表产品 | 适用场景 |
|---|---|---|---|
| 键值存储 | 简单高效,键值对 | Redis、Memcached | 缓存、会话管理 |
| 文档存储 | 灵活schema,JSON文档 | MongoDB、CouchDB | 内容管理、日志 |
| 列族存储 | 列式存储,高压缩 | Cassandra、HBase | 大数据分析 |
| 图形存储 | 节点关系,图遍历 | Neo4j、ArangoDB | 社交网络、推荐 |
三、Redis核心数据结构
3.1 String(字符串)
最基本的数据结构,用于存储字符串、数字或二进制数据:
SET user:1:name "张三"
GET user:1:name
INCR page:views
3.2 Hash(哈希)
用于存储对象,每个哈希可以包含多个键值对:
HSET user:1 name "张三" age 25 email "zhangsan@example.com"
HGETALL user:1
HINCRBY user:1 age 1
3.3 List(列表)
双向链表,支持从两端添加和删除元素:
LPUSH news:feed "新闻1"
LPUSH news:feed "新闻2"
LRANGE news:feed 0 -1
3.4 Set(集合)
无序不重复集合,支持集合运算:
SADD user:1:tags "Java" "Spring"
SADD user:2:tags "Python" "Spring"
SINTER user:1:tags user:2:tags
3.5 Sorted Set(有序集合)
有序集合,每个元素有一个分数(score):
ZADD leaderboard 100 "张三"
ZADD leaderboard 95 "李四"
ZRANGE leaderboard 0 -1 WITHSCORES
3.6 Stream(流)
Redis 5.0+新增,用于消息队列和事件流:
XADD orders * user_id 1 total_amount 100
XREAD COUNT 10 STREAMS orders 0
graph TD
A[Redis数据结构] --> B[String]
A --> C[Hash]
A --> D[List]
A --> E[Set]
A --> F[Sorted Set]
A --> G[Stream]
B --> B1[适用: 简单值]
C --> C1[适用: 对象]
D --> D1[适用: 队列]
E --> E1[适用: 去重]
F --> F1[适用: 排序]
G --> G1[适用: 消息流]
四、Redis缓存策略
4.1 缓存穿透
缓存穿透是指查询一个不存在的数据,导致每次都查询数据库:
sequenceDiagram
participant Client as 客户端
participant Cache as Redis缓存
participant DB as 数据库
Client->>Cache: 查询key=123
Cache-->>Client: 缓存未命中
Client->>DB: 查询key=123
DB-->>Client: 数据不存在
Client->>Cache: 缓存空值(带过期时间)
4.2 缓存击穿
缓存击穿是指某个热点key过期,大量请求同时查询数据库:
sequenceDiagram
participant C1 as 客户端1
participant C2 as 客户端2
participant C3 as 客户端3
participant Cache as Redis缓存
participant Lock as 分布式锁
participant DB as 数据库
C1->>Cache: 查询热点key
Cache-->>C1: 缓存过期
C1->>Lock: 获取锁
Lock-->>C1: 获取成功
C1->>DB: 查询数据
DB-->>C1: 返回数据
C1->>Cache: 更新缓存
C1->>Lock: 释放锁
C2->>Cache: 查询热点key
Cache-->>C2: 返回缓存数据
C3->>Cache: 查询热点key
Cache-->>C3: 返回缓存数据
4.3 缓存雪崩
缓存雪崩是指大量缓存同时过期,导致数据库压力剧增:
解决方案:设置随机过期时间、使用多级缓存、预热热点数据。
五、Redis分布式锁
5.1 基本实现
SET lock:order:123 "uuid" NX EX 30
5.2 释放锁
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
5.3 Redlock算法
Redlock是Redis官方推荐的分布式锁算法,基于多个Redis实例:
graph TD
A[客户端] --> B[Redis1]
A --> C[Redis2]
A --> D[Redis3]
A --> E[Redis4]
A --> F[Redis5]
B --> G{获取锁成功?}
C --> G
D --> G
E --> G
F --> G
G -->|>=3个成功| H[锁获取成功]
G -->|<3个成功| I[释放所有锁]
G -->|<3个成功| J[重试或失败]
六、Redis会话管理
6.1 会话存储
使用Redis存储用户会话,支持分布式环境:
SET session:abc123 "{user_id:1, username:'张三'}" EX 1800
6.2 会话过期
设置会话过期时间,自动清理过期会话:
EXPIRE session:abc123 1800
七、Redis消息队列
7.1 基于List的消息队列
// 生产者
LPUSH queue:orders "{order_id:1}"
// 消费者
BRPOP queue:orders 0
7.2 基于Stream的消息队列
// 生产者
XADD orders * user_id 1 total 100
// 消费者组
XGROUP CREATE orders group1 0
XREADGROUP GROUP group1 consumer1 COUNT 10 STREAMS orders >
八、Redis数据持久化
8.1 RDB快照
RDB是Redis默认的持久化方式,定期生成数据快照:
save 60 1000
bgsave
8.2 AOF日志
AOF记录所有写操作,支持三种同步策略:
appendonly yes
appendfsync everysec
九、Redis集群部署
9.1 主从复制
实现读写分离,主节点负责写,从节点负责读:
graph TD
A[客户端] --> B[主节点Master]
A --> C[从节点Slave1]
A --> D[从节点Slave2]
B --> C[同步数据]
B --> D[同步数据]
9.2 哨兵模式
自动发现主节点故障并进行故障转移:
sentinel monitor mymaster 127.0.0.1 6379 2
9.3 Cluster集群
Redis Cluster支持自动分片和故障转移:
graph TD
A[客户端] --> B[Cluster节点1]
A --> C[Cluster节点2]
A --> D[Cluster节点3]
B --> E[槽0-5460]
C --> F[槽5461-10922]
D --> G[槽10923-16383]
E --> H[从节点]
F --> I[从节点]
G --> J[从节点]
十、Redis性能优化
10.1 内存优化
- 使用合适的数据结构:小对象使用压缩列表
- 设置过期时间:及时清理无用数据
- 使用内存淘汰策略:maxmemory-policy
10.2 网络优化
- 使用Pipeline:减少网络往返
- 使用Lua脚本:原子操作,减少网络开销
- 设置合理的TCP参数:tcp-keepalive等
十一、总结
Redis作为高性能的键值存储系统,在现代应用架构中扮演着重要角色。掌握Redis的核心数据结构和应用场景,能够构建高效、可靠的缓存层和数据处理系统。