搭建 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强制使接收消息包的节点确认发送消息包的节点为可信任的。

posted @ 2023-09-26 17:06  yifanSJ  阅读(76)  评论(0编辑  收藏  举报