搭建 Redis5.0 单节点 及 集群模式 教程
一、单机版本
1、docker-compose
version: '3'
services:
redis:
image: redis:5.0
restart: always
privileged: true
container_name: redis-java
ports:
- 6379:6379
volumes:
- /var/docker/server/redis/redis.conf:/etc/redis/redis.conf
- /var/docker/server/redis/data:/data
command:
redis-server /etc/redis/redis.conf
networks:
weiji-net:
aliases:
- redis-java
2、配置文件
将redis.conf,放入/var/docker/server/redis/redis.conf
Redis集群redis.conf配置文件以下几点要改:
bind 0.0.0.0 # 环路IP
port:6379 # 端口
dir /data # 数据库备份文件存放目录
appendonly yes # 持久化(集群必须开启AOF)
#logfile /var/log/redis/redis-server.log # 日志(未成功)
requirepass TestPWD # 设置master连接密码,slave可省略
protected-mode no # 关闭保护模式(默认redis需要设置管理员账号密码,开启了保护模式)
daemonize no # 是否后台执行,设置为no
3、启动
docker-compose up -d --build
二、集群版本
1、redis集群架构图

在这个图中,每一个蓝色的圈都代表着一个redis的服务器节点。它们任何两个节点之间都是相互连通的。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点。对其进行存取和其他操作。
2. redis是怎么做到的呢?
首先,在redis的每一个节点上,都有这么两个东西
- 一个是插槽(slot)可以理解为是一个可以存储两个数值的一个变量,这个变量的取值范围是:0-16383。
- 一个就是redis-cluster我个人把这个redis-cluster理解为是一个集群管理的插件。
当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
3. 架构细节
- 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
- 节点的fail是通过集群中超过半数的节点检测失效时才生效.
- 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
- redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
4. 选举

1)领导者选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
2)什么时候整个集群不可用(cluster_state:fail),当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
a)节点的fail
节点的fail是通过集群中超过半数的节点检测失效时才生效,这里会触发选举,将slave升级为master
b)集群的fail
如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.
如果进群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
5. 如何理解Redis集群的Slot映射
Redis在单机模式时,使用数据结构dict来实现数据库。
Redis在集群模式时,也是使用数据结构dict来实现数据库,但是集群模式对于数据库有其他需求,包括数据的节点无关性、内部操作对客户端需要屏蔽、冗余备份等,并且在一定的情况,数据还需要在不同的节点间实现迁移。
在所有模式下,Redis的节点数据的备份都是使用备份来实现的。这个暂时不深入。
Redis引入的slot来解决如何实现集群模式下部分需求的问题。
事实下,节点并不是存储在slot里面,slot只是用于管理数据与节点相联的手段而已。在处理相关逻辑问题时,redis使用slot作为索引来管理数据下的所有数据。
6. 流程举例
集群模式下,使用redis-cli连接服务器节点A(指派了slot[2000-3000])并issue如下指令set name derekzhuo。
-node A计算name的slot为1000,发现slot 1000不在本节点上,向redis-cli返回该slot的节点信息;
-redis-cli连接新的node,并且重新issue该指令。
以上流程就是cluster模式下如何处理一个键的流程,也可以很清楚地看出slot的作用其实就是用于做key索引而已。
7、docker-compose 搭建redis集群
我们来搭建一个3主3从的redis集群
7.1 建目录
mkdir /var/docker/server/redis-cluster
cd redis-cluster
mkdir -p 6301 6302 6303 6304 6305 6306
7.2 然后每个目录下放一个redis.conf,并进行如下修改
# bind 0.0.0.0 # 注释掉
port:6301 # 端口
dir /data # 数据库备份文件存放目录
appendonly yes # 持久化(集群必须开启AOF)
#logfile /var/log/redis/redis-server.log # 日志(未成功)
requirepass TestPWD # 设置master连接密码,slave可省略
protected-mode no # 关闭保护模式(默认redis需要设置管理员账号密码,开启了保护模式)
daemonize no # 是否后台执行,设置为no
masterauth 123456 # slave连接master密码,master可省略
cluster-enabled yes # 开启集群模式
cluster-config-file nodes.conf # 集群配置信息存放文件名
cluster-node-timeout 15000 # 节点离线超时时间,到达此值时发起某个主从重新选举master
cluster-require-full-coverage no # 当一个主从整体挂掉的时集群也可以用,0-16383个槽位中,落在该某个主从对应的slots上面的key是用不了的,但是如果key落在其他的范围是仍然可用的(谨慎使用)
cluster-announce-ip 192.168.52.10
cluster-announce-port 6301
cluster-announce-bus-port 16301
# bind 0.0.0.0 # 注释掉
port:6302 # 端口
dir /data # 数据库备份文件存放目录
appendonly yes # 持久化(集群必须开启AOF)
#logfile /var/log/redis/redis-server.log # 日志(未成功)
requirepass TestPWD # 设置master连接密码,slave可省略
protected-mode no # 关闭保护模式(默认redis需要设置管理员账号密码,开启了保护模式)
daemonize no # 是否后台执行,设置为no
masterauth 123456 # slave连接master密码,master可省略
cluster-enabled yes # 开启集群模式
cluster-config-file nodes.conf # 集群配置信息存放文件名
cluster-node-timeout 15000 # 节点离线超时时间,到达此值时发起某个主从重新选举master
cluster-require-full-coverage no # 当一个主从整体挂掉的时集群也可以用,0-16383个槽位中,落在该某个主从对应的slots上面的key是用不了的,但是如果key落在其他的范围是仍然可用的(谨慎使用)
cluster-announce-ip 192.168.52.10
cluster-announce-port 6302
cluster-announce-bus-port 16302
省略6303/6304/6305/6306
7.3 docker-compose.yml
version: '3'
services:
redis-cluster:
image: redis:5.0
command: redis-cli -a TestPWD --cluster create 192.168.52.10:6301 192.168.52.10:6302 192.168.52.10:6303 192.168.52.10:6304 192.168.52.10:6305 192.168.52.10:6306 --cluster-replicas 1 --cluster-yes
depends_on:
- redis-6301
- redis-6302
- redis-6303
- redis-6304
- redis-6305
- redis-6306
redis-6301:
image: redis:5.0
container_name: redis-6301
ports:
- 6301:6301
- 16301:16301
volumes:
- ./etc_rc.local:/etc/rc.local
- ./redis-cluster/6301/redis.conf:/etc/redis/redis.conf
- ./redis-cluster/6301/data:/data
command: redis-server /etc/redis/redis.conf
redis-6302:
image: redis:5.0
container_name: redis-6302
ports:
- 6302:6302
- 16302:16302
volumes:
- ./etc_rc.local:/etc/rc.local
- ./redis-cluster/6302/redis.conf:/etc/redis/redis.conf
- ./redis-cluster/6302/data:/data
command: redis-server /etc/redis/redis.conf
....
省略6303/6304/6305/6306
networks:
weiji-net:
external: true
name: app_net
7.4 构建
docker-compose up -d
7.5 验证集群是否运行
随意进任何一个节点
docker exec -it dd5608d2cb36 /bin/bash
redis-cli -p 6381
auth TestPWD
cluster info

- cluster_state:表示集群的状态,这里显示为 "ok",表示集群正常运行。
- cluster_slots_assigned:表示集群中已分配的槽的数量,这里显示为 16384,这是 Redis 集群的默认槽位数量。
- cluster_slots_ok:表示正常工作的槽的数量,这里显示为 16384,表示所有槽都正常。
- cluster_slots_pfail:表示部分故障的槽的数量,这里显示为 0,表示没有槽是部分故障的。
- cluster_slots_fail:表示完全故障的槽的数量,这里显示为 0,表示没有槽是完全故障的。
- cluster_known_nodes:表示集群中已知的节点数量,这里显示为 6,表示集群中有 6 个节点。
- cluster_size:表示集群的大小,这里显示为 3,表示集群中有 3 个节点是主节点。
- cluster_current_epoch:表示集群的当前纪元(epoch),这里显示为 6。
- cluster_my_epoch:表示当前节点的纪元,这里显示为 2,表示该节点位于纪元 2。
- cluster_stats_messages_ping_sent:表示发送的 ping 消息数量,这里显示为 155。
- cluster_stats_messages_pong_sent:表示发送的 pong 消息数量,这里显示为 174。
- cluster_stats_messages_meet_sent:表示发送的 meet 消息数量,这里显示为 1。
- cluster_stats_messages_sent:表示总共发送的消息数量,这里显示为 330。
- cluster_stats_messages_ping_received:表示接收的 ping 消息数量,这里显示为 174。
- cluster_stats_messages_pong_received:表示接收的 pong 消息数量,这里显示为 156。
- cluster_stats_messages_received:表示总共接收的消息数量,这里显示为 330。
注意:Redis Cluster 每个节点只有一个数据库(即 db0),这是 Redis Cluster 的默认设置。

7.6 将一个新的节点加入 Redis 集群
CLUSTER MEET ip port
实现细节:MEET 和 PING 包
当一个给定的节点接收到一个CLUSTER MEET消息时,命令中指定的节点仍然不知道我们发送了命令,所以为了使节点强制将接收命令的节点将它作为信任的节点接受它,它会发送MEET包而不是PING包。两个消息包有相同的格式,但是MEET强制使接收消息包的节点确认发送消息包的节点为可信任的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了