Redis 简介
Redis(Remote Dictionary Server)是一个开源的、高性能的键值存储系统(Key-Value Store),它以内存作为主要存储介质,支持持久化到磁盘。Redis 常用于缓存、数据库、消息队列和实时应用场景,因为它读写速度极快(每秒可处理数十万次操作),并支持丰富的数据结构。不同于传统的关系型数据库(如 MySQL),Redis 是 NoSQL 数据库,数据以键值对形式存储,每个键是唯一的字符串,值可以是多种数据类型。Redis 支持主从复制、哨兵模式和高可用集群,适用于分布式系统。它由 C 语言编写,支持多种编程语言客户端(如 Java、Python、Go 等)。
Redis 的核心优势包括:
- 高性能:内存操作,延迟低。
- 持久化:支持 RDB(快照)和 AOF(日志)两种方式,避免数据丢失。
- 多功能:可作为缓存(设置过期时间)、会话存储、排行榜等。
- 原子性:许多操作是原子性的,支持事务(MULTI/EXEC)和 Lua 脚本。
Redis 的五种基本数据类型
Redis 支持五种核心数据类型,每种类型有独特的特点和操作指令。这些类型允许 Redis 不仅仅是简单的键值存储,还能处理复杂的数据结构。以下用表格形式总结每种数据类型的特点、常见应用场景和典型指令操作。指令通常以大写形式书写,参数用小写表示(如 SET key value)。所有操作的时间复杂度大多为 O(1) 或 O(n),具体取决于指令。
| 数据类型 | 特点 | 常见应用场景 | 典型指令操作 |
|---|---|---|---|
| String (字符串) | 最简单的数据类型,值可以是字符串、整数、浮点数或二进制数据(最大 512MB)。支持增减操作,常用于简单存储。特点:简单、高效,支持位操作和数值运算。 | 缓存字符串数据、计数器、分布式锁(SETNX)。 | - SET key value:设置键的值。 - GET key:获取键的值。 - INCR key:原子递增整数值(+1)。 - DECR key:原子递减整数值(-1)。 - APPEND key value:追加字符串。 - STRLEN key:获取字符串长度。 - SETEX key seconds value:设置值并指定过期时间(秒)。 时间复杂度:大多 O(1)。 |
| List (列表) | 双向链表结构,支持从两端插入/弹出元素(最大 2^32-1 个元素)。特点:有序、可重复、支持队列/栈操作,适合顺序访问,但随机访问慢(O(n))。 | 消息队列、任务列表、最近访问记录(先进先出或后进先出)。 | - LPUSH key value:从左侧插入元素。 - RPUSH key value:从右侧插入元素。 - LPOP key:从左侧弹出元素。 - RPOP key:从右侧弹出元素。 - LRANGE key start stop:获取指定范围元素(start/stop 为索引,0 为第一个)。 - LLEN key:获取列表长度。 - LINDEX key index:获取指定索引元素。 时间复杂度:两端操作 O(1),中间操作 O(n)。 |
| Set (集合) | 无序、不重复的元素集合(最大 2^32-1 个元素)。特点:自动去重,支持集合运算(如交、并、差),适合唯一性检查。 | 标签系统、好友列表、唯一访客统计。 | - SADD key member:添加元素(重复忽略)。 - SREM key member:移除元素。 - SMEMBERS key:获取所有元素(无序)。 - SCARD key:获取元素数量。 - SISMEMBER key member:检查元素是否存在。 - SINTER key1 key2:求交集。 - SUNION key1 key2:求并集。 - SDIFF key1 key2:求差集。 时间复杂度:添加/移除/检查 O(1),集合运算 O(n)。 |
| Hash (哈希) | 键值对的映射表(类似字典或对象),字段(field)唯一,值可为字符串(最大 2^32-1 个字段)。特点:节省内存,适合存储对象属性,不支持嵌套。 | 存储用户信息(如 id: {name: "Alice", age: 30})、配置项。 | - HSET key field value:设置字段的值。 - HGET key field:获取字段的值。 - HMSET key field1 value1 field2 value2:批量设置。 - HGETALL key:获取所有字段和值。 - HDEL key field:删除字段。 - HLEN key:获取字段数量。 - HINCRBY key field increment:字段值原子递增。 时间复杂度:大多 O(1)。 |
| Sorted Set (有序集合,ZSet) | 集合的有序版本,每个元素关联一个分数(score,双精度浮点),按分数排序(最大 2^32-1 个元素)。特点:唯一元素、有序、支持范围查询和排名。 | 排行榜、优先级队列、时间线排序。 | - ZADD key score member:添加元素和分数(重复更新分数)。 - ZREM key member:移除元素。 - ZSCORE key member:获取元素分数。 - ZRANGE key start stop [WITHSCORES]:按分数升序获取范围元素(可带分数)。 - ZREVRANGE key start stop:按分数降序获取。 - ZRANK key member:获取元素排名(从 0 开始)。 - ZINCRBY key increment member:增加分数。 - ZCARD key:获取元素数量。 时间复杂度:添加/移除 O(log n),范围查询 O(log n + m)(m 为结果数)。 |
操作这些数据类型的通用注意事项
- 键管理:所有数据类型都以键(key)作为标识,键是字符串,支持过期(EXPIRE key seconds)和删除(DEL key)。
- 原子性:Redis 操作大多原子,支持管道(pipeline)和事务(MULTI/EXEC/DISCARD)来批量执行。
- 持久化与复制:数据在内存中,但可配置持久化。操作时需考虑内存使用,避免大键导致性能问题。
- 客户端使用:在实际编程中,使用 Redis 客户端库执行这些指令,如 Python 的 redis-py。
redis主从复制
Redis 主从复制 (Master-Replica Replication,也叫主从复制、主备复制)是 Redis 实现读写分离 和高可用最基础、最核心的机制。从 Redis 5.0 开始,官方把"slave"改成了"replica",命令也从 SLAVEOF 改为 REPLICAOF,但很多老配置和文档仍使用 slave 字样。
主从复制的核心作用
- 读写分离:主节点(Master/Primary)负责写,从节点(Replica)负责读,大幅提升读吞吐量。
- 数据冗余:从节点是主节点的近实时副本,防止单点数据丢失。
- 故障恢复基础:主节点挂掉后,可手动或通过 Sentinel/Cluster 自动把某个从节点提升为主(failover)。
- 水平扩展读能力:可以挂多个从节点(1主多从,甚至级联复制)。
主从复制的工作原理(简要流程)
- 从节点执行
REPLICAOF <master-ip> <master-port>(或配置文件中写replicaof)。 - 从节点与主节点建立 TCP 连接。
- 全量同步 (第一次或断开太久重连):
- 主节点执行 BGSAVE(后台生成 RDB),同时把新写命令缓存到 replication backlog。
- RDB 文件通过网络传输给从节点(可选择 diskless 方式)。
- 从节点清空自己数据,加载 RDB。
- 增量同步 (命令传播阶段):
- 主节点把所有写命令通过 replication buffer 实时发给所有从节点。
- 从节点顺序执行这些命令,保持数据一致。
- 断线重连 :
- 从节点自动重连主节点。
- 如果 replication backlog 里还有断开期间的命令 → 部分重同步(partial resync)。
- 否则 → 再次全量同步。
重要概念:
- replication backlog:主节点内存中的环形缓冲区(默认 1MB,可调大到 10--256MB),保存最近写命令,用于部分重同步。
- run id:每个 Redis 实例启动都有唯一 run id,用于判断是否是同一主节点。
- replid + offset:从节点记录当前复制到的位置。
如何配置主从复制
以下以 Redis 7.x / 8.x 版本为例(目前最常见版本)。
方式一:配置文件方式(推荐生产环境)
主节点(master)redis.conf(通常改动较少)
ini
# 监听所有网卡(生产必须改,勿留 127.0.0.1)
bind 0.0.0.0
# 端口(默认即可,也可改)
port 6379
# 开启保护模式(建议开启,除非有密码)
protected-mode yes
# 如果设置密码,从节点必须匹配
requirepass your_strong_password_123
# 建议开启 AOF + 定期 RDB(至少一种持久化)
appendonly yes
appendfsync everysec
save 60 10000 # 根据业务调整
从节点(replica)redis.conf(最关键改动在这里)
ini
# 与主节点相同的基本配置
bind 0.0.0.0
port 6380 # 建议不同端口或不同机器
requirepass your_strong_password_123
# ======== 复制相关核心配置 ========
replicaof 192.168.1.101 6379 # 主节点的 IP:端口(旧版写 slaveof)
# 如果主节点有密码,必须配置(强烈推荐)
masterauth your_strong_password_123 # 旧版写 masterauth
# 或新版写法(Redis 6+ 推荐使用 ACL)
masteruser replication_user
masterauth replication_pass
# 从节点只读(默认 yes,强烈建议保持)
replica-read-only yes
# 是否使用无盘复制(推荐生产开启,尤其是大流量场景)
repl-diskless-sync yes
repl-diskless-sync-delay 5 # 等待几秒让多个从同时同步,减少主压力
# 复制超时(默认 60s,可适当加大)
replica-timeout 120
# 部分重同步 backlog 大小(生产建议 64MB--256MB,根据写压力)
repl-backlog-size 128mb
# 最小可用从节点数 & 最大延迟(写安全保护)
min-replicas-to-write 1
min-replicas-max-lag 10
启动方式:
bash
# 主节点
redis-server /etc/redis/redis-master.conf
# 从节点
redis-server /etc/redis/redis-replica.conf
方式二:命令行动态配置(适合测试、临时挂从)
在从节点 redis-cli 中直接执行:
bash
# Redis 5.0+ 推荐写法
REPLICAOF 192.168.1.101 6379
# 如果主有密码(Redis 6+ ACL 风格)
ACL SETUSER replication_user on >replication_pass +@all
# 然后
REPLICAOF 192.168.1.101 6379
# 旧版写法(Redis < 5.0)
SLAVEOF 192.168.1.101 6379
取消复制(把当前节点变回独立主节点):
bash
REPLICAOF NO ONE
常用查看命令
bash
# 查看当前节点角色、复制状态
INFO replication
# 示例输出片段
role:master
connected_slaves:2
master_repl_offset:12874921
repl_backlog_active:1
repl_backlog_size:134217728
# 或
role:slave
master_host:192.168.1.101
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0 |
主从复制本身不提供自动故障转移 ,如果需要自动主备切换 ,需要再引入 Redis Sentinel (哨兵)或 Redis Cluster。
Redis 哨兵模式(Sentinel)
Redis 哨兵模式(Sentinel) 是 Redis 官方提供的高可用解决方案,主要用于实现主从架构的自动故障转移(Automatic Failover) 。
它在 Redis 主从复制的基础上,增加了一层"哨兵"进程,用于监控主从节点的健康状态,并在主节点故障时自动完成主从切换。
Sentinel 本身也是 Redis 进程的一种特殊模式(redis-sentinel 或 redis-server --sentinel),多个 Sentinel 组成一个分布式系统,通过 Raft-like 协议(quorum 投票)来达成共识。
Sentinel 的核心功能
- 持续监控:监控主节点(master)和从节点(replicas)的运行状态。
- 故障检测 :
- 主观下线(Subjectively Down, s_down):单个 Sentinel 认为 master 挂了。
- 客观下线(Objectively Down, o_down):多个 Sentinel 达成共识(达到 quorum)。
- 自动故障转移:当 master o_down 后,选举一个新 master,并完成切换。
- 配置提供者:Sentinel 对外提供当前有效的 master 地址(服务发现)。
- 通知:可以通过脚本通知管理员(邮件、短信、企业微信等)。
注意 :Sentinel 不存储数据,只负责管理和协调。数据仍然在 Redis 主从节点上。
典型架构推荐(至少 3 台 Sentinel)
+-------------+ +-------------+
| Sentinel 1 |<----------->| Sentinel 2 |
+-------------+ +-------------+
^ ^
| |
+-------------+-------------+
|
v
+-------------+ +-------------+ +-------------+
| Master |<->| Replica1 |<->| Replica2 |
+-------------+ +-------------+ +-------------+
- 至少 3 个 Sentinel(奇数,避免脑裂),分布在不同机器/可用区。
- quorum 通常设为 2(多数派:≥ (n/2)+1)。
如何配置 Redis Sentinel(主流做法,Redis 7.x / 8.x)
步骤 1:准备主从环境
确保已经有一个主节点 + 至少 1--2 个从节点(参考上一次讲解的主从复制配置),并且主从复制正常(INFO replication 看到 role:master + connected_slaves ≥1)。
步骤 2:创建 sentinel.conf(每个 Sentinel 都用类似配置)
ini
# sentinel.conf 示例(生产推荐)
# 端口(不同 Sentinel 建议不同端口,或不同机器)
port 26379
# 绑定地址(生产必须改)
bind 0.0.0.0
# 守护进程模式
daemonize yes
# pid 文件
pidfile /var/run/redis-sentinel.pid
# 日志文件
logfile "/var/log/redis/sentinel.log"
# Sentinel 工作目录(很重要,会在这里写配置文件)
dir /var/lib/redis/sentinel/
# ======== 核心监控配置 ========
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.1.101 6379 2
# 主观下线判定时间(毫秒):超过这个时间没响应 PING 就算主观下线
sentinel down-after-milliseconds mymaster 10000 # 10秒,生产建议 5--30秒
# 并行同步从节点数量(故障转移后让多少个从同时去同步新主)
sentinel parallel-syncs mymaster 1 # 通常设 1,避免主压力过大
# 故障转移超时(整个 failover 流程超时时间)
sentinel failover-timeout mymaster 180000 # 180秒
# ======== 安全相关(强烈推荐) ========
# Sentinel 自身密码(Redis 6+ ACL 方式更推荐)
requirepass sentinel_strong_pass_2026
# 如果 Redis 主节点有密码,Sentinel 必须知道
sentinel auth-pass mymaster redis_master_pass_2026
# 或 Redis 6+ ACL 方式
# sentinel auth-user mymaster replication_user
# sentinel auth-pass mymaster replication_pass
# ======== 其他优化 ========
sentinel announce-ip 192.168.1.201 # 如果 Sentinel 在 NAT/容器中,公告自己的外网IP
sentinel announce-port 26379
# 保护模式(建议开启)
protected-mode yes
关键参数解释:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| sentinel monitor ... quorum | 2(3哨兵时) | 至少几个哨兵认为 down 才算客观下线,建议 (sentinel数量/2)+1 |
| down-after-milliseconds | 5000--30000 ms | 太短误判,太多恢复慢 |
| parallel-syncs | 1--3 | 越大切换后数据同步越快,但主压力越大 |
| failover-timeout | 180000--600000 | 包含选举、切换、清理的全流程超时 |
| auth-pass / auth-user | 必须配置 | 主节点有密码时必填,否则 Sentinel 无法连接主从 |
步骤 3:启动多个 Sentinel
bash
# 在三台机器(或同一台不同端口)分别启动
redis-sentinel /etc/redis/sentinel.conf
# 或
redis-server /etc/redis/sentinel.conf --sentinel
推荐 systemd 服务方式管理。
步骤 4:验证 Sentinel 是否正常工作
bash
redis-cli -p 26379
> SENTINEL masters # 查看所有监控的主
> SENTINEL master mymaster # 查看某个主的详细信息
> SENTINEL replicas mymaster # 查看从节点
> SENTINEL get-master-addr-by-name mymaster # 最重要的:当前 master 的地址
正常输出示例:
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
1) "192.168.1.101"
2) "6379"
自动故障转移(Automatic Failover)详细流程
- Sentinel 每秒 PING 主从节点。
- 如果 master 在
down-after-milliseconds内无响应 → 该 Sentinel 标记为主观下线(s_down)。 - 多个 Sentinel 通过 gossip 协议交换信息,如果达到 quorum 个 Sentinel 都认为 s_down → 升级为客观下线(o_down)。
- 触发故障转移的 Sentinel(通常是第一个发现 o_down 的,称为 leader)开始选举:
- 按照一定优先级(replica-priority 配置,默认为 100,越小优先级越高) + 复制偏移量 + runid 选出一个从节点作为新主。
- leader 向选中的从节点发送
SLAVEOF NO ONE→ 让它变成主。 - 向其他从节点发送
SLAVEOF 新主IP 新主端口→ 让它们跟随新主。 - 更新 Sentinel 自己的配置,并通过 pub/sub 通知其他 Sentinel 和客户端。
- 整个过程通常在 几秒到几十秒 内完成(取决于 down-after-milliseconds 和网络)。
客户端如何感知新主?(重要!)
- 推荐方式 :使用 支持 Sentinel 的智能客户端 (大多数语言都有)
- Java → JedisSentinelPool / Lettuce
- Python → redis-py 的 Sentinel 连接池
- Go → go-redis/redis 的 Sentinel 模式
- 客户端连接到任意一个 Sentinel,Sentinel 会返回当前 master 地址。
- 故障转移后,Sentinel 会通过 pub/sub 频道
+switch-master通知客户端,客户端自动更新连接。
手动触发故障转移测试(生产慎用):
bash
SENTINEL failover mymaster # 强制故障转移(即使主没挂)
生产注意事项
- 至少 3 个 Sentinel,分布不同可用区/机架。
- quorum = (sentinel 数量 / 2) + 1。
- 开启主节点的 min-replicas-to-write 和 min-replicas-max-lag,防止写到"孤岛主"。
- Sentinel 自身也需要高可用(多实例 + 监控)。
- 记录日志,配置通知脚本(sentinel notification-script)。
- Redis 6+ 强烈推荐使用 ACL 而非简单 requirepass。
- 如果需要更高可用和分片 → 考虑 Redis Cluster 而非单纯 Sentinel。