Redis 核心知识与高可用架构实践

Redis(Remote Dictionary Server)是一种非关系型数据库(NoSQL),以 Key-Value 模型为核心,所有数据常驻内存、单线程处理命令,因此具备极低的读写延迟与极高的并发吞吐。

它的 Key 恒为字符串类型,而 Value 则支持五种基础数据结构:String、Hash、List、Set、ZSet(Sorted Set)。正是这五种结构,让 Redis 从"一个缓存工具"演进为"一个通用内存计算引擎"。

文章目录

    • 一、五大数据类型总览
    • 二、String(字符串)
      • [1. 命令速查](#1. 命令速查)
      • [2. 创建与读取 Key](#2. 创建与读取 Key)
      • [3. 读取 Key 的值](#3. 读取 Key 的值)
      • [4. 删除 Key](#4. 删除 Key)
      • [5. 批量设置与批量获取](#5. 批量设置与批量获取)
      • [6. 追加、覆盖返回旧值、取长度](#6. 追加、覆盖返回旧值、取长度)
      • [7. 过期时间:TTL / EXPIRE / PERSIST](#7. 过期时间:TTL / EXPIRE / PERSIST)
      • [8. 原子计数器:INCR / DECR 家族](#8. 原子计数器:INCR / DECR 家族)
    • 三、List(列表)
      • [1. 命令速查](#1. 命令速查)
      • [2. 插入语义](#2. 插入语义)
      • [3. 查询与修改](#3. 查询与修改)
      • [4. 删除](#4. 删除)
    • 四、Set(集合)
      • [1. 命令速查](#1. 命令速查)
      • [2. 增删查](#2. 增删查)
      • [3. 集合间运算](#3. 集合间运算)
    • 五、ZSet(有序集合)
      • [1. 命令速查](#1. 命令速查)
      • [2. 创建与批量写入](#2. 创建与批量写入)
      • [3. 排名、分数与删除](#3. 排名、分数与删除)
    • 六、Hash(哈希)
      • [1. 命令速查](#1. 命令速查)
      • [2. 完整操作示例](#2. 完整操作示例)
    • 七、消息队列
      • [1. 生产者 / 消费者模式(Producer / Consumer)](#1. 生产者 / 消费者模式(Producer / Consumer))
      • [2. 发布者 / 订阅者模式(Publisher / Subscriber)](#2. 发布者 / 订阅者模式(Publisher / Subscriber))
    • [八、接入 Redis 的三种方式](#八、接入 Redis 的三种方式)
      • [1. Shell 脚本访问 Redis](#1. Shell 脚本访问 Redis)
      • [2. 程序连接 Redis](#2. 程序连接 Redis)
    • 九、高可用演进路线
    • [十、容器化部署 Redis](#十、容器化部署 Redis)
    • 十一、三种架构选型对比
    • 总结

一、五大数据类型总览

类型 名称 核心特征 典型场景
String 字符串 最基本的存储单元,可存字符串、整数、浮点数 缓存、计数器、分布式锁
Hash 哈希 字段与值的映射集合,一个 Key 可挂多个 Field 对象存储(用户信息、商品详情)
List 列表 按插入顺序排序的字符串数组,两端可操作 消息队列、时间线、最新列表
Set 集合 无序且元素唯一,支持集合间逻辑运算 去重、共同好友、标签系统
ZSet 有序集合 每个成员关联一个 score,按分数排序 排行榜、延时队列、带权去重

二、String(字符串)

字符串是最基础的 Redis 值类型,也是使用频率最高的类型。

关键特性:

  • 二进制安全:一个 Redis 字符串可以承载任意类型的数据,一张 JPEG 图片、一个序列化后的对象都可以直接存入;
  • 容量上限 :单个 String 类型的 Value 最大可存储 512 MB;
  • Key 恒为字符串 :Redis 中所有的 Key 都是字符串类型,且严格区分大小写。

1. 命令速查

命令 说明
`SET key value [EX seconds] [PX milliseconds] [NX XX]`
GET key 获取 key 的值
SETEX key seconds value 设置值并指定过期时间(秒)
SETNX key value 仅当 key 不存在时设置(分布式锁基础)
INCR key 将 key 中的数字加 1
INCRBY key increment 将 key 中的数字增加指定值
DECR / DECRBY 减操作
MSET key1 value1 [key2 value2 ...] 批量设置
MGET key1 [key2 ...] 批量获取

2. 创建与读取 Key

SET 用于创建一个 Key 并赋值,语法如下(时间复杂度 O(1)):

bash 复制代码
SET key value [EX seconds] [PX milliseconds] [NX|XX]
  • 若 Key 已持有其他值,SET 会无条件覆写旧值,无视其类型;
  • 对一个带 TTL 的 Key 执行 SET 后,原有的过期时间将被清除;
  • 自 Redis 2.6.12 起,可通过参数改变行为:
    • EX seconds:设置过期秒数,等价于 SETEX key seconds value;
    • PX milliseconds:设置过期毫秒数,等价于 PSETEX key milliseconds value;
    • NX:只在键不存在时才写入,等价于 SETNX;
    • XX:只在键已存在时才更新。
bash 复制代码
# 不论 key 是否存在,都执行设置
127.0.0.1:6379> SET key1 value1
OK
127.0.0.1:6379> GET key1
"value1"
127.0.0.1:6379> TYPE key1
string

# EX:设置 3 秒后自动过期
127.0.0.1:6379> SET title ceo EX 3
OK
127.0.0.1:6379> GET title          # 3 秒后再次查询
(nil)

# Key 严格区分大小写
127.0.0.1:6379> SET name wang
OK
127.0.0.1:6379> SET NAME li
OK
127.0.0.1:6379> GET name
"wang"
127.0.0.1:6379> GET NAME
"li"

# SETNX:仅当 Key 不存在时才赋值
127.0.0.1:6379> SETNX title coo
(integer) 1
127.0.0.1:6379> GET title
"coo"
127.0.0.1:6379> SETNX title ceo    # title 已存在,写入被拒绝
(integer) 0
127.0.0.1:6379> GET title
"coo"

# XX:仅当 Key 已存在时才更新
127.0.0.1:6379> SET title ceo XX
OK
127.0.0.1:6379> GET title
"ceo"

3. 读取 Key 的值

GET 一次只能查看一个 Key 的值:

bash 复制代码
127.0.0.1:6379> GET key1
"value1"
127.0.0.1:6379> GET name age
(error) ERR wrong number of arguments for 'get' command

4. 删除 Key

bash 复制代码
127.0.0.1:6379> DEL key1
(integer) 1
127.0.0.1:6379> DEL key1 key2      # 返回成功删除的数量
(integer) 0

5. 批量设置与批量获取

bash 复制代码
127.0.0.1:6379> MSET key1 value1 key2 value2
OK

127.0.0.1:6379> MGET key1 key2
1) "value1"
2) "value2"

127.0.0.1:6379> KEYS n*
1) "name"
127.0.0.1:6379> KEYS *
1) "name"
2) "key1"
3) "NAME"
4) "title"
5) "key2"

MSET / MGET 以单次往返完成多键操作,是降低网络开销最直接的手段;KEYS 会全量扫描键空间,生产环境应改用 SCAN。

6. 追加、覆盖返回旧值、取长度

bash 复制代码
# APPEND:向已有值尾部追加字符串,返回追加后的字节长度
127.0.0.1:6379> APPEND key1 " append new value"
(integer) 22
127.0.0.1:6379> GET key1
"value1 append new value"

# GETSET:设置新值并返回旧值(原子操作)
127.0.0.1:6379> SET name wang
OK
127.0.0.1:6379> GETSET name xiyangyang
"wang"
127.0.0.1:6379> GET name
"xiyangyang"

# STRLEN:返回 Value 的字节数(注意是字节,不是字符)
127.0.0.1:6379> SET name wang
OK
127.0.0.1:6379> STRLEN name
(integer) 4
127.0.0.1:6379> APPEND name " teng"
(integer) 9
127.0.0.1:6379> GET name
"wang teng"
127.0.0.1:6379> STRLEN name
(integer) 9

7. 过期时间:TTL / EXPIRE / PERSIST

TTL key 查看 Key 的剩余生存时间,Key 到期后会被自动删除。返回值语义固定为三种:

返回值 含义
-1 Key 存在但永不过期(新建 Key 的默认状态;重新赋值也会重置为永不过期)
-2 Key 不存在(含已过期被回收)
n Key 剩余的有效秒数
bash 复制代码
# 重置过期时长
127.0.0.1:6379> TTL name
(integer) 97
127.0.0.1:6379> EXPIRE name 1000
(integer) 1
127.0.0.1:6379> TTL name
(integer) 996

# 取消过期设置,恢复为永不过期
127.0.0.1:6379> TTL name
(integer) 957
127.0.0.1:6379> PERSIST name
(integer) 1
127.0.0.1:6379> TTL name
(integer) -1

8. 原子计数器:INCR / DECR 家族

利用 INCR、DECR、INCRBY、DECRBY,可以把字符串当作原子计数器使用------这是 Redis 单线程命令执行模型带来的天然保证。

bash 复制代码
# INCR:自增 1
127.0.0.1:6379> SET num 10
OK
127.0.0.1:6379> INCR num
(integer) 11
127.0.0.1:6379> GET num
"11"
127.0.0.1:6379> INCR num
(integer) 12
127.0.0.1:6379> GET num
"12"

# DECR:自减 1
127.0.0.1:6379> SET num 10
OK
127.0.0.1:6379> DECR num
(integer) 9
127.0.0.1:6379> GET num
"9"

INCRBY key increment 将 Key 对应的数字加上指定增量(可为负数):

  • Key 不存在时,操作前会被隐式置为 0;
  • Value 类型错误或非数字字符串时返回错误;
  • 最大支持 64 位有符号整数。
bash 复制代码
127.0.0.1:6379> SET mykey 10
OK
127.0.0.1:6379> INCRBY mykey 5
(integer) 15
127.0.0.1:6379> GET mykey
"15"
127.0.0.1:6379> INCRBY mykey -10     # 增量可为负
(integer) 5
127.0.0.1:6379> GET mykey
"5"
127.0.0.1:6379> INCRBY nokey1 5      # Key 不存在,按 0 起算
(integer) 5
127.0.0.1:6379> GET nokey1
"5"

# DECRBY:同样支持负数(即反向增加)
127.0.0.1:6379> SET mykey 10
OK
127.0.0.1:6379> DECRBY mykey 8
(integer) 2
127.0.0.1:6379> DECRBY mykey -20
(integer) 22
127.0.0.1:6379> GET mykey
"22"
127.0.0.1:6379> DECRBY nokey2 3      # Key 不存在,结果为 -3
(integer) -3
127.0.0.1:6379> GET nokey2
"-3"

三、List(列表)

Redis 的 List 本质上是一个按插入顺序排序的字符串数组。

关键特性:

  • 支持双向读写,可从头部(左)或尾部(右)插入与弹出;
  • 单个列表最多容纳 2^32 - 1 = 4294967295 个元素;
  • 元素通过下标定位:0 为首个元素,1 为第二个,以此类推;也支持负数下标 ,-1 表示最后一个元素,-2 表示倒数第二个;
  • 元素可重复 ,常用于日志、任务队列等场景。

1. 命令速查

命令 说明
LPUSH key value [value ...] 从左边(表头)插入元素
RPUSH key value [value ...] 从右边(表尾)插入元素
LPOP key 弹出左边第一个元素
RPOP key 弹出右边第一个元素
LRANGE key start stop 获取指定范围的元素(支持负数索引)
LLEN key 获取列表长度
LINDEX key index 获取指定索引的元素
LSET key index value 修改指定索引的元素
LREM key count value 删除 count 个等于 value 的元素

2. 插入语义

bash 复制代码
LPUSH key value [value ...]   # 时间复杂度 O(1),插入表头
RPUSH key value [value ...]   # 时间复杂度 O(1),插入表尾

多个 value 会按从左到右的顺序依次插入:

  • 对空列表执行 LPUSH mylist a b c,结果为 c b a,等价于原子性地依次执行 LPUSH mylist a、LPUSH mylist b、LPUSH mylist c;
  • 对空列表执行 RPUSH mylist a b c,结果为 a b c。

Key 不存在时会自动创建空列表;Key 存在但不是列表类型时返回错误。

bash 复制代码
# 从左边添加,已有元素整体右移
127.0.0.1:6379> LPUSH phone xiaomi apple huawei
(integer) 3
127.0.0.1:6379> TYPE phone
list

# 从右边添加,已有元素整体左移
127.0.0.1:6379> RPUSH id 18 19 20
(integer) 3
127.0.0.1:6379> TYPE id
list

# 追加新元素
127.0.0.1:6379> LPUSH list1 tom
(integer) 1
127.0.0.1:6379> RPUSH list1 jack
(integer) 2

# 获取列表长度
127.0.0.1:6379> LLEN list1
(integer) 2

3. 查询与修改

bash 复制代码
# LRANGE 取全量:0 到 -1
127.0.0.1:6379> RPUSH list4 a b c d e f
(integer) 6
127.0.0.1:6379> LRANGE list4 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"

# LSET 按下标修改
127.0.0.1:6379> LSET list4 2 cloud
OK
127.0.0.1:6379> LRANGE list4 0 -1
1) "a"
2) "b"
3) "cloud"
4) "d"
5) "e"
6) "f"

4. 删除

bash 复制代码
127.0.0.1:6379> DEL list1
(integer) 1
127.0.0.1:6379> EXISTS list1
(integer) 0

四、Set(集合)

Set 是一个无序的字符串集合 ,同一集合内每个元素唯一、不可重复。它的独特之处在于支持集合间的逻辑运算------交集、并集、差集,因此天然适配"共同好友""标签圈选""去重统计"这类场景。

1. 命令速查

命令 说明
SADD key member [member ...] 添加一个或多个成员
SMEMBERS key 获取集合所有成员
SISMEMBER key member 判断成员是否在集合中
SREM key member [member ...] 删除一个或多个成员
SCARD key 获取集合成员数量
SINTER key1 [key2 ...] 求交集
SUNION key1 [key2 ...] 求并集
SDIFF key1 [key2 ...] 求差集

2. 增删查

bash 复制代码
# 追加:已存在的元素无法重复添加
127.0.0.1:6379> SADD set1 v2 v3 v4
(integer) 3
127.0.0.1:6379> SADD set1 v2         # 已存在,返回 0
(integer) 0

# 获取集合全部成员(顺序不保证)
127.0.0.1:6379> SMEMBERS set1
1) "v4"
2) "v3"
3) "v1"
4) "v2"
127.0.0.1:6379> SMEMBERS set2
1) "v4"
2) "v2"

# 删除指定元素
127.0.0.1:6379> SADD name1 xiyangyang meiyangyang feiyangyang
(integer) 3
127.0.0.1:6379> SMEMBERS name1
1) "feiyangyang"
2) "meiyangyang"
3) "xiyangyang"
127.0.0.1:6379> SREM name1 meiyangyang
(integer) 1
127.0.0.1:6379> SMEMBERS name1
1) "feiyangyang"
2) "xiyangyang"

3. 集合间运算

bash 复制代码
# 交集:同时属于 A 和 B 的元素(如 QQ 共同好友)
127.0.0.1:6379> SINTER set1 set2
1) "v4"
2) "v2"

# 并集:属于 A 或属于 B 的元素
127.0.0.1:6379> SUNION set1 set2
1) "v3"
2) "v1"
3) "v2"
4) "v4"

# 差集:属于 A 但不属于 B 的元素(如"我朋友的朋友")
127.0.0.1:6379> SDIFF set1 set2
1) "v3"
2) "v1"

五、ZSet(有序集合)

ZSet 与 Set 一样不允许成员重复,差别在于:每个成员都关联一个双精度浮点型分数(score),Redis 依据分数把所有成员从低到高排序。

关键特性:

  • 有序:按 score 升序排列;
  • 成员唯一 :value 不可重复,但 score 可以重复;
  • 单个有序集合最多容纳 2^32 - 1 = 4294967295 个成员;
  • 每个元素由 score + value 两部分构成;
  • 最经典的应用场景是排行榜。

1. 命令速查

命令 说明
ZADD key score member [score member ...] 添加带分数的成员
ZRANGE key start stop [WITHSCORES] 按分数升序返回成员
ZREVRANGE key start stop [WITHSCORES] 按分数降序返回成员
ZREM key member [member ...] 删除成员
ZCARD key 获取成员数量
ZSCORE key member 获取成员的分数
ZRANK key member 获取成员的排名(升序)

2. 创建与批量写入

bash 复制代码
127.0.0.1:6379> ZADD zset1 1 v1       # 分数为 1
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v2
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v3       # 分数可重复,元素值不可重复
(integer) 1
127.0.0.1:6379> ZADD zset1 3 v4
(integer) 1
127.0.0.1:6379> TYPE zset1
zset

# 一次性写入多个成员
127.0.0.1:6379> ZADD zset2 1 v1 2 v2 3 v3 4 v4 5 v5
(integer) 5

3. 排名、分数与删除

bash 复制代码
# 查看成员个数
127.0.0.1:6379> ZCARD course
(integer) 4
127.0.0.1:6379> ZCARD zset1
(integer) 4
127.0.0.1:6379> ZCARD zset2
(integer) 5

# 查询指定成员的排名(从 0 开始,按分数升序)
127.0.0.1:6379> ZRANK course go
(integer) 3
127.0.0.1:6379> ZRANK course python
(integer) 1

# 获取成员的分数
127.0.0.1:6379> ZSCORE course cloud
"50"

# 按索引区间读取与删除
127.0.0.1:6379> ZRANGE course 0 -1
1) "cloud"
2) "python"
3) "linux"
4) "go"
127.0.0.1:6379> ZREM course python go
(integer) 2
127.0.0.1:6379> ZRANGE course 0 -1
1) "cloud"
2) "linux"

六、Hash(哈希)

Hash 即字典,用于保存字符串字段(field)与字符串值(value)之间的映射,本质上是一个 Key 之下再挂一组 K/V 的二级结构。它特别适合存储对象,单个 Hash 最多可包含 2^32 - 1 个键值对。

特点: 无序、以 K/V 对组织、适合存放彼此相关的一组数据。

1. 命令速查

命令 说明
HSET key field value 设置 hash 字段的值
HGET key field 获取 hash 字段的值
HMSET key field1 value1 [field2 value2 ...] 批量设置(Redis 4.0+ 推荐直接用 HSET)
HMGET key field1 [field2 ...] 批量获取字段
HGETALL key 获取所有字段和值
HKEYS key 获取所有字段名
HVALS key 获取所有字段值
HDEL key field [field ...] 删除一个或多个字段
HEXISTS key field 判断字段是否存在

2. 完整操作示例

bash 复制代码
# 创建 Hash(Key 不存在时自动创建;field 已存在则旧值被覆盖)
127.0.0.1:6379> HSET 9527 name zhouxingxing age 20
(integer) 2
127.0.0.1:6379> TYPE 9527
hash

# 查看所有字段与值
127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "20"

# 增加字段
127.0.0.1:6379> HSET 9527 gender male
(integer) 1
127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "20"
5) "gender"
6) "male"

# 读取指定字段 / 批量读取
127.0.0.1:6379> HGET 9527 name
"zhouxingxing"
127.0.0.1:6379> HGET 9527 age
"20"
127.0.0.1:6379> HMGET 9527 name age
1) "zhouxingxing"
2) "20"

# 删除指定字段
127.0.0.1:6379> HDEL 9527 age
(integer) 1
127.0.0.1:6379> HGET 9527 age
(nil)
127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "gender"
4) "male"

# 批量设置多个字段
127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "gender"
4) "male"
5) "age"
6) "50"
7) "city"
8) "hongkong"

# 分别取出所有 field 与所有 value
127.0.0.1:6379> HKEYS 9527
1) "name"
2) "gender"
3) "age"
4) "city"
127.0.0.1:6379> HVALS 9527
1) "zhouxingxing"
2) "male"
3) "50"
4) "hongkong"

# 删除整个 Hash
127.0.0.1:6379> DEL 9527
(integer) 1
127.0.0.1:6379> EXISTS 9527
(integer) 0

七、消息队列

消息队列 把要传输的数据放入队列中,从而实现应用之间的数据交换。它的三大价值是:解耦、异步、削峰限流 。常见的消息队列中间件有 Kafka、RabbitMQ、Redis。

消息队列分为两种模型:

1. 生产者 / 消费者模式(Producer / Consumer)

多个消费者同时监听同一个队列,但一条消息只能被抢到它的那一个消费者消费一次 。队列可以由多个生产者写入、由多个消费者取出处理,应用最为广泛。

在 Redis 中,能真正实现这套语义的数据类型只有 List 和 Streams(此外 Redis 还提供了发布/订阅 Pub/Sub 模式)。

用 List 实现消息队列: 将需要延后处理的任务序列化成字符串塞进 Redis 列表,另一个线程从列表中轮询取出处理。几个入队、出队命令就能组合出多种用法:

组合 语义
LPUSH + RPOP 左进右出(FIFO)
RPUSH + LPOP 右进左出(FIFO)
LPUSH + BRPOP 左进右阻塞出
RPUSH + BLPOP 右进左阻塞出
bash 复制代码
# 生产消息
127.0.0.1:6379> LPUSH haizeiwang jishu1 jishu2 jishu3
(integer) 3

# 消费消息
127.0.0.1:6379> RPOP haizeiwang
"jishu3"
127.0.0.1:6379> RPOP haizeiwang
"jishu2"
127.0.0.1:6379> RPOP haizeiwang
"jishu1"
127.0.0.1:6379> RPOP haizeiwang
(nil)

# 验证队列消息已全部消费完成
127.0.0.1:6379> LRANGE haizeiwang 0 -1
(empty list or set)

及时消费问题: 若消费者想实时处理数据,就要在程序里写一个 while(true) 不断调用 RPOP / LPOP,这会带来不必要的 CPU 空转开销。

为此 Redis 提供了 BLPOP、BRPOP 这类阻塞式读取 命令(前缀 B 即 Blocking):客户端在没有读到队列数据时自动阻塞,直到有新数据写入才继续,从而省下无效轮询的开销。

2. 发布者 / 订阅者模式(Publisher / Subscriber)

发布者将消息发布到指定频道(channel),事先监听该频道的一个或多个订阅者都会收到同一条消息 。即"一消息多消费者",适用于社交应用中的群聊、群发、群公告等场景。

需注意:Pub/Sub 不持久化消息,离线订阅者会丢失期间的消息;若要求消息不丢,应使用 List + 阻塞弹出或 Streams。


八、接入 Redis 的三种方式

1. Shell 脚本访问 Redis

Redis 官方客户端 redis-cli 可直接嵌入 Shell 脚本,实现批量写入。

bash 复制代码
# 为脚本添加执行权限
[root@localhost ~]# chmod +x write_redis.sh

# 运行脚本
[root@localhost ~]# ./write_redis.sh
OK
......
OK
已成功写入100条数据到 Redis。

# 验证结果
[root@localhost ~]# redis-cli
127.0.0.1:6379> INFO keyspace
# Keyspace
db0:keys=100,expires=0,avg_ttl=0
127.0.0.1:6379> KEYS key:*

可选增强:

bash 复制代码
# 带密码认证(若 Redis 设置了 requirepass)
[root@localhost ~]# redis-cli -h 127.0.0.1 -p 6379 -a your_password

# 批量管道导入,性能远高于逐条写入
[root@localhost ~]# cat data.txt | redis-cli --pipe

-a 会让密码出现在进程列表中,生产环境建议使用 --askpass 交互输入或通过配置文件指定。

2. 程序连接 Redis

Redis 支持多种开发语言的客户端,官方清单见:

以 Python 为例,选用 redis-py 库(使用手册:https://redis.io/docs/latest/develop/clients/redis-py/)。

bash 复制代码
pip install redis

建立连接:

bash 复制代码
import redis

r = redis.Redis(host='192.168.108.172', port=6379, password='123456', db=0)
print(r)

参数说明:

参数 含义
host Redis 服务器 IP 地址(此处为局域网地址)
port Redis 默认端口 6379
password 认证密码,说明服务端配置了 requirepass 123456
db 使用的逻辑库编号,Redis 默认有 16 个库,编号 0~15

print(r) 打印的是客户端对象的内部描述,用于调试确认连接配置是否正确。

⚠️ 脚本文件名不要取作 redis.py ,否则会与 redis 模块同名冲突,导致导入异常。

接收 set 的返回值:

bash 复制代码
import redis

r = redis.Redis(host='192.168.108.172', port=6379, password='123456', db=0)
print(r)

# 接收 set 操作的返回值
result = r.set('color1', 'red')
print(result)     # 输出 True(或 'OK',取决于 redis-py 版本)

r.set('color1', 'red') 向 Redis 写入一个字符串键值对(键 color1、值 red),等价于在 CLI 中执行 SET color1 red。

redis-py 版本 r.set() 成功时的返回值
4.0.0 及以上 True(布尔值,当前主流版本)
3.x 及更早 b'OK'(字节串)

自 redis-py 4.0 起,为贴合 Python 习惯,成功操作统一返回 True,失败则抛出异常(如连接错误、认证失败)。

存取值与字符串操作:

bash 复制代码
# 存储与读取
r.set('color1', 'red')
value = r.get('color1')
print(value)

# 字符串数字操作:incr 自增、decr 自减、append 追加
r.set('int1', 10)
result = r.incr('int1')
result = r.decr('int1')
print(result)

列表操作:

bash 复制代码
r.lpush('mylist', 'nihao')
r.lpush('mylist', 'laogao')
print(r.lrange('mylist', 0, -1))

逐行解读:

  • r.lpush('mylist', 'nihao'):用 LPUSH 把 nihao 从左侧(头部)推入 mylist;Key 不存在时 Redis 会自动创建,结果为 ['nihao'];
  • r.lpush('mylist', 'laogao'):再次左插,列表是"头进",新元素在前,结果变为 ['laogao', 'nihao'];
  • r.lrange('mylist', 0, -1):取索引 0 到 -1(即全部元素),-1 表示最后一个元素、0 表示第一个;
  • 返回的是字节串(bytes)组成的列表 ,因为 Redis 存储的是二进制安全字符串,输出形如 [b'laogao', b'nihao']。每个字符串前的 b'...' 表示 bytes 类型,而非普通 str。

小知识:列表是"左进右出"还是"右进左出"?

  • LPUSH 从左边插入 → 新元素在头部;
  • RPUSH 从右边插入 → 新元素在尾部;
  • 索引 0 是最左边(最新 LPUSH 的元素),-1 是最右边(最早插入的元素)。

哈希操作:

bash 复制代码
r.hset('student', 'name', 'lisi')
r.hset('student', 'age', '18')
print(r.hget('student', 'name'))
print(r.hget('student', 'age'))
print(r.hgetall('student'))
  • r.hset('student', 'name', 'lisi'):在名为 student 的哈希中设置字段 name 的值为 lisi,等价于 HSET student name lisi;
  • 再设置 age 为 18。注意 Redis 中所有值都是字符串,即使看起来像数字,存储时也是字符串类型;
  • r.hget(...) 返回 bytes 类型(redis-py 默认返回字节),输出 b'lisi'、b'18';
  • r.hgetall(...) 返回一个 dict,但键和值都是 bytes 类型。

九、高可用演进路线

主从复制 → 加上自动故障转移 = 哨兵模式 → 再加上数据分片与写扩展 = Redis Cluster

1. 主从复制(Master / Slave Replication)

主从复制是 Redis 实现高可用、读写分离、数据冗余的核心机制,也是所有更高层架构的基础。它允许一个主节点(Master)将数据复制到一个或多个从节点(Slave / Replica)。

  • 目的:数据冗余 + 读写分离
  • 原理:主节点把数据变更同步给从节点,从节点保有与主节点一致的数据副本

五大特点:

特点 说明
一主多从 一个 Master 可以有多个 Slave
从节点单主 一个 Slave 只能有一个 Master
单向同步 数据流向只能由 Master → Slave
主节点读写 Master 可读可写
从节点只读 Slave 只读

故障接管的前提: 当 Master 出现故障,可以自动将一个 Slave 提升为新的 Master,因此 Slave 需要设置与 Master 相同的连接密码;并且新 Master 需要通过持久化机制完成数据恢复。

主从同步工作原理(五步):

  1. Slave 向 Master 发送 sync 命令;
  2. Master 启动后台存盘进程,同时收集所有新的修改数据命令;
  3. Master 完成存盘后,将整个数据文件传送给 Slave;
  4. Slave 接收数据文件并加载到内存,完成首次完全同步;
  5. 后续有新数据产生时,Master 持续将新命令传递给 Slave 完成增量同步。
实验环境(1 主 2 从)

准备三台配置相同的虚拟机,并关闭防火墙:

主机名 IP 地址 系统
master 192.168.108.10 CentOS 7.9
slave01 192.168.108.11 CentOS 7.9
slave02 192.168.108.12 CentOS 7.9
配置所有节点
bash 复制代码
# 所有节点执行
[root@localhost ~]# cd /usr/local/redis-6.2.14/
[root@localhost redis-6.2.14]# vim redis.conf
75 bind 0.0.0.0 -::1
配置从节点
bash 复制代码
# slave01、slave02 指向 master 的 IP 和端口
[root@localhost redis-6.2.14]# vim redis.conf
480 replicaof 192.168.108.10 6379

# 不修改配置文件,通过命令动态指定也可以
127.0.0.1:6379> REPLICAOF MASTER_IP PORT     # 新版推荐
127.0.0.1:6379> SLAVEOF MASTER_IP PORT       # 旧版写法,将被淘汰
重启所有 Redis
bash 复制代码
[root@localhost redis-6.2.14]# redis-cli shutdown
[root@localhost redis-6.2.14]# redis-server redis.conf &
验证同步状态
bash 复制代码
[root@master ~]# redis-cli
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.108.12,port=6379,state=online,offset=280,lag=0
slave1:ip=192.168.108.11,port=6379,state=online,offset=280,lag=0
master_failover_state:no-failover
master_replid:9abdc709c2e13658f9fe30908d53b7fd2ddd8e29
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:280
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:280
bash 复制代码
[root@slave01 ~]# redis-cli
127.0.0.1:6379> INFO replication
# Replication
role:slave
master_host:192.168.108.10
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_read_repl_offset:280
slave_repl_offset:280

在主节点写入数据,验证是否被同步到从节点:

bash 复制代码
# master 节点
127.0.0.1:6379> SET name laogao
OK

# slave01、slave02 查看,数据已同步过来
127.0.0.1:6379> GET name
"laogao"
解除主从关系

在从节点执行 REPLICAOF NO ONE 或 SLAVEOF NO ONE 即可取消主从复制。取消后会断开与 Master 的连接、不再存在复制关联,但不会清除 Slave 上已有的数据。

bash 复制代码
# 新版
127.0.0.1:6379> REPLICAOF NO ONE
# 旧版
127.0.0.1:6379> SLAVEOF NO ONE

2. 哨兵模式(Sentinel)

Redis Sentinel 是官方提供的高可用(HA)解决方案 ,用于在主从架构之上实现自动故障检测与故障转移。

  • 目的:在主从复制的基础上,实现自动故障转移
  • 原理:哨兵是一个独立的分布式系统,由多个 Sentinel 实例(进程)组成,用于监控 Redis 主从节点的健康状态

✅ 哨兵本身不存储数据,只负责监控与协调。

四大主要功能:

功能 说明
监控 Monitoring 持续检查 Master 与 Replica 是否正常运行
通知 Notification 被监控实例异常时,通过 API 通知管理员或其他系统
自动故障转移 Automatic Failover 主节点宕机时,自动将从节点提升为新主,并更新其他从节点的复制源
配置提供者 Configuration Provider 客户端可通过 Sentinel 获取当前主节点地址,实现动态服务发现

架构组成:

  • Master:主节点,处理写请求;
  • Replica(Slave):从节点,复制主节点数据,可处理读请求;
  • Sentinel 节点 :独立进程,通常部署奇数个(如 3 个)以避免脑裂。

故障转移流程(六步):

  1. 主观下线(SDOWN) :某个 Sentinel 发现主节点无响应(超过 down-after-milliseconds),将其标记为主观下线;
  2. 客观下线(ODOWN) :达到 quorum 配置值数量的 Sentinel 达成共识,确认主节点已宕机;
  3. 选举 Leader:Sentinel 之间通过 Raft 算法选举出一个 Leader 负责执行故障转移;
  4. 提升新主 :Leader 选择一个"最优"从节点(优先级高、复制偏移量大、运行稳定)执行 REPLICAOF NO ONE,将其转为主节点;
  5. 重配从节点:其他从节点重新指向新主节点;
  6. 通知客户端:通过发布/订阅机制通知客户端主节点已变更。

使用场景:

场景 说明
高可用缓存服务 主节点宕机时自动切换,保障业务连续性
避免人工干预 无需运维手动执行 REPLICAOF NO ONE
读写分离 + 自动容灾 结合主从复制,实现读扩展与写高可用
中小规模集群 适用于不需要分片(Sharding)的场景,大规模应选 Redis Cluster

⚠️ Sentinel 不解决数据分片问题,仅解决单主节点的高可用。

操作步骤

延续上面的实验,此时三台 Redis 处于一主二从状态,三台都要执行。

bash 复制代码
[root@master redis-6.2.14]# cp sentinel.conf sentinel.conf.bak
[root@master redis-6.2.14]# vim sentinel.conf

# 主节点 IP、端口,以及哨兵投票数量 2
# 当有 2 个及以上哨兵认为主节点不可用时,即为客观下线,触发主从故障转移
84 sentinel monitor mymaster 192.168.108.10 6379 2

# 超过该时间主节点未响应哨兵,则哨兵将其主观下线,单位毫秒
125 sentinel down-after-milliseconds mymaster 30000

启动哨兵(三台都要做):

bash 复制代码
[root@localhost redis-6.2.14]# redis-sentinel sentinel.conf &
[2] 9203

查看哨兵状态:

bash 复制代码
[root@master redis-6.2.14]# redis-cli -p 26379
127.0.0.1:26379> INFO sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.108.10:6379,slaves=2,sentinels=3

验证故障转移: 模拟故障,将 master 关机,可以看到剩下的两台 slave 开始选举新的 master 主机。

bash 复制代码
# 将 master 恢复,启动并放在后台运行
[root@master ~]# cd /usr/local/redis-6.2.14/
[root@master redis-6.2.14]# redis-server redis.conf &
[root@master redis-6.2.14]# redis-sentinel sentinel.conf &

原 master 回归后会自动以 slave 身份加入集群,跟随新主。

✅ 哨兵模式是 Redis 实现自动高可用的标准方案,适用于对可用性要求高、但无需数据分片的业务场景。超大规模集群应考虑 Redis Cluster。


3. Redis Cluster(3 主 3 从)

Redis Cluster 是 Redis 3.0+ 官方推出的分布式解决方案 ,核心是数据分片(Sharding)+ 主从复制 + 去中心化故障转移,用于解决单机 Redis 的容量、性能与单点故障瓶颈,实现水平扩展、高可用与高并发。

  • 目的:同时解决高可用、海量数据存储、高并发读写,即分布式扩展
  • 原理:通过数据分片进行存储,并通过多主多从架构实现高可用
核心概念

Redis Cluster 是无中心架构 的分布式系统,数据自动分散到多个节点,每个节点只存部分数据;节点间通过 Gossip 协议 通信,自带故障转移,无需 Sentinel。

关键角色:

角色 职责
主节点 Master 处理读写、管理哈希槽、参与故障投票,是核心节点
从节点 Replica 异步复制主节点数据,默认只读;主节点宕机时自动选举晋升
哈希槽 Hash Slot 集群固定 16384 个槽(0~16383),是数据分片的最小单位
节点 ID 每个节点的唯一标识,用于集群内识别与通信

五大核心特性:

  • 数据分片:突破单机内存限制,总容量 = 所有主节点内存之和;
  • 高可用:部分节点故障不影响整体,自动故障转移;
  • 线性扩展:加节点即可提升容量与并发;
  • 去中心化:无中心节点,避免单点瓶颈;
  • 自动路由:客户端连接任意节点,自动重定向到目标节点。
工作原理

1. 数据分片(哈希槽机制)

  • 槽位总数:16384(2¹⁴)
  • 键 → 槽映射:
bash 复制代码
HASH_SLOT = CRC16(key) mod 16384
  • 槽位分配:每个主节点负责一段连续 槽位。例如 3 主集群:0-5460、5461-10922、10923-16383。

2. 节点通信(Gossip 协议)

节点间通过集群总线 (独立端口,默认为服务端口 +10000)通信,消息类型包括:

  • PING / PONG:心跳检测、状态同步;
  • FAIL:广播节点失效;
  • UPDATE:槽位映射、集群拓扑更新。

3. 请求路由流程

  1. 客户端连接任意节点,发送命令;
  2. 节点计算 key 所属槽位;
  3. 槽位归属本节点 → 直接处理;否则 → 返回 MOVED 重定向;
  4. 智能客户端缓存槽位映射,减少重定向次数。

4. 故障转移(高可用)

  1. 故障检测 :某主节点超时无响应,多数主节点将其标记为 FAIL;
  2. 从节点选举 :该主节点的从节点发起 FAILOVER 请求;
  3. 投票晋升:主节点投票通过,从节点升级为主并接管槽位;
  4. 拓扑更新:Gossip 同步新状态,集群恢复。

5. 数据一致性

  • 异步复制:主从复制为异步,存在短暂数据不一致;
  • 最终一致性 :故障转移后数据最终一致,不保证强一致;
  • 写安全:多数主节点可达时,写操作尽量保留。
使用场景

适合:

  1. 海量数据存储(> 100 GB):电商商品库、用户画像、社交内容、IoT 设备数据------突破单机内存上限,分布式存储海量热数据;
  2. 高并发读写(QPS ≥ 5 万):秒杀、抢购、热点评论、实时排行榜------多主节点并行处理,并发能力线性提升。

不适合:

  • 强事务、多键跨槽操作(如 MSET 多个不同槽的 key);
  • 数据量小、低并发的场景(用哨兵 / 主从更简单);
  • 需要强一致性的场景(需搭配分布式事务)。
3 主 3 从实战

架构: Cluster 自 Redis 3.0 起支持,是官方自带的集群方式。其原理采用分布式思想,数据会均分到所有主节点上;当数据量过大时服务器均摊压力,各主节点存放的都是分片数据 而非全量数据。这是目前生产环境采用较多的部署方式,至少需要 6 台节点:3 主 3 从。

系统 IP 地址 主机名 角色
CentOS 7.9 192.168.108.21 redis1 Master
CentOS 7.9 192.168.108.22 redis2 Master
CentOS 7.9 192.168.108.23 redis3 Master
CentOS 7.9 192.168.108.24 redis4 Slave
CentOS 7.9 192.168.108.25 redis5 Slave
CentOS 7.9 192.168.108.26 redis6 Slave

准备 6 台已安装 Redis 的虚拟机,同时执行:关闭防火墙、修改配置文件。

bash 复制代码
# 所有主机操作
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# cd /usr/local/redis-6.2.14/
[root@localhost redis-6.2.14]# vim redis.conf

# 监听地址
75 bind 0.0.0.0 -::1

# 开启 cluster 集群
1387 cluster-enabled yes

# 启动 Redis
[root@localhost redis-6.2.14]# redis-server redis.conf &

创建集群(任意一台执行即可):

bash 复制代码
[root@redis1 redis-6.2.14]# redis-cli --cluster create 192.168.108.21:6379 192.168.108.22:6379 192.168.108.23:6379 192.168.108.24:6379 192.168.108.25:6379 192.168.108.26:6379 --cluster-replicas 1

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.108.25:6379 to 192.168.108.21:6379
Adding replica 192.168.108.26:6379 to 192.168.108.22:6379
Adding replica 192.168.108.24:6379 to 192.168.108.23:6379

M: fcbf04a3649f4e9e6b381861a94393c31eb67e67 192.168.108.21:6379 slots:[0-5460] (5461 slots) master
M: f3cb00b07a7836666bd3fd391040ff308ad35685 192.168.108.22:6379 slots:[5461-10922] (5462 slots) master
M: 90507dea1ca425cfe6ca993f8c453b2377ded5f0 192.168.108.23:6379 slots:[10923-16383] (5461 slots) master
S: 95fd02ecaf3fb34822fd56ed7ae61b05d782d892 192.168.108.24:6379 replicates 90507dea1ca425cfe6ca993f8c453b2377ded5f0
S: 18b45e542ebbf318fd9a92cfe2adcde4c255c72b 192.168.108.25:6379 replicates fcbf04a3649f4e9e6b381861a94393c31eb67e67
S: 8f5e04a03ae0984d843dab8fb9cd0cc4c4537624 192.168.108.26:6379 replicates f3cb00b07a7836666bd3fd391040ff308ad35685

Can I set the above configuration? (type 'yes' to accept): yes      # 输入 yes 确认

>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
>>> Performing Cluster Check (using node 192.168.108.21:6379)

[0-5460] 表示该节点负责槽位 0--5460,(5461 slots) 表示共 5461 个槽位。

查看集群状态:

bash 复制代码
[root@redis1 redis-6.2.14]# redis-cli
127.0.0.1:6379> CLUSTER NODES
192.168.108.21:6379@16379 myself,master - 0 1770089899000 1 connected 0-5460
192.168.108.22:6379@16379 master - 0 1770089899000 2 connected 5461-10922
192.168.108.23:6379@16379 master - 0 1770089898000 3 connected 10923-16383
192.168.108.24:6379@16379 slave 90507dea... 0 1770089900314 3 connected
192.168.108.25:6379@16379 slave fcbf04a3... 0 1770089899000 1 connected
192.168.108.26:6379@16379 slave f3cb00b0... 0 1770089897000 2 connected

127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:1134
cluster_stats_messages_pong_sent:1172
cluster_stats_messages_sent:2306
cluster_stats_messages_ping_received:1167
cluster_stats_messages_pong_received:1134
cluster_stats_messages_meet_received:5

创建数据: 数据必须写入其所属槽位对应的节点,否则会收到 MOVED 重定向提示。

bash 复制代码
# redis1:该 key 的槽位不属于本节点,返回重定向
127.0.0.1:6379> SET name gqd
(error) MOVED 5798 192.168.108.22:6379      # 提示应在 redis2 操作

# redis2:槽位归属正确,写入成功
127.0.0.1:6379> SET name 'gqd'
OK
127.0.0.1:6379> GET name
"gqd"

# redis1 上读取同样会被重定向
127.0.0.1:6379> GET name
(error) MOVED 5798 192.168.108.22:6379

如何透明地跨节点读写? 使用 redis-cli -c 开启集群模式,客户端会自动跟随重定向:

bash 复制代码
[root@redis1 redis-6.2.14]# redis-cli -c
127.0.0.1:6379> SET age 18
OK
127.0.0.1:6379> GET age
"18"

# 换一台机器,同样能取到------客户端自动跳转到归属节点
[root@redis3 redis-6.2.14]# redis-cli -c
127.0.0.1:6379> GET age
-> Redirected to slot [741] located at 192.168.108.21:6379
"18"
模拟故障:主节点宕机后会发生什么

关掉 redis1 节点,再次查看集群信息:

bash 复制代码
[root@redis1 redis-6.2.14]# init 0
bash 复制代码
# redis2 上查看节点信息
127.0.0.1:6379> CLUSTER NODES
192.168.108.21:6379@16379 master,fail - ...
192.168.108.25:6379@16379 master - 0 1770091177432 7 connected 0-5460

结果可知,集群仍保持 3 台 master,原来的 redis5 节点被选举为新的 master。

完整过程解析: 如果 Cluster 中 192.168.108.21:6379(Master 1)挂掉,而它的从节点 192.168.108.25:6379 仍然存活,整个集群会自动完成故障转移(failover),服务不中断、数据不丢失。

故障前的角色关系:

节点 IP 角色 负责槽 副本关系
192.168.108.21 Master 0 -- 5460 ← 由 .25 复制
192.168.108.25 Slave (无槽) 复制 .21

其他节点(.22 / .26、.23 / .24)正常运行。

✅ 第 1 步:故障检测(约 15 秒内)

其他 master 节点(.22 和 .23)通过 Gossip 协议发现 .21 无响应。经过 cluster-node-timeout(默认 15 秒)后,多数 master(≥ 2/3)将其标记为 FAIL(客观下线)。

⏱ 在这 15 秒内,访问槽 [0--5460] 的请求会失败或超时。

✅ 第 2 步:Slave .25 自动发起选举

.25(原 .21 的 slave)检测到 master 已 FAIL,等待一个短暂随机延迟(通常 < 1 秒),然后向其他 master 节点(.22 和 .23)请求投票。

✅ 第 3 步:获得多数票,晋升为新 Master

.22 和 .23 收到请求后验证 .25 是合法副本。因为有 2 个 master 投票(超过半数),.25 成功当选,执行:

bash 复制代码
SLAVEOF NO ONE

并接管槽 0--5460。

✅ 第 4 步:集群拓扑更新,恢复服务

所有节点收到通知并更新集群视图:.25 变为 master,槽 0--5460 的 owner 变为 .25,集群状态重新变为:

bash 复制代码
cluster_state: ok
cluster_slots_fail: 0

客户端再次写入 key(如 SET user:1001 "Alice",其槽落在 0--5460)时,会被自动重定向到 192.168.108.25:6379,操作成功。

故障前后对比:

项目 故障前 故障后(.21 挂)
Master 节点 .21、.22、.23 .25、.22、.23
Slave 节点 .25、.26、.24 .26、.24(.25 已晋升)
槽覆盖 0--16383 0--16383(完整)
集群状态 ok 短暂 fail → 恢复为 ok
数据完整性 完整 完整(无丢失)
客户端影响 --- 写入槽 0--5460 暂时失败(< 30 秒),随后自动恢复

✅ 整个过程全自动,无需人工干预。

❗ 极端情况:如果 .21 和 .25 同时挂掉?

槽 0--5460 将无人负责,集群状态变为:

bash 复制代码
cluster_state: fail
cluster_slots_fail: 5461

所有涉及这些槽的读写都会失败(返回 (error) CLUSTERDOWN The cluster is down),必须手动恢复 .21 或 .25 才能恢复服务。

这就是为什么主从节点必须部署在不同物理机 / 不同可用区!

如何验证(动手测试): 关掉 .21 后你会看到------

  • .21 状态由 fail? 变为 fail(fail? 状态停留很短暂);
  • .25 角色从 slave 变为 master,并拥有 0-5460 槽;
  • 几十秒后 CLUSTER INFO 显示 cluster_state:ok。

挂掉 redis5 的对照测试:

bash 复制代码
[root@redis2 redis-6.2.14]# redis-cli -c -h 192.168.108.22 -p 6379 CLUSTER NODES
192.168.108.23:6379@16379 master - 0 1770092343225 3 connected 10923-16383
192.168.108.25:6379@16379 master,fail - 1770092246338 1770092243211 7 connected 0-5460
192.168.108.22:6379@16379 myself,master - 0 1770092341000 2 connected 5461-10922
192.168.108.26:6379@16379 slave f3cb00b0... 0 1770092342000 2 connected
192.168.108.24:6379@16379 slave 90507dea... 0 1770092345259 3 connected
192.168.108.21:6379@16379 master,fail - 1770091143695 1770091140000 1 connected

[root@redis2 redis-6.2.14]# redis-cli -c -h 192.168.108.22 -p 6379 CLUSTER INFO
cluster_state:fail                          # 集群状态 fail
cluster_slots_assigned:16384
cluster_slots_ok:10923
cluster_slots_pfail:0
cluster_slots_fail:5461
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:2

恢复集群: 将关掉的服务器开机、启动 Redis 服务即可,集群会自动重新纳管节点并恢复 ok 状态。

结论: 3 主 3 从架构完全能容忍任意一个 master 宕机,这正是 Redis Cluster 高可用的核心价值。

场景 集群是否可用 数据是否安全 是否自动恢复
仅 .21(master)挂 ✅ 是 ✅ 是 ✅ 是(由 .25 接管)
.21 + .25 同时挂 ❌ 否 ⚠️ 槽 0--5460 不可用 ❌ 否

十、容器化部署 Redis

使用 Docker 部署 Redis 是最快捷的方式,默认 Redis 容器即可支持远程连接 ,无需额外修改 bind 与 protected-mode。

bash 复制代码
# 拉取镜像并启动,映射端口到宿主机
[root@localhost ~]# docker run -d --name redis -p 6379:6379 redis:latest

# 进入容器验证
[root@localhost ~]# docker exec -it redis redis-cli
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET name wang
OK
127.0.0.1:6379> GET name
"wang"

启动后可用 Redis Desktop Manager 直接连接宿主机 IP 与 6379 端口,在 Server 面板查看 Redis 版本、运行平台、内存占用、客户端连接数与命令统计,在 Key Statistics 面板查看各逻辑库的 Key 数量与过期情况。


十一、三种架构选型对比

维度 主从复制 哨兵模式 Redis Cluster
解决的问题 数据冗余、读写分离 自动故障转移 分片 + 高可用 + 高并发
数据分片 ❌ 全量复制 ❌ 全量复制 ✅ 16384 槽分片
写扩展 ❌ 单主 ❌ 单主 ✅ 多主并行
故障自愈 ❌ 需人工 ✅ 自动 ✅ 自动
最小节点数 2 3 Redis + 3 Sentinel 6(3 主 3 从)
一致性 异步 异步 最终一致
适用规模 小 中小 大规模
运维复杂度 低 中 高

总结

Redis 的价值远不止"快"。它以 Key-Value 模型为起点,用 String、Hash、List、Set、ZSet 五种数据结构,覆盖了缓存、计数、排行榜、对象存储、集合运算等绝大多数高频场景;再以 List 与发布订阅机制,轻量地承载起消息队列的解耦与削峰职责。而真正让 Redis 走进生产核心的,是它清晰的高可用演进路径:主从复制解决数据冗余与读写分离,哨兵模式把故障转移从人工运维中解放出来,Cluster 则用 16384 个哈希槽完成数据分片与水平扩展。三者层层递进,也各有边界------哨兵不做分片,集群只保证最终一致。选型时不必盲目追新,而应回到数据规模、并发量与一致性要求上对号入座。理解机制背后的取舍,永远比记住命令更重要。

相关推荐
mldong1 小时前
八种语言的工作流引擎,我用 6 张 UML 图画完了
后端·架构
数据库小学妹10 小时前
国产数据库怎么选?兼容、迁移、核心案例与融合架构四道关
数据库·架构·国产数据库·数据库迁移·融合数据库
霸道流氓气质10 小时前
Serverless 架构入门与实战:FaaS/BaaS 模型、Spring Cloud Function 适配与 AI 推理冷启动优化的 Java 全栈指南
spring cloud·架构·serverless
IvorySQL10 小时前
PostgreSQL 日报| PgBouncer 修复三个 CVE 漏洞(10 月 15 日)
数据库·postgresql·区块链
饺子大魔王的男人10 小时前
后台表格、查询、流程总在重复写?我用ToolJet把PostgreSQL直接做成可远程访问的业务系统
数据库·postgresql
Gauss松鼠会11 小时前
高斯数据库(openGauss)的物理存储结构
运维·服务器·数据库·sql·opengauss·经验总结
Knight_AL11 小时前
本地服务连接 SaaS 测试环境实践:Docker 部署 Redis 与 RocketMQ 完成接口联调
redis·docker·rocketmq
杨云龙UP11 小时前
PostgreSQL 18.4 数据库整库迁移实战:pg_dump 备份与 pg_restore 恢复完整操作手册
运维·服务器·数据库·postgresql·pg_dump·pg_restore