第一章:Redis 基础入门
1.1 Redis 简介与特点
| 概念名称 | 说明 | 注意事项 |
|---|
| Redis 全称 | Remote Dictionary Server,是一个开源的基于内存的键值数据库 | 不是传统关系型数据库,不支持 SQL |
| 数据模型 | 支持字符串、列表、集合、有序集合、哈希、流等多种数据结构 | 所有数据默认存储在内存中,可配置持久化到磁盘 |
| 高性能 | 单线程事件驱动架构(6.0+ 支持多 I/O 线程),读写速度极快(10万+ QPS) | CPU 密集型操作(如大 key 排序)可能阻塞主线程 |
| 持久化能力 | 支持 RDB 快照和 AOF 日志两种持久化方式 | 默认开启 RDB,AOF 需手动配置;两者可同时启用 |
| 原子性 | 所有单个命令操作是原子的 | 多命令组合需使用事务或 Lua 脚本保证原子性 |
| 客户端-服务器架构 | 使用 TCP 协议通信,默认端口 6379 | 可通过 redis-cli、各种语言客户端连接 |
| 社区与生态 | 拥有丰富的客户端库(Python、Java、Node.js 等)和运维工具 | 官方推荐使用最新稳定版(如 7.x) |
1.2 安装与启动 Redis
| 步骤名称 | 操作细节 | 注意事项 |
|---|
| 在 Linux(Ubuntu/Debian)安装 | 执行:sudo apt update && sudo apt install redis-server | 安装后自动启动服务,配置文件位于 /etc/redis/redis.conf |
| 在 macOS 安装 | 使用 Homebrew:brew install redis | 安装后不会自动启动,需手动运行 redis-server |
| 从源码编译安装 | 下载源码(如 redis.io/download),解压后执行 make && make install | 需确保已安装 gcc、make 等编译工具 |
| 启动 Redis 服务 | 命令行执行:redis-server | 默认加载当前目录下的 redis.conf,若无则使用内置默认配置 |
| 启动时指定配置文件 | redis-server /path/to/redis.conf | 推荐生产环境使用自定义配置文件 |
| 检查 Redis 是否运行 | ps aux | grep redis 或 systemctl status redis | 若未启动,可手动运行 redis-server |
| 停止 Redis 服务 | redis-cli shutdown | 若启用了 AUTH,需先认证再执行 shutdown |
| 配置开机自启(Linux) | 使用 systemctl enable redis-server(Debian系) | 需确认系统使用 systemd |
1.3 Redis 命令行客户端基本使用
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| 启动客户端 | redis-cli | 连接本地默认 Redis 实例(127.0.0.1:6379) | redis-cli | 若 Redis 绑定其他 IP 或端口,需指定 -h 和 -p |
| 连接远程 Redis | redis-cli -h <host> -p <port> | 连接指定主机和端口的 Redis 服务 | redis-cli -h 192.168.1.10 -p 6380 | 需确保网络可达且防火墙开放端口 |
| 认证登录 | AUTH <password> | 对启用了 requirepass 的 Redis 进行身份验证 | AUTH mysecretpassword | 密码错误会返回 NOAUTH 错误 |
| 测试连通性 | PING | 检查 Redis 服务是否响应 | PING → 返回 “PONG” | 常用于健康检查脚本 |
| 退出客户端 | QUIT | 断开与 Redis 服务器的连接并退出 cli | QUIT | 也可直接按 Ctrl+D |
| 执行单条命令(非交互模式) | redis-cli <command> | 在 shell 中直接执行 Redis 命令 | redis-cli SET name Alice / redis-cli GET name | 适合写入脚本或自动化任务 |
| 批量执行命令 | redis-cli --pipe | 通过标准输入批量导入命令(需符合协议格式) | echo -e "SET a 1\nSET b 2" | redis-cli --pipe | 高性能批量导入方式,适用于数据迁移 |
| 查看帮助 | HELP <command> 或 redis-cli --help | 获取命令用法或客户端参数说明 | HELP SET / redis-cli --help | HELP 在交互模式下可用;--help 是命令行参数 |
第二章:Redis 核心数据类型与操作
2.1 字符串(String)类型
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| SET | SET key value [EX seconds|PX milliseconds] [NX|XX] | 设置字符串键值,可选过期时间和条件 | SET name Alice / SET token abc123 EX 3600 NX | NX 表示仅当 key 不存在时设置;XX 表示仅当存在时设置 |
| GET | GET key | 获取字符串值 | GET name → “Alice” | 若 key 不存在,返回 nil |
| GETSET | GETSET key value | 设置新值并返回旧值 | GETSET counter 10 → 返回旧值(如 “5”) | 原子操作,常用于计数器初始化 |
| MSET | MSET key1 value1 [key2 value2 ...] | 批量设置多个字符串键值 | MSET a 1 b 2 c 3 | 原子操作,全部成功或全部失败 |
| MGET | MGET key1 [key2 ...] | 批量获取多个字符串值 | MGET a b c → [“1”, “2”, “3”] | 不存在的 key 对应返回 nil |
| INCR | INCR key | 将 key 的值加 1(必须为整数) | INCR visits → 返回新值 | 若 key 不存在,视为 0 后加 1;非整数会报错 |
| INCRBY | INCRBY key increment | 将 key 的值增加指定整数 | INCRBY score 10 | 支持负数(相当于减) |
| DECR | DECR key | 将 key 的值减 1 | DECR stock | 同 INCR,要求值为整数 |
| DECRBY | DECRBY key decrement | 将 key 的值减少指定整数 | DECRBY balance 50 | 等价于 INCRBY key -50 |
| APPEND | APPEND key value | 在字符串末尾追加内容 | APPEND log "new entry" | 若 key 不存在,等同于 SET |
| STRLEN | STRLEN key | 获取字符串长度(字节) | STRLEN name → 5 | 中文字符按 UTF-8 字节计算 |
| SETEX | SETEX key seconds value | 设置带秒级过期时间的字符串 | SETEX session 60 user123 | 等价于 SET key value EX seconds |
| PSETEX | PSETEX key milliseconds value | 设置带毫秒级过期时间的字符串 | PSETEX temp 5000 data | 过期精度更高,但内存开销略大 |
2.2 列表(List)类型
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| LPUSH | LPUSH key value [value ...] | 从列表左侧(头)插入一个或多个元素 | LPUSH tasks "task1" "task2" | 返回列表长度;若 key 不存在则创建 |
| RPUSH | RPUSH key value [value ...] | 从列表右侧(尾)插入元素 | RPUSH logs "logA" "logB" | 同上,方向相反 |
| LPOP | LPOP key [count] | 弹出并返回左侧第一个(或前 count 个)元素 | LPOP tasks → “task2” / LPOP tasks 2 → [“task2”, “task1”] | Redis 6.2+ 支持 count 参数;若列表空,返回 nil |
| RPOP | RPOP key [count] | 弹出并返回右侧最后一个(或后 count 个)元素 | RPOP logs | 同 LPOP,方向相反 |
| LRANGE | LRANGE key start stop | 获取列表中指定范围的元素(含 stop) | LRANGE tasks 0 -1 → 全部元素 / LRANGE tasks 0 2 → 前3个 | 支持负数索引(-1 表示最后一个) |
| LINDEX | LINDEX key index | 获取指定索引处的元素 | LINDEX tasks 0 → 第一个元素 | 索引从 0 开始;越界返回 nil |
| LLEN | LLEN key | 获取列表长度 | LLEN tasks → 3 | key 不存在返回 0 |
| LREM | LREM key count value | 移除列表中等于 value 的元素 | LREM tasks 0 "task1" → 删除所有匹配项 / LREM tasks 1 "task1" → 从左删1个 | count > 0:从头删;< 0:从尾删;=0:全删 |
| LSET | LSET key index value | 设置指定索引位置的元素值 | LSET tasks 0 "new_task" | 索引必须存在,否则报错 |
| LTRIM | LTRIM key start stop | 保留列表中指定范围的元素,其余删除 | LTRIM logs 0 99 → 保留最近100条 | 常用于日志滚动 |
| BLPOP | BLPOP key [key ...] timeout | 阻塞式左弹出(等待直到有元素) | BLPOP tasks 10 → 最多阻塞10秒 | 可监听多个 key,返回第一个非空列表的元素 |
| BRPOP | BRPOP key [key ...] timeout | 阻塞式右弹出 | BRPOP queue 30 | 同 BLPOP,方向相反 |
2.3 集合(Set)类型
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| SADD | SADD key member [member ...] | 向集合添加一个或多个成员 | SADD tags "redis" "db" "cache" | 成员唯一,重复添加无效;返回实际新增数量 |
| SMEMBERS | SMEMBERS key | 获取集合所有成员 | SMEMBERS tags → [“redis”, “cache”, “db”] | 无序返回;大数据集慎用(O(N)) |
| SISMEMBER | SISMEMBER key member | 判断成员是否在集合中 | SISMEMBER tags "redis" → 1(是) | 时间复杂度 O(1) |
| SCARD | SCARD key | 获取集合成员数量 | SCARD tags → 3 | key 不存在返回 0 |
| SREM | SREM key member [member ...] | 移除集合中的一个或多个成员 | SREM tags "cache" | 返回成功移除的数量 |
| SPOP | SPOP key [count] | 随机弹出一个(或 count 个)成员 | SPOP users → 随机用户 / SPOP users 2 → 随机2个 | 弹出后成员被删除;count 为 Redis 3.2+ 支持 |
| SRANDMEMBER | SRANDMEMBER key [count] | 随机返回一个(或 count 个)成员(不删除) | SRANDMEMBER tags 2 | count 为正:不重复;为负:可重复 |
| SMOVE | SMOVE source destination member | 将成员从一个集合移到另一个 | SMOVE pending approved "user123" | 若 member 不在 source,返回 0 |
| SDIFF | SDIFF key1 [key2 ...] | 返回第一个集合与其他集合的差集 | SDIFF set1 set2 | 不修改原集合 |
| SINTER | SINTER key1 [key2 ...] | 返回多个集合的交集 | SINTER set1 set2 | 常用于共同标签、好友交集 |
| SUNION | SUNION key1 [key2 ...] | 返回多个集合的并集 | SUNION set1 set2 | 合并所有成员去重 |
2.4 有序集合(Sorted Set / ZSet)类型
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| ZADD | ZADD key [NX|XX] [CH] [INCR] score member [score member ...] | 向有序集合添加成员及分数 | ZADD leaderboard 100 "Alice" 95 "Bob" | 分数可为浮点数;成员唯一,分数可更新 |
| ZRANGE | ZRANGE key start stop [WITHSCORES] | 按分数升序返回指定排名范围成员 | ZRANGE leaderboard 0 -1 WITHSCORES | 支持负索引;WITHSCORES 返回分数 |
| ZREVRANGE | ZREVRANGE key start stop [WITHSCORES] | 按分数降序返回成员 | ZREVRANGE leaderboard 0 2 | 常用于 Top N 排行榜 |
| ZSCORE | ZSCORE key member | 获取成员的分数 | ZSCORE leaderboard "Alice" → “100” | 成员不存在返回 nil |
| ZCARD | ZCARD key | 获取有序集合成员数量 | ZCARD leaderboard → 2 | key 不存在返回 0 |
| ZREM | ZREM key member [member ...] | 移除一个或多个成员 | ZREM leaderboard "Bob" | 返回成功移除数量 |
| ZINCRBY | ZINCRBY key increment member | 为成员分数增加增量 | ZINCRBY scores 10 "Alice" | 若成员不存在,先设为 0 再加 |
| ZRANK | ZRANK key member | 获取成员的升序排名(从0开始) | ZRANK leaderboard "Alice" → 0 | 成员不存在返回 nil |
| ZREVRANK | ZREVRANK key member | 获取成员的降序排名 | ZREVRANK leaderboard "Alice" → 1 | 最高分排名为 0 |
| ZRANGEBYSCORE | ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] | 按分数范围返回成员 | ZRANGEBYSCORE scores 90 100 | min/max 可用 -inf +inf;支持 LIMIT 分页 |
| ZREMRANGEBYRANK | ZREMRANGEBYRANK key start stop | 移除指定排名范围内的成员 | ZREMRANGEBYRANK leaderboard 0 0 → 删除第一名 | 包含 stop |
| ZREMRANGEBYSCORE | ZREMRANGEBYSCORE key min max | 移除指定分数范围内的成员 | ZREMRANGEBYSCORE scores 0 50 | 清理低分数据常用 |
2.5 哈希(Hash)类型
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| HSET | HSET key field value [field value ...] | 设置哈希字段的值(Redis 4.0+ 支持多字段) | HSET user:1001 name Alice age 30 | 返回新增字段数(已存在则覆盖,不计入) |
| HGET | HGET key field | 获取哈希字段的值 | HGET user:1001 name → “Alice” | 字段不存在返回 nil |
| HMSET | HMSET key field value [field value ...] | 批量设置哈希字段(已废弃,建议用 HSET) | HMSET user:1002 city Beijing job Engineer | Redis 4.0+ 中 HSET 已支持多字段,HMSET 保留兼容 |
| HMGET | HMGET key field [field ...] | 批量获取多个字段值 | HMGET user:1001 name age → [“Alice”, “30”] | 不存在字段对应返回 nil |
| HGETALL | HGETALL key | 获取哈希所有字段和值 | HGETALL user:1001 → [“name”, “Alice”, “age”, “30”] | 大对象慎用(O(N)) |
| HDEL | HDEL key field [field ...] | 删除一个或多个字段 | HDEL user:1001 age | 返回成功删除字段数 |
| HEXISTS | HEXISTS key field | 判断字段是否存在 | HEXISTS user:1001 name → 1 | 存在返回 1,否则 0 |
| HLEN | HLEN key | 获取哈希字段数量 | HLEN user:1001 → 2 | key 不存在返回 0 |
| HKEYS | HKEYS key | 获取所有字段名 | HKEYS user:1001 → [“name”, “age”] | 无序;大数据集慎用 |
| HVALS | HVALS key | 获取所有字段值 | HVALS user:1001 → [“Alice”, “30”] | 与 HKEYS 顺序一致 |
| HINCRBY | HINCRBY key field increment | 对字段值增加整数 | HINCRBY user:1001 login_count 1 | 字段不存在则视为 0 |
| HINCRBYFLOAT | HINCRBYFLOAT key field increment | 对字段值增加浮点数 | HINCRBYFLOAT product:1 price 0.99 | 返回新值(字符串形式) |
第三章:Redis 键管理与通用命令
3.1 键的命名与生命周期管理
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| 键命名规范 | 推荐使用”业务:实体:id”格式(如 user:profile:1001) | 避免使用空格、特殊符号;建议统一前缀便于管理 |
| 键最大长度 | Redis 支持最大 512MB 的键名 | 实际应用中应保持简短(通常 < 1KB),过长影响性能 |
| 生命周期控制方式 | 通过 EXPIRE、PEXPIRE、EXPIREAT 等命令设置过期时间 | 过期后键自动删除,内存释放 |
| 持久化对过期的影响 | RDB 快照会保存过期时间;AOF 在重写时剔除已过期键 | 主从复制中,从节点不主动删除过期键,依赖主节点同步 DEL |
| 惰性删除 + 定期删除 | Redis 采用惰性删除(访问时检查)+ 后台定期随机抽样删除 | 无法保证过期键立即释放内存 |
| 避免大 Key | 单个键对应值过大(如百万元素 List)会导致阻塞 | 建议拆分为多个小 Key 或使用 Hash 分片 |
| 命名空间隔离 | 不同业务使用不同前缀(如 order:、session:) | 便于使用 KEYS 或 SCAN 按前缀批量操作 |
3.2 通用命令(如 EXISTS、DEL、TYPE、EXPIRE 等)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| EXISTS | EXISTS key [key ...] | 检查一个或多个键是否存在 | EXISTS name → 1 / EXISTS a b c → 返回存在的数量 | Redis 3.2+ 支持多 key;返回整数(存在数量) |
| DEL | DEL key [key ...] | 删除一个或多个键 | DEL temp_key session:123 | 返回成功删除的键数量;O(1) 到 O(N) 取决于值大小 |
| TYPE | TYPE key | 获取键的数据类型 | TYPE user:1001 → “hash” | 返回 string、list、set、zset、hash、stream 等 |
| EXPIRE | EXPIRE key seconds | 为键设置秒级过期时间 | EXPIRE token 3600 | 若 key 不存在,返回 0;已存在则更新过期时间 |
| PEXPIRE | PEXPIRE key milliseconds | 为键设置毫秒级过期时间 | PEXPIRE temp 5000 | 精度更高,适用于短时效场景 |
| EXPIREAT | EXPIREAT key timestamp | 为键设置在指定 Unix 时间戳(秒)过期 | EXPIREAT cache 1700000000 | timestamp 为绝对时间 |
| PEXPIREAT | PEXPIREAT key milliseconds-timestamp | 设置毫秒级绝对过期时间 | PEXPIREAT event 1700000000123 | 少用,多数场景用 EXPIRE 即可 |
| TTL | TTL key | 获取键剩余生存时间(秒) | TTL session → 1800 | 返回 -1 表示无过期;-2 表示 key 不存在 |
| PTTL | PTTL key | 获取键剩余生存时间(毫秒) | PTTL lock → 4999 | 精度更高;同样返回 -1(永不过期)或 -2(不存在) |
| PERSIST | PERSIST key | 移除键的过期时间,使其持久存在 | PERSIST config | 若 key 无过期时间,返回 0 |
| RENAME | RENAME key newkey | 重命名键(若 newkey 存在则覆盖) | RENAME old_name new_name | 若 key 不存在,报错;newkey 原有值被删除 |
| RENAMENX | RENAMENX key newkey | 仅当 newkey 不存在时重命名 | RENAMENX temp backup | 成功返回 1,否则 0;避免覆盖 |
| KEYS | KEYS pattern | 查找所有匹配模式的键 | KEYS user:* / KEYS *.log | 生产环境禁用!会阻塞主线程(O(N)) |
| SCAN | SCAN cursor [MATCH pattern] [COUNT count] | 增量迭代键空间(非阻塞) | SCAN 0 MATCH user:* COUNT 10 | 返回新 cursor 和一批 key;cursor=0 表示结束 |
| RANDOMKEY | RANDOMKEY | 随机返回一个键 | RANDOMKEY → “session:abc” | key 不存在时返回 nil |
| MOVE | MOVE key db | 将键移动到另一个数据库(0-15) | MOVE config 1 | 目标 db 中若已存在 key,则失败;不推荐跨 db 使用 |
| DBSIZE | DBSIZE | 返回当前数据库键总数 | DBSIZE → 1024 | 快速 O(1) 操作 |
| FLUSHDB | FLUSHDB | 清空当前数据库所有键 | FLUSHDB | 危险操作!生产慎用 |
| FLUSHALL | FLUSHALL | 清空所有数据库(0-15)的所有键 | FLUSHALL | 极度危险!通常需配置 rename-command 禁用 |
第四章:Redis 高级功能
4.1 发布/订阅(Pub/Sub)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| PUBLISH | PUBLISH channel message | 向指定频道发送消息 | PUBLISH news "Breaking: Redis 7 released!" | 返回接收消息的客户端数量;消息不持久化 |
| SUBSCRIBE | SUBSCRIBE channel [channel ...] | 订阅一个或多个频道 | SUBSCRIBE news sports | 进入阻塞监听模式,无法执行其他命令 |
| UNSUBSCRIBE | UNSUBSCRIBE [channel [channel ...]] | 取消订阅指定频道(或全部) | UNSUBSCRIBE news / UNSUBSCRIBE | 在 SUBSCRIBE 模式下使用;无参则退订所有 |
| PSUBSCRIBE | PSUBSCRIBE pattern [pattern ...] | 按模式订阅频道(支持通配符) | PSUBSCRIBE news.* / PSUBSCRIBE *.alert | 支持 *、?、[ ] 等 glob 模式 |
| PUNSUBSCRIBE | PUNSUBSCRIBE [pattern [pattern ...]] | 取消按模式订阅 | PUNSUBSCRIBE news.* | 仅影响 PSUBSCRIBE 订阅的模式 |
| PUBSUB CHANNELS | PUBSUB CHANNELS [pattern] | 列出至少有一个订阅者的频道 | PUBSUB CHANNELS / PUBSUB CHANNELS news.* | 用于监控活跃频道 |
| PUBSUB NUMSUB | PUBSUB NUMSUB channel [channel ...] | 获取各频道的订阅者数量 | PUBSUB NUMSUB news sports | 返回频道与订阅数交替列表 |
| PUBSUB NUMPAT | PUBSUB NUMPAT | 获取模式订阅(PSUBSCRIBE)总数 | PUBSUB NUMPAT → 2 | 返回整数 |
注意: Pub/Sub 消息是即时的,不存储历史;客户端断开即丢失未消费消息。如需持久化消息队列,应使用 Stream。
4.2 事务(Transaction)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| MULTI | MULTI | 开启事务,后续命令进入队列 | MULTI | 返回 OK;之后命令返回 QUEUED |
| EXEC | EXEC | 执行事务中所有排队命令 | EXEC → 返回各命令结果列表 | 若 EXEC 前客户端断开,事务自动丢弃 |
| DISCARD | DISCARD | 清空事务队列并退出事务 | DISCARD | 返回 OK;回到正常模式 |
| WATCH | WATCH key [key ...] | 监视一个或多个键,实现乐观锁 | WATCH balance → MULTI → ... → EXEC | 若被监视键在 EXEC 前被修改,EXEC 返回 nil(事务失败) |
| UNWATCH | UNWATCH | 取消所有键的监视 | UNWATCH | 通常在 DISCARD 后自动触发 |
重要说明:
- Redis 事务不支持回滚(Rollback),但保证原子性(要么全执行,要么全不执行)。
- 事务中语法错误会导致 EXEC 失败;运行时错误(如对 string 执行 LPUSH)不会中断后续命令。
4.3 Lua 脚本执行
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| EVAL | EVAL script numkeys key [key ...] arg [arg ...] | 执行 Lua 脚本 | EVAL "return redis.call('GET', KEYS[1])" 1 mykey / EVAL "return ARGV[1]" 0 hello | KEYS 数组传键,ARGV 传参数;numkeys 指定 KEYS 个数 |
| EVALSHA | EVALSHA sha1 numkeys key [key ...] arg [arg ...] | 通过脚本 SHA1 值执行(避免重复传输) | EVALSHA a8f... 1 counter | 需先用 SCRIPT LOAD 加载脚本 |
| SCRIPT LOAD | SCRIPT LOAD script | 将脚本加载到服务器缓存,返回 SHA1 | SCRIPT LOAD "return 'ok'" → “a8f…” | 脚本永久缓存(直到重启或 SCRIPT FLUSH) |
| SCRIPT EXISTS | SCRIPT EXISTS sha1 [sha1 ...] | 检查脚本是否已缓存 | SCRIPT EXISTS a8f... b2c... → [1, 0] | 返回 1 表示存在,0 表示不存在 |
| SCRIPT FLUSH | SCRIPT FLUSH | 清空所有缓存的 Lua 脚本 | SCRIPT FLUSH | 通常用于开发或脚本更新 |
| SCRIPT KILL | SCRIPT KILL | 终止正在执行的只读脚本 | SCRIPT KILL | 若脚本已写数据,则无法终止(需 SHUTDOWN NOSAVE) |
Lua 脚本规则:
- 脚本内使用
redis.call() 或 redis.pcall() 调用 Redis 命令。
- 脚本执行是原子的,期间其他命令不会插入。
- 禁止在脚本中使用随机数、时间等非确定性函数(除非用
math.randomseed 固定种子)。
4.4 流(Stream)类型(Redis 5.0+)
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| XADD | XADD key [NOMKSTREAM] [*|id] field value [field value ...] | 向流中添加新条目 | XADD logs * level ERROR msg "disk full" | * 表示自动生成 ID(毫秒-序号);默认创建流(NOMKSTREAM 可禁用) |
| XRANGE | XRANGE key start end [COUNT count] | 按 ID 范围获取条目(升序) | XRANGE logs - + COUNT 10 / XRANGE logs 1600000000000 1600000001000 | - 表示最小 ID,+ 表示最大 ID |
| XREVRANGE | XREVRANGE key end start [COUNT count] | 按 ID 范围获取条目(降序) | XREVRANGE logs + - COUNT 5 | 常用于获取最新 N 条日志 |
| XREAD | XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] id [id ...] | 从一个或多个流读取新条目 | XREAD BLOCK 5000 STREAMS logs $ / XREAD COUNT 2 STREAMS orders 0 | $ 表示最新 ID;BLOCK 实现阻塞等待;0 表示从头开始 |
| XLEN | XLEN key | 获取流中条目数量 | XLEN events → 1024 | O(1) 操作 |
| XDEL | XDEL key id [id ...] | 删除指定 ID 的条目 | XDEL logs 1600000000000-0 | 条目标记为删除,内存可能不会立即释放 |
| XTRIM | XTRIM key MAXLEN [~] count | 修剪流至最多 count 条目 | XTRIM logs MAXLEN 1000 / XTRIM logs MAXLEN ~ 1000 | ~ 表示近似修剪(性能更好) |
| XGROUP CREATE | XGROUP CREATE key groupname id [MKSTREAM] | 为流创建消费者组 | XGROUP CREATE logs workers $ MKSTREAM | $ 表示从最新开始消费;MKSTREAM 允许 key 不存在时创建 |
| XREADGROUP | XREADGROUP GROUP group consumer [COUNT count] [BLOCK ms] [NOACK] STREAMS key [key ...] id [id ...] | 通过消费者组读取 | XREADGROUP GROUP workers c1 STREAMS logs > | > 表示读取新消息;支持多消费者负载均衡 |
| XACK | XACK key group id [id ...] | 确认已处理消息(移出 Pending Entries List) | XACK logs workers 1600000000000-0 | 必须在 XREADGROUP 后调用,否则消息会重发 |
| XPENDING | XPENDING key group [start end count] [consumer] | 查看待处理消息 | XPENDING logs workers / XPENDING logs workers - + 10 worker1 | 用于监控积压和故障恢复 |
Stream 优势:
- 消息持久化(即使消费者离线也不会丢失)
- 支持多消费者组、消息确认、重试机制
- 替代传统 Pub/Sub 和 List 实现可靠消息队列
第五章:Redis 持久化与配置
5.1 RDB 快照持久化
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| RDB 原理 | 在指定时间点将内存数据快照写入磁盘(二进制 dump.rdb 文件) | 适合备份、灾难恢复;恢复速度快 |
| 触发方式 | 自动(按配置规则)或手动(SAVE / BGSAVE) | SAVE 阻塞主线程;BGSAVE 后台 fork 子进程执行 |
| 配置规则(save) | 格式:save <seconds> <changes>,满足任一即触发 | 示例:save 900 1 → 15分钟至少1次修改 / save 300 10 → 5分钟至少10次修改 / save 60 10000 → 1分钟至少1万次修改 |
| 手动触发命令 | BGSAVE | 返回 “Background saving started”;可通过 INFO PERSISTENCE 查看状态 |
| 文件名 | 默认为 dump.rdb,可由 dbfilename 配置 | 存放路径由 dir 指定(如 /var/lib/redis/) |
| 数据一致性 | 快照是某一时刻的完整副本,但可能丢失最后一次快照后的数据 | 不适用于要求强持久化的场景(如金融交易) |
| 性能影响 | fork 子进程时若内存大,可能导致延迟(Copy-On-Write) | 建议在低峰期或配合 AOF 使用 |
5.2 AOF 日志持久化
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| AOF 原理 | 记录每个写命令到 appendonly.aof 文件,重启时重放命令恢复数据 | 数据更安全,最多丢失 1 秒数据(取决于 fsync 策略) |
| 开启方式 | 配置 appendonly yes | 默认关闭;开启后优先于 RDB 恢复(若两者都启用) |
| 同步策略(appendfsync) | always:每次写都 fsync(最安全,性能差)/ everysec:每秒 fsync(默认,平衡)/ no:由 OS 决定(最快,可能丢数据) | everysec 是推荐值;always 仅用于极端安全场景 |
| AOF 重写(rewrite) | 生成精简版 AOF(去除冗余命令),减小文件体积 | 通过 BGREWRITEAOF 手动触发,或 auto-aof-rewrite-percentage 自动触发 |
| 重写原理 | fork 子进程遍历内存,生成新 AOF,期间主进程继续写旧 AOF + 缓冲区 | 重写期间内存占用可能翻倍 |
| 文件名 | 默认 appendonly.aof,可由 appendfilename 配置 | 路径同样由 dir 控制 |
| 恢复行为 | 启动时自动加载 AOF 文件;若文件损坏,可用 redis-check-aof --fix 修复 | 修复可能丢失部分尾部命令 |
5.3 混合持久化(Redis 4.0+)
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| 混合模式原理 | AOF 重写时,前半部分用 RDB 格式(快照),后半部分用 AOF 格式(增量命令) | 结合 RDB 恢复速度 + AOF 数据完整性 |
| 开启方式 | 配置 aof-use-rdb-preamble yes | Redis 4.0+ 默认开启(部分发行版可能默认关闭) |
| 文件结构 | AOF 文件开头是 RDB magic header(REDIS…),之后是 AOF 命令 | 兼容旧版 Redis?否!旧版无法识别混合 AOF |
| 恢复流程 | 先加载 RDB 部分快速重建状态,再重放 AOF 增量命令 | 启动速度显著快于纯 AOF |
| 适用场景 | 对启动速度和数据安全均有要求的生产环境 | 推荐作为默认持久化方案 |
5.4 redis.conf 配置文件详解
| 配置项 | 说明 | 默认值 | 注意事项 |
|---|
| bind | 绑定 IP 地址(限制访问来源) | 127.0.0.1 | 生产若需远程访问,应绑定内网 IP 并配合防火墙;避免 0.0.0.0 |
| port | 监听端口 | 6379 | 可修改以避免扫描攻击 |
| protected-mode | 保护模式(无密码且 bind 未设时拒绝外网连接) | yes | 开发可关,生产建议保持开启 |
| requirepass | 设置客户端连接密码 | 无(空) | 启用后客户端需 AUTH;密码明文存储,建议配合 ACL(Redis 6+) |
| daemonize | 是否后台运行 | no | Linux 服务通常设为 yes |
| pidfile | PID 文件路径 | /var/run/redis.pid | 用于 systemctl 管理 |
| logfile | 日志文件路径 | ""(标准输出) | 后台运行时建议指定日志文件 |
| databases | 数据库数量(0-15) | 16 | 实际应用中建议只用 DB 0,避免混淆 |
| save | RDB 快照触发条件 | 多行规则(见 5.1) | 设为空(save "")可禁用 RDB |
| stop-writes-on-bgsave-error | RDB 失败时是否禁止写入 | yes | 避免在磁盘满时继续写导致数据不一致 |
| rdbcompression | RDB 文件是否压缩 | yes | 压缩节省空间,略微增加 CPU |
| dbfilename | RDB 文件名 | dump.rdb | — |
| dir | 工作目录(RDB/AOF 存放路径) | ./ | 必须有写权限;建议设为绝对路径如 /var/lib/redis |
| appendonly | 是否开启 AOF | no | — |
| appendfilename | AOF 文件名 | appendonly.aof | — |
| appendfsync | AOF 同步策略 | everysec | — |
| auto-aof-rewrite-percentage | AOF 重写触发增长率 | 100 | 当前 AOF 大小 > 上次重写后大小 * (1 + %) 时触发 |
| auto-aof-rewrite-min-size | AOF 重写最小文件大小 | 64mb | 小于此值不触发重写 |
| aof-use-rdb-preamble | 是否启用混合持久化 | yes(4.0+) | — |
| maxmemory | 最大内存限制 | 0(无限制) | 生产必设!避免 OOM |
| maxmemory-policy | 内存淘汰策略 | noeviction | 常用:allkeys-lru(LRU 淘汰任意 key)、volatile-lru(仅带过期的 key) |
| tcp-keepalive | TCP 保活检测间隔(秒) | 300 | 有助于清理死连接 |
| timeout | 客户端空闲超时(秒) | 0(永不关闭) | 可设为 300 防止连接泄漏 |
| rename-command | 重命名危险命令 | 无 | 如 rename-command FLUSHALL "" 可禁用该命令 |
配置生效方式:
- 修改 redis.conf 后需重启 Redis(部分参数支持 CONFIG SET 动态修改,如 maxmemory)
- 使用 CONFIG GET/SET 可查看或临时修改运行时配置(重启失效)
第六章:Redis 性能与运维
6.1 内存管理与优化
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| 内存使用构成 | 包括键值对象、内部数据结构(如 dict、sds)、客户端缓冲区、复制积压缓冲区等 | 使用 INFO memory 查看详细分布 |
| maxmemory 限制 | 通过配置 maxmemory 设置 Redis 最大可用内存 | 生产环境必须设置,防止 OOM 导致系统崩溃 |
| 内存淘汰策略(maxmemory-policy) | noeviction:不淘汰,写满后报错 / allkeys-lru:LRU 淘汰任意 key / volatile-lru:仅淘汰带过期时间的 key(LRU) / allkeys-random / volatile-random:随机淘汰 / volatile-ttl:优先淘汰 TTL 短的 key / volatile-lfu / allkeys-lfu(4.0+):LFU 淘汰 | 推荐:allkeys-lru(通用缓存)或 volatile-lru(带 TTL 的会话存储) |
| 内存碎片率(mem_fragmentation_ratio) | used_memory_rss / used_memory,理想值 1.0~1.5 | >1.5 表示碎片高,可重启或启用 activedefrag(5.0+) |
| 对象共享与编码优化 | Redis 对小整数(0~9999)、短字符串等使用共享对象;List/Hash/Set/ZSet 在元素少时使用紧凑编码(ziplist、intset) | 避免大 Key(如百万级 List),会退化为标准结构,占用更多内存 |
| 客户端输出缓冲区限制 | 配置 client-output-buffer-limit 防止慢客户端耗尽内存 | 示例:normal 0 0 0 / slave 256mb 64mb 60 / pubsub 32mb 8mb 60 |
| 内存分析工具 | MEMORY USAGE key:查看单个 key 内存占用 / MEMORY STATS:全局内存统计 / redis-cli --bigkeys:扫描大 Key | --bigkeys 会遍历全库,建议在低峰期运行 |
6.2 慢查询日志分析
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| slowlog-log-slower-than | 配置项(单位:微秒) | 设置记录慢查询的阈值 | 默认 10000(10ms) | 设为负数可禁用;设为 0 记录所有命令 |
| slowlog-max-len | 配置项 | 慢查询日志最大条目数(FIFO) | 默认 128 | 可通过 CONFIG SET 动态调整 |
| SLOWLOG GET | SLOWLOG GET [count] | 获取最近慢查询日志 | SLOWLOG GET 5 | 返回:ID、时间戳、耗时(μs)、命令 |
| SLOWLOG LEN | SLOWLOG LEN | 获取当前慢查询日志数量 | SLOWLOG LEN → 10 | — |
| SLOWLOG RESET | SLOWLOG RESET | 清空慢查询日志 | SLOWLOG RESET | — |
| 常见慢命令 | KEYS *、FLUSHALL、大 Key 的 DEL/HGETALL/SMEMBERS、复杂 Lua 脚本 | — | 避免在生产使用 KEYS;大 Key 操作应拆分或使用 SCAN | |
分析建议:
- 定期检查 SLOWLOG GET,定位性能瓶颈
- 结合应用日志,确认是否因网络、序列化等非 Redis 原因导致延迟
6.3 监控与 INFO 命令
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| INFO | INFO [section] | 获取服务器各类运行信息 | INFO / INFO memory / INFO clients / INFO replication | 不带参数返回全部;常用 section:server, clients, memory, persistence, stats, replication, cpu, commandstats |
| INFO server | — | Redis 版本、运行模式、端口等 | — | 查看版本兼容性 |
| INFO clients | — | 当前连接客户端数量、阻塞客户端等 | connected_clients: 10 / blocked_clients: 0 | blocked_clients > 0 可能存在 BLPOP/BZPOPMAX 等阻塞调用 |
| INFO memory | — | 内存使用详情(含碎片率) | used_memory: 1048576 / mem_fragmentation_ratio: 1.2 | 关注 used_memory 和碎片率 |
| INFO stats | — | 命令统计、命中率、拒绝连接数等 | total_commands_processed: 10000 / keyspace_hits: 8000 / keyspace_misses: 2000 | 命中率 = hits / (hits + misses) |
| INFO commandstats | — | 各命令调用次数、耗时统计 | cmdstat_get:calls=5000,usec=10000,usec_per_call=2.00 | 识别高频/高耗时命令 |
| INFO replication | — | 主从复制状态 | role:master / connected_slaves:2 | 从节点显示 master_host、offset 等 |
| MONITOR | MONITOR | 实时打印所有接收到的命令(调试用) | MONITOR | 极度影响性能!禁止在生产使用 |
| CLIENT LIST | CLIENT LIST | 列出所有客户端连接信息 | CLIENT LIST | 显示 addr、fd、age、idle、flags、omem(输出缓冲)等 |
6.4 安全配置(AUTH、绑定 IP 等)
| 配置项/命令 | 说明 | 默认值 | 注意事项 |
|---|
| bind | 限制 Redis 监听的网络接口 | 127.0.0.1 | 生产若需内网访问,设为内网 IP(如 10.0.0.5);禁止 bind 0.0.0.0 且无密码 |
| protected-mode | 保护模式:当无密码且未 bind 特定 IP 时,拒绝外网连接 | yes | 开发可关,生产建议保持开启 |
| requirepass | 设置客户端连接密码 | 无 | 启用后所有客户端需执行 AUTH password;密码明文存储于 redis.conf |
| AUTH | AUTH password | 客户端认证命令 | AUTH mysecretpassword |
| rename-command | 重命名或禁用危险命令 | 无 | 示例:rename-command FLUSHDB "" → 禁用 / rename-command CONFIG "myconfig" → 改名 |
| firewall | 系统防火墙限制 | — | 使用 iptables/uFW 仅允许可信 IP 访问 6379 端口 |
| TLS/SSL(6.0+) | 启用加密通信 | 无 | 需配置 tls-port、tls-cert-file 等;适用于公网或合规场景 |
| ACL(6.0+) | 细粒度权限控制(用户、命令、Key 权限) | 默认用户 default,权限 allkeys allcommands | 示例:ACL SETUSER alice on >mypass ~cache:* +get +set |
安全最佳实践:
- 永远不要将 Redis 暴露在公网上
- 必须设置 requirepass 或使用 ACL
- 禁用或重命名 FLUSHALL、CONFIG、DEBUG 等高危命令
- 定期审计配置和连接来源
第七章:Redis 高可用与集群
7.1 主从复制(Replication)
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| 复制原理 | 从节点(slave/replica)连接主节点(master),同步全量 RDB 快照 + 增量命令流 | Redis 5.0 起术语由 slave 改为 replica,但命令仍兼容 SLAVEOF |
| 异步复制 | 主节点不等待从节点确认,写入即返回 → 可能存在数据延迟 | 不保证强一致性;主宕机可能丢失未同步数据 |
| 一主多从 | 一个主节点可被多个从节点复制,用于读写分离、灾备 | 从节点默认只读(replica-read-only yes) |
| 配置方式(动态) | 在从节点执行:REPLICAOF <masterip> <masterport> | Redis 5.0+ 使用 REPLICAOF;旧版用 SLAVEOF |
| 配置方式(静态) | 在从节点 redis.conf 中设置:replicaof 192.168.1.10 6379 | 重启后自动连接主节点 |
| 主从断线重连 | 从节点会尝试自动重连;若偏移量(offset)在 backlog 范围内,进行部分同步(PSYNC) | 否则触发全量同步(BGSAVE + 传输 RDB) |
| 复制积压缓冲区(repl-backlog-size) | 主节点维护的环形命令缓冲区,用于 PSYNC | 默认 1MB;写密集场景应增大(如 128MB) |
| 无盘复制(diskless replication) | 主节点直接通过 socket 发送 RDB 流,不落盘 | 配置 repl-diskless-sync yes;适用于磁盘慢、网络快的环境 |
| 从节点只读 | 默认 replica-read-only yes,防止误写 | 可设为 no,但不推荐(数据不会同步回主) |
7.2 哨兵模式(Sentinel)
| 方法/配置项 | 语法/说明 | 用途 | 代码示例 / 配置 | 注意事项 |
|---|
| Sentinel 作用 | 监控主从状态、自动故障转移、通知、配置提供者 | 实现高可用(HA) | — | 至少部署 3 个 Sentinel 节点(避免脑裂) |
| 启动 Sentinel | redis-sentinel /path/to/sentinel.conf 或 redis-server /path/to/sentinel.conf --sentinel | Sentinel 是特殊模式的 Redis 进程 | — | — |
| 核心配置项 | sentinel monitor <master-name> <ip> <port> <quorum> | 监控指定主节点 | sentinel monitor mymaster 192.168.1.10 6379 2 | quorum 表示判定主观下线所需 Sentinel 数;客观下线需多数同意 |
| 故障转移超时 | sentinel failover-timeout <master-name> <ms> | 控制故障转移各阶段超时 | sentinel failover-timeout mymaster 180000 | 单位毫秒;影响切换速度 |
| 并行同步数 | sentinel parallel-syncs <master-name> <num> | 故障转移后,最多同时同步新主的从节点数 | sentinel parallel-syncs mymaster 1 | 设为 1 可减少主节点压力 |
| 自动发现 | Sentinel 通过主节点自动发现从节点和其他 Sentinel | 无需手动配置从节点 | — | 确保 Sentinel 能访问主节点的 INFO replication 输出 |
| 客户端获取地址 | 应用通过 Sentinel 查询当前主节点地址 | SENTINEL get-master-addr-by-name mymaster | 返回 IP 和端口 | 客户端库(如 Jedis、Lettuce)内置 Sentinel 支持 |
| 主观下线(SDOWN) | 单个 Sentinel 认为主不可达 | — | — | 由 down-after-milliseconds 控制(默认 30s) |
| 客观下线(ODOWN) | 多数 Sentinel 同意主不可达,触发故障转移 | — | — | 需 ≥ quorum 个 Sentinel 报告 SDOWN |
| 配置持久化 | Sentinel 会自动更新 sentinel.conf 文件 | 记录主从拓扑变化 | — | 配置文件需有写权限 |
部署建议:
- Sentinel 与 Redis 实例不要部署在同一台机器(避免单点故障)
- 使用奇数个 Sentinel(3、5)以保证多数投票
7.3 Redis Cluster 集群模式
| 概念/操作名称 | 说明 | 注意事项 |
|---|
| 分片机制 | 数据按 16384 个哈希槽(slot)分布,每个 key 通过 CRC16(key) % 16384 定位槽 | 客户端可计算槽位置,直连目标节点 |
| 节点角色 | 主节点(master)负责槽和写;从节点(replica)复制主节点,用于故障转移 | 最小集群:3 主 + 3 从(共 6 节点) |
| 高可用 | 每个主节点至少一个从节点;主宕机时,从节点自动提升为主 | 需启用 cluster-require-full-coverage no 避免部分槽不可用导致整个集群拒绝服务 |
| 启动集群模式 | 配置项:cluster-enabled yes / cluster-config-file nodes.conf / cluster-node-timeout 15000 | 每个节点必须有独立的 cluster-config-file |
| 创建集群 | 使用 redis-cli --cluster create | 示例:redis-cli --cluster create 192.168.1.1:7000 192.168.1.1:7001 ... --cluster-replicas 1 |
| 槽分配 | 初始由 --cluster create 自动均分;也可手动迁移 | redis-cli --cluster reshard |
| 故障检测 | 节点间互相 ping/pong;超时未响应标记为 pfail(主观失败) | 多数主节点同意后标记为 fail(客观失败),触发从节点选举 |
| 客户端要求 | 必须支持 Cluster 协议(如 Lettuce、StackExchange.Redis) | 普通客户端无法使用 |
| 限制 | 不支持多 key 操作跨槽(如 KEYS、MGET 跨槽 key) | 可通过 hash tag 强制同槽:{user123}.profile、{user123}.orders |
| 查看集群状态 | CLUSTER INFO / CLUSTER NODES | — |
常用 Cluster 命令
| 命令 | 语法 | 用途 | 示例 |
|---|
| CLUSTER MEET | CLUSTER MEET ip port | 手动将节点加入集群 | CLUSTER MEET 192.168.1.2 7000 |
| CLUSTER ADDSLOTS | CLUSTER ADDSLOTS slot [slot ...] | 为当前节点分配槽 | CLUSTER ADDSLOTS 0 1 2 |
| CLUSTER DELSLOTS | CLUSTER DELSLOTS slot [slot ...] | 移除当前节点的槽 | — |
| CLUSTER FAILOVER | CLUSTER FAILOVER | 手动触发从节点故障转移 | 用于计划内主从切换 |
| READONLY / READWRITE | — | 从节点默认只读;READWRITE 无效(仅主可写) | 在从节点执行 READONLY 可显式启用只读模式 |
Cluster vs Sentinel:
- Sentinel:适用于单主多从、需要读写分离的场景
- Cluster:适用于数据分片 + 高可用,突破单机内存/性能瓶颈