Redis 从基础到集群实战:数据类型、客户端、高可用架构完整梳理

Redis 数据类型、消息队列、客户端与高可用集群完整详解

基于学习文档整理,适合技术博客发布,内容包含:5 大基础数据类型、消息队列实现、多语言客户端使用、主从复制、哨兵模式、Redis Cluster 集群、Docker 容器化部署,原理 + 命令 + 实战案例 + 优缺点分析。

目录

  1. Redis 五大基础数据类型
  2. Redis 实现消息队列(生产者消费者 / 发布订阅)
  3. Redis 多种客户端使用
  4. Redis 高可用体系:主从复制
  5. Redis Sentinel 哨兵模式
  6. Redis Cluster 集群(3 主 3 从)
  7. Docker 部署 Redis(单机 + Compose 集群)

1、Redis 五大基础数据类型

Redis 是 Key‑Value 的 NoSQL 内存数据库,所有的 key 统一都是字符串类型,value 支持 5 种不同的数据结构,每种结构适配不同业务场景。

1.1 String 字符串

字符串是 Redis 最基础的数据单元,二进制安全,可以存储普通字符串、数字、图片序列化数据,单个 value 最大支持 512MB。

常用核心命令

表格

命令 作用
`set key value EX seconds[NX XX]` 设置 key‑value;EX 设置过期时间;NX 不存在才设置;XX 存在才覆盖
get key 获取 key 对应值
mset k1 v1 k2 v2 批量设置多个键值
mget k1 k2 批量获取多个 key
incr / decr key 数字自增、自减,原子操作
ttl key 查看剩余过期时间,‑1永不过期,‑2key 不存在
expire key seconds 设置 key 生存时间

业务场景:缓存、计数器、分布式锁、session 存储。

小提示:SET key value NX PX 30000 是分布式锁加锁标准写法。

1.2 List 列表

Redis 的 List 是双向链表结构,元素有序、允许重复,可以从头部 (left)、尾部 (right) 插入和弹出数据。

常用核心命令

表格

命令 作用
lpush key v1 v2 从链表头部(左边)插入数据
rpush key v1 v2 从链表尾部(右边)插入数据
lpop / rpop key 头部 / 尾部弹出元素
brpop key timeout 阻塞式弹出,没有数据就阻塞等待,timeout 为 0 代表永久阻塞
lrange key start stop 获取区间元素,0 -1获取列表全部元素
llen key 获取列表长度

业务场景:简单消息队列、日志存储、最新消息列表。

注意:BRPOP阻塞命令可以避免 while (true) 轮询带来的 CPU 空耗。

1.3 Set 集合

集合中元素无序、不能重复,原生支持多个集合的交、并、差集合运算。

常用核心命令

表格

命令 作用
sadd key m1 m2 向集合添加成员,重复元素自动忽略
smembers key 查看集合全部元素
sismember key member 判断元素是否存在集合中
sinter k1 k2 交集:同时存在于 k1、k2 的元素
sunion k1 k2 并集:k1 或者 k2 中存在的全部元素
sdiff k1 k2 差集:存在 k1 但是不在 k2 的元素
srem key m1 删除集合成员

业务场景:用户签到、好友共同好友、去重统计。

1.4 ZSet 有序集合(sorted set)

有序集合,成员 value 不可重复,score 分数可以重复,依靠 score 实现自动排序。

常用核心命令

表格

命令 作用
zadd key score member 添加元素,设置分数 score
zrange key 0 -1 [WITHSCORES] 分数从小到大升序展示;WITHSCORES 同时输出分数
zrevrange key 0 -1 [WITHSCORES] 分数从大到小降序
zrank key member 获取成员升序排名
zscore key member 获取成员对应的分数
zrem key member 删除成员

业务场景:排行榜、积分排名、热度榜单。

1.5 Hash 哈希

Hash 结构:hashkey → field‑value,非常适合存储对象,不用把对象序列化为字符串。

常用核心命令

表格

命令 作用
hset hashkey f1 v1 f2 v2 设置 hash 的字段与值
hget hashkey f1 获取单个字段值
hgetall hashkey 获取 hash 下全部 field 和 value
hmget hashkey f1 f2 批量获取多个字段
hdel hashkey f1 删除指定字段
hexists hashkey f1 判断字段是否存在

业务场景:存储用户信息、商品简要信息,部分字段更新不需要修改整个对象。

对比 String 序列化对象:Hash 可以只更新对象的某一个字段,不用全部重写。


2、Redis 实现消息队列

Redis 可以实现两类消息模型:生产者‑消费者模型 、发布‑订阅 (Pub/Sub) 模型。注意:Redis 实现的队列不是专业 MQ(RabbitMQ/Kafka),有局限性。

2.1 生产者消费者模型(List 实现)

原理:使用 List 作为队列,生产者往队列写数据,消费者读取数据。

  • 生产者:LPUSH queue msg1 msg2 消息入队
  • 消费者:BRPOP queue 0 阻塞读取消息,有消息立刻返回,没有消息阻塞等待。

流程图:生产者写入 List 队列,多个消费者抢消息,一条消息只会被一个消费者消费。

✅ 优点:阻塞读取,无空轮询,实现简单。 ❌ 缺点:

  1. 没有消息 ACK 确认机制;消费者拿到消息还没处理完宕机,消息直接丢失。
  2. 消息堆积会占用大量内存。
  3. 没有死信队列、重试等高级特性。

2.2 发布订阅 Pub / Sub

  • 发布者:PUBLISH channel msg,向指定频道发布消息
  • 订阅者:SUBSCRIBE channel,监听频道消息;PSUBSCRIBE pattern通配符订阅多个频道。

特点:同一条消息,所有订阅该频道的客户端全部收到,一对多广播。

✅ 适用场景:配置变更通知、集群消息通知、群消息推送。 ❌ 致命缺点:

  1. 消息不持久化,订阅客户端离线期间的消息直接丢失。
  2. 没有消息回溯,只能接收订阅之后产生的消息。

💡生产建议:对消息可靠性要求高,不要用 List 和 PubSub 做业务队列,优先使用专业 MQ;仅做简单通知、异步任务可以临时使用。


3、Redis 客户端访问方式

Redis 提供多种访问方式:shell 命令行、shell 脚本、GUI 图形客户端、编程语言客户端 (Python 示例)。

3.1 redis‑cli 命令行客户端

bash 复制代码
#基础连接
redis-cli
#远程带密码连接
redis-cli -h 192.168.108.172 -p 6379 -a 123456 --no-auth-warning
#集群模式连接,开启自动重定向
redis-cli -c

3.2 Shell 脚本操作 Redis

可以直接在 shell 调用redis‑cli实现批量写入数据。 示例脚本 write_redis.sh

bash 复制代码
#!/bin/bash
REDIS_HOST="127.0.0.1"
REDIS_PORT=6379
REDIS_DB=0
#循环写入100条key
for i in {0..99}; do
KEY="key:$i"
VALUE="$i"
redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -n "$REDIS_DB" SET "$KEY" "$VALUE"
done
echo "写入完成"

赋予执行权限运行

bash 复制代码
chmod +x write_redis.sh
./write_redis.sh

大批量导入数据优先使用 redis‑cli --pipe管道模式,性能更高。

3.3 GUI 图形客户端 Another‑Redis‑Desktop‑Manager

开源可视化 Redis 管理工具,支持 Windows/Mac/Linux。 使用前提:

  1. 修改 redis 配置 bind 0.0.0.0 允许外部访问
  2. 设置密码 requirepass xxx
  3. 关闭防火墙或者开放 6379 端口 可以可视化查看 key、编辑数据、查看内存、查看 info 运行状态。

3.4 Python 客户端 redis‑py

  1. 安装依赖
bash 复制代码
pip install redis
  1. 基础连接示例
bash 复制代码
import redis
#创建连接对象
r = redis.Redis(host='192.168.108.172',port=6379,password="123456",db=0)

#string操作
r.set("color1","red")
val = r.get("color1")
print(val)

#list操作
r.lpush("mylist","nihao")
print(r.lrange("mylist",0,-1))

#hash操作
r.hset("student","name","lisi")
print(r.hgetall("student"))

⚠️注意:redis‑py 默认返回 bytes 字节类型,需要 decode 转字符串。


4、Redis 高可用:主从复制 Master‑Replica (Slave)

4.1 作用

  1. 数据冗余备份:主节点数据复制到从节点,防止单节点数据丢失
  2. 读写分离:主节点处理写请求,从节点承担读请求,分担压力。

4.2 核心特性

  1. 一个 Master 可以拥有多个 Replica 从节点;一个从节点只能归属一个主节点
  2. 数据单向同步:只能主→从,从节点不会写回主节点
  3. Master 可读可写;Replica 默认只读,拒绝写操作。

4.3 复制工作原理

  1. Slave 向 Master 发送SYNC同步请求
  2. Master fork 子进程执行 BGSAVE,生成 RDB 快照文件
  3. Master 把完整 RDB 快照发送给从节点;从节点清空本地数据,加载 RDB,完成全量同步
  4. 全量同步完成后,Master 持续把后续所有写命令发送给从节点,执行增量同步,保持数据一致。

4.4 配置方式

修改从节点 redis.conf 配置文件

bash 复制代码
replicaof 192.168.108.10 6379

或者 redis‑cli 运行时动态配置(重启失效)

bash 复制代码
REPLICAOF 192.168.108.10 6379
#取消主从,把从节点独立成主节点
REPLICAOF NO ONE

4.5 查看主从状态

bash 复制代码
info replication

4.6 主从复制的痛点

❗没有自动故障转移 。当 Master 宕机,从节点不会自动升级为主节点,需要人工操作REPLICAOF NO ONE手动切换,业务会中断。 为了解决这个痛点,引入哨兵 Sentinel。


5、Redis Sentinel 哨兵模式

哨兵是独立运行的进程 ,基于主从复制实现自动故障转移高可用 ,不需要人工介入切换主节点。生产环境哨兵部署奇数个(3 个最佳),用来防止脑裂问题。

5.1 Sentinel 四大核心功能

  1. 监控 Monitoring:持续探测 Master、Slave 节点运行状态。
  2. 通知 Notification:实例故障后可以通知运维。
  3. 自动故障转移 Automatic Failover:主节点宕机,自动选举最优从节点升级为新 Master,其他从节点自动指向新主。
  4. 配置提供者:客户端连接哨兵获取当前真实 master 地址,实现服务动态发现。

注意:哨兵进程不存储业务数据,仅仅做监控和调度。

5.2 故障转移完整流程

  1. 主观下线 SDOWN:某一个哨兵探测到主节点超时无响应,单方面标记为主观下线。
  2. 客观下线 ODOWN:超过配置 quorum 数量的哨兵都判定主节点故障,达成共识,标记客观下线,确认主节点真的挂掉。
  3. 哨兵集群内部通过 Raft 算法,选举一个 Leader 哨兵,由 Leader 执行故障转移。
  4. Leader 挑选最优从节点(优先级高、复制偏移量大)执行REPLICAOF NO ONE提升为新 Master。
  5. 剩余所有从节点重新配置,复制指向新的 master。
  6. 通过发布订阅通知全部客户端主节点地址变更。

5.3 sentinel.conf 关键配置

bash 复制代码
#监控主节点,mymaster自定义名称,2代表至少2个哨兵判定故障才触发客观下线
sentinel monitor mymaster 192.168.108.10 6379 2
#判定主观下线超时时间,单位毫秒
sentinel down-after-milliseconds mymaster 30000

启动哨兵

bash 复制代码
redis-sentinel sentinel.conf &

5.4 哨兵模式局限

✅解决主节点故障自动切换,实现高可用。 ❌不支持数据分片,全部数据还是存储在一套主从,无法突破单机内存上限;适合中小规模业务;海量大数据场景选择 Redis‑Cluster 集群。


6、Redis‑Cluster 集群(3 主 3 从)

Redis3.0 之后官方提供分布式集群方案,去中心化架构,不需要哨兵,同时实现:数据分片(水平扩容)+ 主从副本 + 内置自动故障转移。

标准生产部署:3 主 3 从架构,每个主节点配套一个从节点。

6.1 核心概念:哈希槽 hash slot

Redis 集群一共固定 16384 个哈希槽,编号 0‑16383,是数据分片最小单元。

key 映射槽计算公式: HASH_SLOT = CRC16(key) mod 16384

  1. 每个主节点分配一部分连续哈希槽;
  2. 同一个 key,计算出来的槽永远固定,key 只会保存在负责该槽的主节点;
  3. 客户端访问 key,会计算 key 所属槽,访问对应主节点;不在当前节点返回 MOVED 重定向。

6.2 集群通信 Gossip 协议

集群节点之间通过独立集群总线端口(服务端口 + 10000,例如 6379 集群总线端口 16379)互相通信。 消息类型:PING/PONG 心跳检测、FAIL 节点失效广播、更新槽位拓扑信息。

6.3 故障转移机制

  1. 集群其他主节点 Gossip 探测某 master 超时无响应,多数主节点投票标记节点 FAIL 客观下线。
  2. 该故障 master 对应的从节点发起选举,获取集群主节点多数投票。
  3. 从节点晋升为新 Master,接管原主节点全部哈希槽。
  4. Gossip 协议广播新集群拓扑,整个集群更新节点状态。

⚠️极端风险:如果一个 Master 和它所有从节点同时宕机,该 master 负责的哈希槽无人接管,整个集群状态变为cluster_state:fail,整个集群读写全部报错不可用。 生产实践:主节点和它的从节点必须部署到不同服务器,避免机器断电全部挂掉。

6.4 创建 3 主 3 从集群实战

准备 6 台 Redis 实例,开启集群配置redis.conf

bash 复制代码
bind 0.0.0.0
cluster-enabled yes  #开启集群模式

执行创建集群命令,--cluster‑replicas 1代表每个主分配 1 个从节点。

bash 复制代码
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

交互输入yes确认分配槽位。

集群常用查看命令

bash 复制代码
#查看集群节点详细信息
cluster nodes
#查看集群整体状态
cluster info

客户端连接集群务必加 -c 参数,开启自动重定向,否则访问不属于本节点槽的 key 会返回 MOVED 报错。

6.5 Redis Cluster 优缺点

✅优点

  1. 数据分片,多主并行读写,突破单机内存上限,支持水平扩容;
  2. 自带主从副本,故障自动转移,不需要哨兵;
  3. 去中心化,没有单点。

❌缺点

  1. 多键跨不同哈希槽命令受限,不支持多 key 跨槽事务;
  2. 主从复制是异步复制,故障转移瞬间可能存在少量数据丢失风险;
  3. 运维复杂度高于哨兵模式。

适用场景:海量热数据存储,高并发访问,单机内存不够用的业务。


7、Docker 部署 Redis(单机 + compose 集群)

7.1 Docker 单机部署 Redis

bash 复制代码
# 启动redis容器,端口映射,挂载数据目录持久化RDB
docker run --name redis -p 6379:6379 -d -v /data/redis:/data redis
#进入容器客户端操作
docker exec -it redis redis-cli

7.2 docker‑compose 部署 3 主 3 从 Redis‑Cluster

编写docker‑compose.yml,定义 6 个容器,3 主 3 从。

重点配置:cluster‑announce‑ip,向外部宣告容器宿主机 IP,否则外部客户端无法访问集群。

bash 复制代码
version: '2.27'
networks:
  redis-cluster-net:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.109.0/24
services:
  redis-21:
    image: redis:latest
    container_name: redis-21
    restart: always
    ports:
      - "6379:6379"
      - "16379:16379"
    networks:
      redis-cluster-net:
        ipv4_address: 192.168.109.21
    volumes:
      - ./node21/data:/data
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --cluster-announce-ip 192.168.109.21
      --cluster-announce-port 6379
      --cluster-announce-bus-port 16379
      --appendonly yes
      --protected-mode no

  redis-22:
    image: redis:latest
    container_name: redis-22
    restart: always
    ports:
      - "6380:6379"
      - "16380:16379"
    networks:
      redis-cluster-net:
        ipv4_address: 192.168.109.22
    volumes:
      - ./node22/data:/data
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --cluster-announce-ip 192.168.109.22
      --cluster-announce-port 6379
      --cluster-announce-bus-port 16379
      --appendonly yes
      --protected-mode no

  redis-23:
    image: redis:latest
    container_name: redis-23
    restart: always
    ports:
      - "6381:6379"
      - "16381:16379"
    networks:
      redis-cluster-net:
        ipv4_address: 192.168.109.23
    volumes:
      - ./node23/data:/data
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --cluster-announce-ip 192.168.109.23
      --cluster-announce-port 6379
      --cluster-announce-bus-port 16379
      --appendonly yes
      --protected-mode no

  redis-25:
    image: redis:latest
    container_name: redis-25
    restart: always
    ports:
      - "6382:6379"
      - "16382:16379"
    networks:
      redis-cluster-net:
        ipv4_address: 192.168.109.25
    volumes:
      - ./node25/data:/data
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --cluster-announce-ip 192.168.109.25
      --cluster-announce-port 6379
      --cluster-announce-bus-port 16379
      --appendonly yes
      --protected-mode no

  redis-26:
    image: redis:latest
    container_name: redis-26
    restart: always
    ports:
      - "6383:6379"
      - "16383:16379"
    networks:
      redis-cluster-net:
        ipv4_address: 192.168.109.26
    volumes:
      - ./node26/data:/data
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --cluster-announce-ip 192.168.109.26
      --cluster-announce-port 6379
      --cluster-announce-bus-port 16379
      --appendonly yes
      --protected-mode no

  redis-24:
    image: redis:latest
    container_name: redis-24
    restart: always
    ports:
      - "6384:6379"
      - "16384:16379"
    networks:
      redis-cluster-net:
        ipv4_address: 192.168.109.24
    volumes:
      - ./node24/data:/data
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --cluster-announce-ip 192.168.109.24
      --cluster-announce-port 6379
      --cluster-announce-bus-port 16379
      --appendonly yes
      --protected-mode no

启动容器

bash 复制代码
docker compose up -d

进入其中一个容器,执行集群创建命令

bash 复制代码
docker exec -it redis-21 redis-cli --cluster create \
192.168.109.21:6379 \
192.168.109.22:6379 \
192.168.109.23:6379 \
192.168.109.24:6379 \
192.168.109.25:6379 \
192.168.109.26:6379 \
--cluster-replicas 1

输入yes确认分配槽,集群构建完成。


小结

  1. Redis 五大数据类型对应不同业务场景,理解结构才能选对类型。
  2. Redis 队列能力有限,仅适合简单通知;可靠性业务选择专业 MQ。
  3. 高可用演进路线:单机 → 主从复制(备份读写分离,无自动故障切换) → Sentinel 哨兵(自动故障转移,不分片) → Redis‑Cluster 集群(分片 + 高可用,海量数据)。
  4. Docker 可以快速部署单机和集群,集群模式重点注意cluster‑announce‑ip配置,否则外部客户端无法访问。
相关推荐
FfHUCisI1 小时前
pprof 火焰图(Flame Graph)阅读与热点代码重构实战
架构·golang
神一样的老师1 小时前
WS63 访问 HTTPS 握手失败(-0x7780)根治
数据库·网络协议·https
mldong2 小时前
审批详情页高亮的那个节点,"名字"其实是一串 id:jeeflow 工作流引擎的四块数据来源
后端·架构
Patrick在香港2 小时前
时间戳凭空早了 8 小时:datetime.utcnow() 弃用实测与漂移复盘
数据库·python·标准库·datetime·时区·弃用
深蓝AI2 小时前
Redis 文档 MCP 揭示 Agent 检索真相:3 个工具、双读路径,引用为什么不能交给模型编
人工智能·redis
李兆龙的博客10 小时前
问津集 #26:Lakebase——Postgres 的版本化页面存储、数据库分支与计算弹性
数据库
倔强的石头_12 小时前
聊聊金仓KFS:一款把数据同步软件做扎实的产品
数据库
闲云野鹤在人间12 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算