Redis集群搭建(传统方式&Docker方式)&集群扩容&集群缩容

11 篇文章 0 订阅
本文详细介绍了Redis集群的工作原理,包括哈希槽、节点通信和故障转移机制。接着,展示了两种安装Redis Cluster的方式:传统方式和Docker部署。集群扩容和缩容的步骤也进行了说明,包括如何添加和移除节点。最后,讲解了如何在SpringBoot应用中整合RedisCluster,并提供了相关配置示例。
摘要由CSDN通过智能技术生成

目录

一、Redis集群原理

集群间通信方式 

主节点宕机

从节点选举为主节点

二、RedisCluster安装

传统方式

Docker方式

三、集群扩容

四、集群缩容

五、SpringBoot整合Redis Cluster


一、Redis集群原理

Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

节点 A 包含 0 到 5500号哈希槽。

节点 B 包含5501 到 11000 号哈希槽。

节点 C 包含11001 到 16384号哈希槽。

注意:一个键值并不是对应一个哈希槽,一个哈希槽可以有很多键值。理论上一个集群可以存放很多很多键值。

CRC16算法

static const uint16_t crc16tab[256]= {
    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
    0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
    0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
    0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
    0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
    0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
    0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
    0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
    0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
    0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
    0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
    0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
    0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
    0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
    0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
    0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
    0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
    0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
    0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
    0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
    0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
    0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
    0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
    0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
    0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
    0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
    0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
    0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
    0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
    0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
    0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
};

uint16_t crc16(const char *buf, int len) {
    int counter;
    uint16_t crc = 0;
    for (counter = 0; counter < len; counter++)
            crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *buf++)&0x00FF];
    return crc;
}

集群间通信方式 

所有的集群节点都通过TCP连接和一个二进制协议(集群连接,cluster bus)建立通信。 每一个节点都通过集群连接(cluster bus)与集群上的其余每个节点连接起来。节点之间使用一个 gossip流言协议来传播集群的信息。

主节点宕机

节点的失效有两种状态PFAIL和FAIL,当集群中A节发送给B节点的一个活跃的 ping 包(active ping)(一个发送后要等待其回复的 ping 包)已经等待了超过 NODE_TIMEOUT 时间,那么A认为这个节点具有不可达性,标记为PFAIL,如果其他节点也把B节点标记为PFAIL状态(A节点通过gossip 字段收集到集群中大部分主节点标识的节点 B 的状态信息为PFAIL),那么A就会把B标记为FAIL,并告诉其他可达的节点,B节点FAIL了。

从节点选举为主节点

从节点的选举和提升都是由从节点处理的,主节点会投票要提升哪个从节点。一个从节点的选举是在主节点被至少一个具有成为主节点必备条件的从节点标记为 FAIL 的状态的时候发生的。

当以下条件满足时,一个从节点可以发起选举:

  • 该从节点的主节点处于 FAIL 状态。
  • 这个主节点负责的哈希槽数目不为零。
  • 从节点和主节点之间的重复连接(replication link)断线不超过一段给定的时间,这是为了确保从节点的数据是可靠的。
  • 一个从节点想要被推选出来,那么第一步应该是提高它的 currentEpoch(可以理解为事件版本号) 计数,并且向主节点们请求投票。

从节点通过广播一个 FAILOVER_AUTH_REQUEST 数据包给集群里的每个主节点来请求选票。然后等待回复(最多等 NODE_TIMEOUT 这么长时间)。一旦一个主节点给这个从节点投票,会回复一个 FAILOVER_AUTH_ACK,并且在 NODE_TIMEOUT * 2 这段时间内不能再给同个主节点的其他从节点投票。

一旦某个从节点收到了大多数主节点的回应,那么它就赢得了选举。否则,如果无法在 NODE_TIMEOUT 时间内访问到大多数主节点,那么当前选举会被中断并在 NODE_TIMEOUT * 4 这段时间后由另一个从节点尝试发起选举。

从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一点点延迟。

主节点接收到来自于从节点、要求以 FAILOVER_AUTH_REQUEST 请求的形式投票的请求。 要授予一个投票,必须要满足以下条件:

  • 在一个给定的时段(epoch)里,一个主节点只能投一次票,并且拒绝给以前时段投票:每个主节点都有一个 lastVoteEpoch 域,一旦认证请求数据包(auth request packet)里的 currentEpoch 小于 lastVoteEpoch,那么主节点就会拒绝再次投票。当一个主节点积极响应一个投票请求,那么 lastVoteEpoch 会相应地进行更新。
  • 一个主节点投票给某个从节点当且仅当该从节点的主节点被标记为 FAIL。
  •  如果认证请求里的 currentEpoch 小于主节点里的 currentEpoch 的话,那么该请求会被忽视掉。因此,主节点的回应总是带着和认证请求一致的 currentEpoch。如果同一个从节点在增加 currentEpoch 后再次请求投票,那么保证一个来自于主节点的、旧的延迟回复不会被新一轮选举接受。

二、RedisCluster安装

传统方式

1、创建文件

[root@localhost local]# mkdir redis-cluster
[root@localhost redis-cluster]# mkdir 7000
[root@localhost redis-cluster]# mkdir 7001
[root@localhost redis-cluster]# mkdir 7002
[root@localhost redis-cluster]# mkdir 7003
[root@localhost redis-cluster]# mkdir 7004
[root@localhost redis-cluster]# mkdir 7005
#降配置文件复制到相应的目录下
[root@localhost redis-cluster]# cp /usr/local/redis-6.2.4/redis.conf /usr/local/redis-cluster/7000/ -r
[root@localhost redis-cluster]# cp /usr/local/redis-6.2.4/redis.conf /usr/local/redis-cluster/7001/ -r
[root@localhost redis-cluster]# cp /usr/local/redis-6.2.4/redis.conf /usr/local/redis-cluster/7002/ -r
[root@localhost redis-cluster]# cp /usr/local/redis-6.2.4/redis.conf /usr/local/redis-cluster/7003/ -r
[root@localhost redis-cluster]# cp /usr/local/redis-6.2.4/redis.conf /usr/local/redis-cluster/7004/ -r
[root@localhost redis-cluster]# cp /usr/local/redis-6.2.4/redis.conf /usr/local/redis-cluster/7005/ -r

2、修改配置文件

#注释掉
bind 127.0.0.1 -::1
#后台启动
daemonize yes 
# 允许外部访问
protected-mode no 
#修改端口号,从7000到7005
port 7000
#指定启动的pid文件 7000-7005
pidfile /var/run/redis_7000.pid
#日志路径 引号不要丢 7000-7005
logfile  "usr/local/redis-cluster/7000/redis.log"
#修改rdb文件,为后面的扩容使用,因为是同一台虚拟机,不在同一个虚拟机可以不用改 7000-7005
dbfilename dump_7000.rdb
#修改密码
requirepass xiaojie
#集群的密码,不然节点切换的时候需要输入密码
masterauth xiaojie
#开启集群
cluster-enabled yes 
#自动生成文件 7000-7005
cluster-config-file nodes-7000.conf

3、启动集群

启动脚本 授权 chmod +x startall.sh 

/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7000/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7001/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7002/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7003/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7004/redis.conf
/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7005/redis.conf

4、创建集群

#无密码 cluster-replicas 1 主从节点1:1分配
./redis-cli --cluster create  192.168.139.154:7000  192.168.139.154:7001  192.168.139.154:7002  192.168.139.154:7003  192.168.139.154:7004  192.168.139.154:7005  --cluster-replicas 1

#有密码
./redis-cli --cluster create  192.168.139.154:7000  192.168.139.154:7001  192.168.139.154:7002  192.168.139.154:7003  192.168.139.154:7004  192.168.139.154:7005  --cluster-replicas 1 -a xiaojie

 输入yes接收卡槽分配。

 看到这个图说明 集群安装成功了。

cluster nodes 指令查看集群节点

测试

 [root@localhost bin]# ./redis-cli -p 7000 -c -a 'xiaojie'

 OK搭建完成。

Docker方式

1、拉取镜像

[root@localhost bin]# docker pull redis

2、创建文件

[root@localhost local]# mkdir docker-redis-cluster 

 3、创建redis-cluster.tmpl文件


#端口
port ${PORT}
#集群密码
masterauth xiaojie
#redis密码
requirepass xiaojie
#开启集群
cluster-enabled yes
#配置文件
cluster-config-file nodes.conf

cluster-node-timeout 5000
#集群通讯的ip如果在外网访问,需要填写服务器的公网ip
cluster-announce-ip 192.168.6.137
##集群节点的汇报port,防止nat
cluster-announce-port ${PORT}
#集群节点的汇报bus-port,防止nat
cluster-announce-bus-port 1${PORT}
#开启aof
appendonly yes

4、创建data和conf文件


[root@localhost docker-redis-cluster]# for port in `seq 9000 9005`; do mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data; done

 5、创建Redis容器

[root@localhost docker-redis-cluster]# for port in `seq 9000 9005`; do docker run -d --net=host -v /usr/local/docker-redis-cluster/${port}/conf/redis.conf:/etc/redis/redis.conf -v /usr/local/docker-redis-cluster/${port}/data:/data --restart always --name=redis-${port}  redis redis-server /etc/redis/redis.conf; done

6、进入任一容器创建集群

#进入容器
[root@localhost docker-redis-cluster]# docker exec -it 9e36f2ab4ae7 bash
#创建集群
root@localhost:/data# redis-cli --cluster create  192.168.6.137:9000  192.168.6.137:9001  192.168.6.137:9002  192.168.6.137:9003  192.168.6.137:9004  192.168.6.137:9005  --cluster-replicas 1 -a xiaojie

7、测试

root@localhost:/data# redis-cli -p 9000 -c -a 'xiaojie'  
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.6.137:9002> set docker docker 
-> Redirected to slot [9730] located at 192.168.6.137:9001
OK
192.168.6.137:9001> get docker
"docker"
192.168.6.137:9001> 

三、集群扩容

集群扩容就是在原来的基础上新增集群节点,而不需要重新启动服务器。简单明白的说,就是新增一个服务器,然后从其他节点上分给它一些卡槽和数据(如果卡槽上有数据则连带数据一起分给新增的节点)。

添加两个配置文件,在下面源码地址上有

新增主节点

#启动新增的连个节点
[root@localhost bin]# ./redis-server /usr/local/redis-cluster/7006/redis.conf 
[root@localhost bin]# ./redis-server /usr/local/redis-cluster/7007/redis.conf
#新增主节点
[root@localhost bin]# /usr/local/redis/bin/redis-cli --cluster add-node 192.168.139.154:7006   192.168.139.154:7000 -a xiaojie  #没有密码则不用-a xiaojie

 

 可以看到新增的节点是没有卡槽的。

下面我们为新增的主节点分配从节点

[root@localhost bin]# ./redis-cli --cluster add-node   192.168.139.154:7007  192.168.139.154:7000  --cluster-slave   --cluster-master-id  9493cb0e7ee7b35da0c9078e9a99e5b577de9f1a -a xiaojie 
#master-id 为7006节点对应的id可以看到我们为7006新增从节点

 输入cluster nodes 检查集群状态,如上图,还没有分配卡槽

下面分配卡槽

#这个客户端可以连接任何一个节点,不限于7000
[root@localhost bin]# ./redis-cli --cluster reshard  192.168.139.154:7000 -a xiaojie

 你想移动多少卡槽? 16384/4=4096 所以我们想要移动4096个卡槽到7006节点上,然后就会从其他的三个主节(从节点上是没有卡槽的)点上分给7006。所以输入4096

 输入对应的id,这里我们选择all 再接着选择yes等待分配完卡槽就好啦。

右上图可见,已经给我们分配完卡槽了。 

四、集群缩容

集群缩容,正好和扩容相反,就是在不重启服务器的情况 下移除服务节点。

 我们选择将7006卡槽全部给7001,注意:移除节点时,一定要确保,所有的卡槽已经移除到别的主节点上。

[root@localhost bin]# ./redis-cli --cluster  reshard  192.168.139.154:7000  --cluster-from   9493cb0e7ee7b35da0c9078e9a99e5b577de9f1a -a xiaojie  --cluster-to d5ac3163a51a0b7e70e777d8ff137a4ba901d611  --cluster-slots -a xiaojie

五、SpringBoot整合Redis Cluster

spring:
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  datasource:
    name: my-test
    url: jdbc:mysql://127.0.0.1:3306/my_test?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
  redis:
    cluster:
      nodes: #我连接的是Docker安装的集群
      - 192.168.6.137:9000
      - 192.168.6.137:9001
      - 192.168.6.137:9002
      - 192.168.6.137:9003
      - 192.168.6.137:9004
      - 192.168.6.137:9005
    password: xiaojie
    connect-timeout: 5000
#    password: xiaojie #这个密码一定要加,然后才能保证能连接到redis服务器,如果没有配置密码则不需要
#    connect-timeout: 5000
#    database: 0
#    sentinel:
#      master: mymaster
#      nodes: 192.168.6.137:26379,192.168.6.137:26380,192.168.6.137:26381
#      password: xiaojie #这个密码是哨兵的密码,如果在sentinel.conf中没有配置requirepass则不需要

完整代码和集群配置文件:spring-boot: Springboot整合redis、消息中间件等相关代码 

参考:

REDIS cluster-spec -- Redis中文资料站 -- Redis中国用户组(CRUG)

docker部署redis集群 - 桥头堡洗脚城 - 博客园

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熟透的蜗牛

永远满怀热爱,永远热泪盈眶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值