Redis之RedisCluster集群

Redis之Redis Cluster的使用

一、Redis Cluster 简介

Redis Sentinel 水平扩容一直都是一个痛点,因为水平扩容牵涉到数据的迁移。迁移过程一方面要保证自己的业务是可用的,一方面要保证尽量不丢失数据所以数据能不迁移就尽量不迁移。针对这个问题,Redis Cluster就应运而生了。

Redis Cluster 是 Redis 的分布式解决方案,在3.0版本正式推出,有效地解决了 Redis 分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用 Cluster 架构方案达到负载均衡的目的。

二、Redis Cluster 和哨兵集群的比较

哨兵集群:本质上还是一个主从模式下的集群方案,增加一个选举机制,当主节点宕机之后会从所有节点中选出新的主节点,选举机制的实现依赖于sentinel进程。这种模式基本已经可以实现高可用,读写分离 ,但是在性能,存储量上还是不够好。

cluster集群:是Redis的一种分布式解决方案,在3.0版本中正式提出,这个方案把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。Redis Cluster槽的范围是0 ~ 16383。槽是集群内数据管理和迁移的基本单位。主要目的是为了方便数据的拆分和集群的扩展,每个节点负责一定数量的槽。通过slot = CRC16(key)&16383计算所在卡槽的节点位置。

三、搭建Redis Cluster集群

结构图

配置文件
# ip监控
bind 0.0.0.0
protected-mode no
# 端口  修改
port 7000
# 后台运行
daemonize yes
# 工作目录
dir ./
# pid 修改
pidfile "/var/run/redis_7001.pid"
# 日志名  修改
logfile "redis_7001.log"
# RDB同步数据  修改
dbfilename "dump_7001.rdb"
# AOF同步
appendonly yes
# 修改
appendfilename "appendonly_7001.aof"
# AOF 策略
appendfsync everysec
# 失效消息通知配置
# notify-keyspace-events "xE"
# 开启cluster, 去掉注释
cluster-enabled yes
# 自动生成  修改
cluster-config-file cluster_7001.conf
# 节点通信时间
cluster-node-timeout 15000

将这配置文件复制六份需要修改的地方,修改之后。

启动脚本
#!/bin/bash

# 整个测试环境的根目录
ROOT_PATH=/opt/redis-cluster-self-service
# 存放redis-server的目录
REDIS_SERVER=/opt/redis-cluster-self-service/redis-master/bin/redis-server
echo ">>> 清除启动的 Redis cluster 集群...";
for item in  `ps -ef | grep -v grep | grep redis | awk '{print $2}'`
do
    echo $item
    kill -9 $item
done
echo ">>> 成功清除启动的 Redis cluster 集群...";
echo ">>> 启动redis cluster 集群...";
for item in {0..5}
    do
        $REDIS_SERVER $ROOT_PATH/redis-node-700${item}/redis-700${item}.conf;
	if [ $? == 0 ];then
	    # sleep 5s;
	    echo "启动端口为700${item}的Redis服务器成功";
	else
	    echo "启动端口为700${item}的Redis服务器失败";
	fi	
    done

echo ">>> 启动redis cluster 集群结束";
echo ">>> 检测是否启动成功...";
ps -ef | grep -v grep | grep redis
启动集群
[root@long-test redis-cluster-self-service]# ./start.sh # chmod +x start.sh赋予权限
>>> 清除启动的 Redis cluster 集群...
17171
>>> 成功清除启动的 Redis cluster 集群...
>>> 启动redis cluster 集群...
启动端口为7000的Redis服务器成功
启动端口为7001的Redis服务器成功
启动端口为7002的Redis服务器成功
启动端口为7003的Redis服务器成功
启动端口为7004的Redis服务器成功
启动端口为7005的Redis服务器成功
>>> 启动redis cluster 集群结束
>>> 检测是否启动成功...
root      17237      1  0 05:59 ?        00:00:00 /opt/redis-cluster-self-service/redis-master/bin/redis-server 0.0.0.0:7000 [cluster]
root      17242      1  0 05:59 ?        00:00:00 /opt/redis-cluster-self-service/redis-master/bin/redis-server 0.0.0.0:7001 [cluster]
root      17244      1  0 05:59 ?        00:00:00 /opt/redis-cluster-self-service/redis-master/bin/redis-server 0.0.0.0:7002 [cluster]
root      17249      1  0 05:59 ?        00:00:00 /opt/redis-cluster-self-service/redis-master/bin/redis-server 0.0.0.0:7003 [cluster]
root      17257      1  4 05:59 ?        00:00:00 /opt/redis-cluster-self-service/redis-master/bin/redis-server 0.0.0.0:7004 [cluster]
root      17259      1 11 05:59 ?        00:00:00 /opt/redis-cluster-self-service/redis-master/bin/redis-server 0.0.0.0:7005 [cluster]
[root@long-test redis-cluster-self-service]# 
连接其中一个Redis
[root@long-test redis-cluster-self-service]# redis-cli -p 7000   # 连接7000端口
127.0.0.1:7000> set name 1234
(error) CLUSTERDOWN Hash slot not served   # 未分配卡槽
分配卡槽
[root@long-test redis-cluster-self-service]# redis-cli --cluster create 192.168.252.131:7000 192.168.252.131:7001 192.168.252.131:7002 192.168.252.131:7003 192.168.252.131:7004 192.168.252.131:7005 --cluster-replicas 1

--cluster-replicas 1:是表示主节点和从节点为1:1的比例(一主一从)的结构。

分配的卡槽情况:

最后分配结果:

再次连接其中一个redis
[root@long-test redis-cluster-self-service]# redis-cli -p 7000
127.0.0.1:7000> set name 123456
(error) MOVED 5798 192.168.252.131:7001   # 仍然不能写入值,提示我们key对应的卡槽在7001这个redis上
127.0.0.1:7000> 

我们需要在连接的时候添加一个重定向的参数:

[root@long-test redis-cluster-self-service]# redis-cli -p 7000 -c  # -c redis的客户端会为我们自动重定向
127.0.0.1:7000> set name 123456
-> Redirected to slot [5798] located at 192.168.252.131:7001
OK
192.168.252.131:7001>  # 现在已经在redis的7001这个服务器上了

四、 Redis Cluster 扩容

复制上面的配置文件,然后启动服务:

70067007就是我们新需要扩容的redis服务。

Redis将节点扩容到Redis集群中

先添加一个主节点

# 将7006 扩容主节点
[root@long-test redis-cluster-self-service]# redis-cli --cluster add-node 192.168.252.131:7006 192.168.252.131:7000

扩容主节点之后的集群节点情况

再添加一个从节点:

# 将7007 扩容从节点
[root@long-test redis-cluster-self-service]# redis-cli --cluster add-node 192.168.252.131:7007 192.168.252.131:7000 --cluster-slave --cluster-master-id 22ebb08e9461445d8f77ca650fca7d1a777928aa

# --cluster-master-id 后面添加的是主节点的ID, 从上图命令中可以得到

再次查看添加从节点之后集群情况:

这样就说明我们添加节点成功了,但是我们还需要分配卡槽,这样的话添加的节点才可以读写数据。

分配卡槽

在我们刚才是三台的时候每台redis分到的卡槽是:16384/3=5461,其中一个节点时5462个,剩下两个是5461

现在我们扩容的时候是4台redis, 平均分配到四台上,那我们每一台16384/4=4096

分配的方法有两种方式:

  • all: 均摊,从当前的每个节点中分配一部分到新的节点中
  • done: 选择某一个节点进行分配。

接下来就是yes,等待分配移动节点结束,在这期间是无法读写的。

分配之后的卡槽情况:

分配之后我们进行读写:

[root@long-test redis-cluster-self-service]# redis-cli -p 7000 -c
127.0.0.1:7000> set yyyy 123456   # 可以写入7006节点的数据了
-> Redirected to slot [10980] located at 192.168.252.131:7006
OK
192.168.252.131:7006> 

五、 Redis Cluster 缩容

缩容的命令:

[root@long-test redis-cluster-self-service]# redis-cli --cluster reshard 192.168.252.131:7000 --cluster-from 532c30c5d91a4011145ce7e92d4949fdf056bf73 --cluster-to 51e81d10bbd2cb399e91273fc52831c24a82dac9 --cluster-slots 4096

# --cluster-from 要减少的节点ID
# --cluster-to   要移动到的节点ID
# --cluster-slots 4096   移动的节点

缩容之后的卡槽情况:

六、Redis Cluster 宕机自动选举

7006节点杀掉,我们看一下7007是否会变为主节点:

7006节点启动之后我们会发现变为从节点:

七、 Springboot整合Redis Cluster

这里我们每个redis节点配置一个密码:

在redis的配置文件中添加一个密码:

requirpass 123456

重新创建分配卡槽

[root@long-test ]# redis-cli --cluster create 192.168.252.131:7000 192.168.252.131:7001 192.168.252.131:7002 192.168.252.131:7003 192.168.252.131:7004 192.168.252.131:7005 192.168.252.131:7006 192.168.252.131:7007 -a 123456 --cluster-replicas 1

# -a 123456    是为了设置整个集群的密码123456

依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置文件

spring:
  redis:
    password: 123456
    cluster:
      # 所有节点列表
      nodes:
        - 192.168.252.131:7000
        - 192.168.252.131:7001
        - 192.168.252.131:7002
        - 192.168.252.131:7003
        - 192.168.252.131:7004
        - 192.168.252.131:7005
        - 192.168.252.131:7006
        - 192.168.252.131:7007
      # 最大重定向次数  
      max-redirects: 4
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 8
        # 连接池最大阻塞等待时间
        max-wait: -1ms
        # 连接池中最大空闲连接数
        max-idle: 10
        # 连接池中最小空闲连接数
        min-idle: 5

使用:

@RestController
public class RedisController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/set_key")
    public String setKey() {
        stringRedisTemplate.opsForValue().set("order_name", UUID.randomUUID().toString());
        System.out.println("设置的key");
        return "success";
    }

}

查看我们写入的值:

[root@long-test redis-cluster-self-service]# redis-cli -p 7000 -a 123456 -c
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:7000> get order_name  # 重定向到7001节点
-> Redirected to slot [4291] located at 192.168.252.131:7001
"407f7841-3054-4775-ac00-9b03d502a164"
192.168.252.131:7001> 

八、主从、哨兵、集群的辨析

最后我们在看一下Redis中多机数据库实现的这三种模式的总结和辨析:

  • 主从复制:集群方式里最简单的。它主要是基于Redis的主从复制特性架构的。通常我们会设置一个主节点,N个从节点;默认情况下,主节点负责处理使用者的IO操作,而从节点则会对主节点的数据进行备份,并且也会对外提供读操作的处理。
  • 哨兵集群:基于主从模式做的一定变化,它能够为Redis提供了高可用性。在实际生产中,服务器难免不会遇到一些突发状况:服务器宕机,停电,硬件损坏等。这些情况一旦发生,其后果往往是不可估量的。而哨兵模式在一定程度上能够帮我们规避掉这些意外导致的灾难性后果。这种模式下每台redis服务器都存储相同的数据,很浪费内存;并难以支持现线扩容,横向扩展比较麻烦。
  • Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。也就是分布式存储,也就是说每台redis节点上存储不同的内容。并且仍然具有主从和哨兵的优点。当其中一个主节点宕机需要半数以上的主节点确定才会从从节点中选举出新的主节点。

九、欢迎关注下微信公众号

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章