笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 设计模式

  • JVM 详解

  • Linux

  • Redis

    • Redis 入门

    • Redis 进阶

      • Redis 事务—锁机制
      • Redis 事务—秒杀案例
      • Redis 持久化—RDB
      • Redis 持久化—AOF
      • Redis 主从复制
      • Redis 集群
        • 问题
        • 什么是集群
        • 安装
        • 安装(Docker)
          • 创建目录及文件
          • 编写配置文件
          • 启动
          • 创建 Redis Cluster 集群
          • 查看集群状态
          • 查看集群信息和节点信息
        • 登录
          • 普通方式登录
          • 集群策略登录
          • 通过 cluster nodes 命令查看集群信息
        • 如何分配这六个节点
        • 什么是 slots
        • 在集群中录入值
          • 批量操作
        • 查询集群中的值
        • 故障恢复
        • 集群的 Jedis 开发
        • Redis 集群提供了以下好处
        • Redis 集群的不足
      • Redis 应用问题解决
      • Redis6 新功能
  • 分布式锁

  • Shiro

  • Gradle

  • Java 进阶
  • Redis
  • Redis 进阶
EasT-Duan
2024-08-10
目录

Redis 集群

欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

# 问题

容量不够,redis 如何进行扩容?

并发写操作, redis 如何分摊?

另外,主从模式,薪火相传模式,主机宕机,导致 ip 地址发生变化,应用程序中配置需要修改对应的主机地址、端口等信息。

之前通过代理主机来解决,但是 redis3.0 中提供了解决方案。就是无中心化集群配置。

# 什么是集群

Redis 集群实现了对 Redis 的水平扩容,即启动 N 个 redis 节点,将整个数据库分布存储在这 N 个节点中,每个节点存储总数据的 1/N。

Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。

# 安装

  • 制作 6 个实例,6379,6380,6381,6382,6383,6384

    • 配置基本信息

    • #开启daemonize yes
      #Pid文件名字
      #指定端口
      #Log文件名字
      #Dump.rdb名字
      #Appendonly 关掉或者换名字
      #cluster-enabled yes    打开集群模式
      #cluster-config-file nodes-6379.conf  设定节点配置文件名
      #cluster-node-timeout 15000   设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换。
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
    • include /root/myredis/redis.conf
      port 6379
      pidfile "/var/run/redis_6379.pid"
      dbfilename "dump6379.rdb"
      dir "/root/redis-cluster"
      logfile "/root/redis-cluster/redis_err_6379.log"
      cluster-enabled yes
      cluster-config-file nodes-6379.conf
      cluster-node-timeout 15000
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
  • 复制五份

    • 使用:% s/6379/638x 替换 5 个文件配置
  • 启动服务

    • redis-server ~/redis-cluster/redis6379.conf
    • ....
  • 将六个节点合成一个集群

    • 组合之前,请确保所有 redis 实例启动后,nodes-xxxx.conf 文件都生成正常。

  • 启动集群

    • cd  /opt/redis-6.2.1/src
      
      redis-cli --cluster create --cluster-replicas 1 192.168.25.100:6379 192.168.25.100:6380 192.168.25.100:6381 192.168.25.100:6382 192.168.25.100:6383 192.168.25.100:6384
      
      1
      2
      3
    • 此处不要用 127.0.0.1,请用真实 IP 地址,--replicas 1 采用最简单的方式配置集群,一台主机,一台从机,正好三组。

    • 注意:上面的命令只在第一次创建集群时使用,如果想要删除原来的数据重新创建的话,需要删除~/redis-cluster 文件夹中的其他文件,仅仅保留.conf 文件。

# 安装(Docker)

# 创建目录及文件

分别在 192.168.25.99 和 192.168.25.100 两台机器上执行以下操作。

# 创建目录
mkdir -p /usr/local/docker/redis-cluster
# 切换至指定目录
cd /usr/local/docker/redis-cluster
# 编写 redis-cluster.tmpl 文件
vi redis-cluster.tmpl
1
2
3
4
5
6

# 编写配置文件

192.168.25.99 机器的 redis-cluster.tmpl 文件内容如下:

port ${PORT}
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.99
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
1
2
3
4
5
6
7
8
9
10
11
12

192.168.25.100 机器的 redis-cluster.tmpl 文件内容如下:

port ${PORT}
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.100
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
1
2
3
4
5
6
7
8
9
10
11
12
  • port :节点端口;
  • requirepass :添加访问认证;
  • masterauth :如果主节点开启了访问认证,从节点访问主节点需要认证;
  • protected-mode :保护模式,默认值 yes,即开启。开启保护模式以后,需配置 bind ip 或者设置访问密码;关闭保护模式,外部网络可以直接访问;
  • daemonize :是否以守护线程的方式启动(后台启动),默认 no;
  • appendonly :是否开启 AOF 持久化模式,默认 no;
  • cluster-enabled :是否开启集群模式,默认 no;
  • cluster-config-file :集群节点信息文件;
  • cluster-node-timeout :集群节点连接超时时间;
  • cluster-announce-ip :集群节点 IP,填写宿主机的 IP;
  • cluster-announce-port :集群节点映射端口;
  • cluster-announce-bus-port :集群节点总线端口。

每个 Redis 集群节点都需要打开两个 TCP 连接。一个用于为客户端提供服务的正常 Redis TCP 端口,例如 6379。还有一个基于 6379 端口加 10000 的端口,比如 16379。

​ 第二个端口用于集群总线,这是一个使用二进制协议的节点到节点通信通道。节点使用集群总线进行故障检测、配置更新、故障转移授权等等。客户端永远不要尝试与集群总线端口通信,与正常的 Redis 命令端口通信即可,但是请确保防火墙中的这两个端口都已经打开,否则 Redis 集群节点将无法通信。

在 192.168.25.99 机器的 redis-cluster 目录下执行以下命令:

for port in `seq 6371 6373`; do \
  mkdir -p ${port}/conf \
  && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \
  && mkdir -p ${port}/data;\
done
1
2
3
4
5

在 192.168.25.100 机器的 redis-cluster 目录下执行以下命令:

for port in `seq 6374 6376`; do \
  mkdir -p ${port}/conf \
  && PORT=${port} envsubst < redis-cluster.tmpl > ${port}/conf/redis.conf \
  && mkdir -p ${port}/data;\
done
1
2
3
4
5

192.168.25.99 目录结构:

192.168.25.100 目录结构:

============================== 192.168.25.99 ==============================
port 6371
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.99
cluster-announce-port 6371
cluster-announce-bus-port 16371

port 6372
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.99
cluster-announce-port 6372
cluster-announce-bus-port 16372

port 6373
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.99
cluster-announce-port 6373
cluster-announce-bus-port 16373
============================== 192.168.25.99 ==============================
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
============================== 192.168.25.100 ==============================
port 6374
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.100
cluster-announce-port 6374
cluster-announce-bus-port 16374

port 6375
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.100
cluster-announce-port 6375
cluster-announce-bus-port 16375

port 6376
requirepass 111111
masterauth 111111
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip 192.168.25.100
cluster-announce-port 6376
cluster-announce-bus-port 16376
============================== 192.168.25.100 ==============================
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

在 192.168.25.99 机器的 /usr/local/docker/redis-cluster 目录下创建 docker-compose.yml 文件并编辑。

# 描述 Compose 文件的版本信息
version: "3.8"

# 定义服务,可以多个
services:
  redis-6371: # 服务名称
    image: redis:6.2.5 # 创建容器时所需的镜像
    container_name: redis-6371 # 容器名称
    restart: always # 容器总是重新启动
    network_mode: "host" # host 网络模式
    volumes: # 数据卷,目录挂载
      - ./6371/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./6371/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf # 覆盖容器启动后默认执行的命令

  redis-6372:
    image: redis:6.2.5
    container_name: redis-6372
    restart: always
    network_mode: "host"
    volumes:
      - ./6372/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./6372/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf

  redis-6373:
    image: redis:6.2.5
    container_name: redis-6373
    restart: always
    network_mode: "host"
    volumes:
      - ./6373/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./6373/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

在 192.168.25.100 机器的 /usr/local/docker/redis-cluster 目录下创建 docker-compose.yml 文件并编辑。

# 描述 Compose 文件的版本信息
version: "3.8"

# 定义服务,可以多个
services:
  redis-6374: # 服务名称
    image: redis:6.2.5 # 创建容器时所需的镜像
    container_name: redis-6374 # 容器名称
    restart: always # 容器总是重新启动
    network_mode: "host" # host 网络模式
    volumes: # 数据卷,目录挂载
      - ./6374/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./6374/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf # 覆盖容器启动后默认执行的命令

  redis-6375:
    image: redis:6.2.5
    container_name: redis-6375
    restart: always
    network_mode: "host"
    volumes:
      - ./6375/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./6375/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf

  redis-6376:
    image: redis:6.2.5
    container_name: redis-6376
    restart: always
    network_mode: "host"
    volumes:
      - ./6376/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - ./6376/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 启动

执行 docker-compose up -d ,启动两台服务器。

# 创建 Redis Cluster 集群

# 进入容器
docker exec -it redis-6371 bash
# 切换至指定目录
cd /usr/local/bin/
1
2
3
4
redis-cli -a 111111 --cluster create 192.168.25.99:6371 192.168.25.99:6372 192.168.25.99:6373 192.168.25.100:6374 192.168.25.100:6375 192.168.25.100:6376 --cluster-replicas 1
1

# 查看集群状态

# 进入容器
docker exec -it redis-6371 bash
# 切换至指定目录
cd /usr/local/bin/
redis-cli -a 111111 --cluster check 192.168.25.100:6375
1
2
3
4
5

# 查看集群信息和节点信息

# 连接至集群某个节点
redis-cli -c -a 111111 -h 192.168.25.100 -p 6376
# 查看集群信息
cluster info
# 查看集群结点信息
cluster nodes
1
2
3
4
5
6

# 登录

# 普通方式登录

可能直接进入读主机,存储数据时,会出现 MOVED 重定向操作。所以,应该以集群方式登录。

# 集群策略登录

# 通过 cluster nodes 命令查看集群信息

# 如何分配这六个节点

一个集群至少要有三个主节点。

选项 --cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

分配原则尽量保证每个主数据库运行在不同的 IP 地址,每个从库和主库不在一个 IP 地址上。

# 什么是 slots

一个 Redis 集群包含 16384 个插槽(hash slot), 数据库中的每个键都属于这 16384 个插槽的其中一个,

集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16 (key) 语句用于计算键 key 的 CRC16 校验和 。

集群中的每个节点负责处理一部分插槽。 举个例子, 如果一个集群可以有主节点, 其中:

节点 A 负责处理 0 号至 5460 号插槽。

节点 B 负责处理 5461 号至 10922 号插槽。

节点 C 负责处理 10923 号至 16383 号插槽。

# 在集群中录入值

在 redis-cli 每次录入、查询键值,redis 都会计算出该 key 应该送往的插槽,如果不是该客户端对应服务器的插槽,redis 会报错,并告知应前往的 redis 实例地址和端口。

redis-cli 客户端提供了 –c 参数实现自动重定向。

如 redis-cli -c –p 6379 登入后,再录入、查询键值对可以自动重定向。

# 批量操作

不在一个 slot 下的键值,是不能使用 mget,mset 等多键操作。

可以通过 {} 来定义组的概念,从而使 key 中 {} 内相同内容的键值对放到一个 slot 中去。

# 查询集群中的值

CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。

# 故障恢复

如果主节点下线?从节点能否自动升为主节点?注意:15 秒超时。

主节点恢复后,主从关系会如何?主节点回来变成从机。

如果所有某一段插槽的主从节点都宕掉,redis 服务是否还能继续?

  • 如果某一段插槽的主从都挂掉
    • redis.conf 中的参数 cluster-require-full-coverage 为 yes,整个集群都挂掉
    • redis.conf 中的参数 cluster-require-full-coverage 为 no,该插槽数据全都不能使用,也无法存储。

# 集群的 Jedis 开发

即使连接的不是主机,集群会自动切换主机存储。主机写,从机读。

无中心化主从集群。无论从哪台主机写的数据,其他主机上都能读到数据。

public class JedisClusterTest {
    public static void main(String[] args) {
        Set<HostAndPort> set = new HashSet<HostAndPort>();
        set.add(new HostAndPort("192.168.25.100", 6379));
        JedisCluster jedisCluster = new JedisCluster(set);
        jedisCluster.set("k1", "v1");
        System.out.println(jedisCluster.get("k1"));
    }
}
1
2
3
4
5
6
7
8
9

# Redis 集群提供了以下好处

  • 实现扩容
  • 分摊压力
  • 无中心配置相对简单

# Redis 集群的不足

  • 多键操作是不被支持的
  • 多键的 Redis 事务是不被支持的。lua 脚本不被支持
  • 由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至 redis cluster,需要整体迁移而不是逐步过渡,复杂度较大
#Redis
上次更新: 2025/04/12, 05:37:39
Redis 主从复制
Redis 应用问题解决

← Redis 主从复制 Redis 应用问题解决→

最近更新
01
Reactor 核心
02-24
02
前置条件
10-30
03
计算机网络
09-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式