SpringBoot+Redis-Cluster集群搭建及调优

2023-10-31

转载请注明出处

集群配置

3主3从

服务器配置

六台(14~19)Linux服务器简易版,8G运行内存

具体搭建步骤

安装所必须的一些工具包

如果已经安装过则无需安装
yum install gcc
yum -y install wget
yum -y install vim*

安装redis

在14服务器上进行以下操作

#进入安装目录,下载redis包并安装
cd /usr/local/
wget https://download.redis.io/releases/redis-5.0.8.tar.gz
tar xzf redis-5.0.8.tar.gz
cd redis‐5.0.8
make

#启动并指定配置文件
src/redis‐server redis.conf(使用后台启动,修改redis.conf里的daemonize改为yes)

#验证启动是否成功
ps -ef | grep redis
#进入redis客户端
src/redis-cli -p 6379 (默认6379端口)
#退出客户端
quit

到目前位置,已经成功搭建了一个单击redis,下面介绍如何使其成为集群

集群搭建

安装其他redis节点

在另外5台服务器上(15~19),同样地按以上步骤安装redis

修改14上面的redis.conf配置文件

(1)daemonize yes
(2)port 8001(分别对每个机器的端口号进行设置)
(3)pidfile /var/run/redis_8001.pid
(4)logfile “8001.log”
(5)dir /usr/local/redis-cluster/8001/(指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据)
(6)cluster-enabled yes(启动集群模式)
(7)cluster-config-file nodes-8001.conf(集群节点信息文件,这里800x好和port对应上)
(8)cluster-node-timeout 5000
(9)# bind 127.0.0.1(去掉bind绑定访问ip信息)
(10) protected-mode no (关闭保护模式)
(11) appendonly yes
#如果要设置密码需要增加如下配置:
(12) requirepass 123456 (设置redis访问密码)
(13) masterauth 123456 (设置集群节点间访问密码,跟上面一致)

复制修改后的配置文件至其他节点并替换

替换后,将配置文件的端口改为相应节点的端口,使用命令批量替换
:%s/源字符串/目的字符串/g

分别启动所有redis节点并验证启动成功

使用上面安装redis的命令启动即可,不再赘述。

设置防火墙开放指定节点,保证节点间正常通信

如果未开放端口,会出现创建集群命令超时的现象

firewall-cmd --zone=public --add-port=此处填写端口/tcp --permanent
firewall-cmd --reload

使用cli创建整体的redis集群

进入我们第一个搭建的redis节点14,执行如下命令:
注意:cli命令在redis5.0之后才会有(之前是使用meet命令已被淘汰);–cluster-replicas 1代表一个主节点对应一个从节点,也就是三主三从,默认哈希槽平均分配。

/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster create --cluster-replicas 1 192.168.2.14:8001 192.168.2.15:8002 192.168.2.16:8003 192.168.2.17:8004 192.168.2.18:8005 192.168.2.19:8006

创建成功后会有如下提示
在这里插入图片描述

RedisCluster帮助命令

吃透这个命令里面的东西蛮重要,玩转cluster这是第一步

/usr/local/redis-5.0.8/src/redis-cli -a 123456 --cluster help

验证集群

cluster info(查看集群信息)、cluster nodes(查看节点列表)
在这里插入图片描述
./redis-cli -c -h -p(连接任意一个客户端即连接集群,‐a访问服务端密码,‐c表示集群模式,指定ip地址和端口号)
如果不加-c,倒是也可以连上,但如果连节点1并执行set操作,此时算出来的哈希槽命中了节点二,就会报错
如/usr/local/redis-5.0.8/src/redis-cli -a 123456 -h 192.168.2.101 -p 8001 -c
使用程序或可视化工具进行数据操作

关闭集群

/usr/local/redis-5.0.8/src/redis-cli -a 123456 -c -h 192.168.2.102 -p 8002 shutdown

集群扩容

新增一对主从节点,其中主节点要先加入,加入后通过cluster nodes命令复制其ID备用

/usr/local/redis-5.0.8/src/redis-cli --cluster add-node 新增主节点IP:端口 原任意一节点IP:端口

/usr/local/redis-5.0.8/src/redis-cli --cluster add-node 新增从节点IP:端口 原任意一节点IP:端口 --cluster-slave --cluster-master-id 主节点ID

分配哈希槽

/usr/local/redis-5.0.8/src/redis-cli --cluster reshard 原任意一节点IP:端口 
How many slots do you want to move(from 1 to 16384) 此处填写希望分配的哈希槽数
What is the reciving node ID 此处填写新加入的主节点ID
Please enter all the source node IDs.
Type 'all' to use all tho nodes as sourco nodos for the hash slots.
Type 'done' once you entered all the source nodes IDs .
Source node #1:此处写all,就是从别的节点平均取出哈希槽分配给新节点,也可以写节点ID来限制只有哪些节点分配哈希槽给新节点。
例如:
//平均分
Source node #1:all
//只从节点1分哈希槽出去
Source node #1:节点1的ID
//从节点1和节点2平均分哈希槽出去
Source node #1:节点1的ID
Source node #2:节点2的ID

注意:
新分配的哈希槽不一定是连续的
槽位迁移了,数据也会被迁移到新的节点上

如果其中一对主从节点挂掉了,整个集群将不可用,更改一条配置可将其变为可用,但这样就会存在丢失数据的风险:

//改为no是可用
cluster-replica-no-coverage no

SpringBoot整合redis-cluster

依赖

<!--默认是lettuce客户端-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

yml或properties文件

两种配置文件二选一即可,推荐yml,因为优雅并且社区文档多,现在很少人用properties了

yml

spring:
  redis:
    password: 123456  #密码
    lettuce:  #lettuce连接池配置
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 1000
      shutdown-timeout: 100
    cluster:  #集群配置
      nodes:
        - 192.168.2.14:8001
        - 192.168.2.15:8002
        - 192.168.2.16:8003
        - 192.168.2.17:8004
        - 192.168.2.18:8005
        - 192.168.2.19:8006
      max-redirects: 3

properties

spring.redis.password=123456
spring.redis.lettuce.pool.max-active=1000
spring.redis.lettuce.pool.min-idle=10
spring.redis.lettuce.pool.max-idle=50
spring.redis.lettuce.pool.max-wait=1000
spring.redis.timeout=3000
# springboot2.3 以后加上下面配置可自动刷新拓扑,某节点挂掉后,会有新的主从关系,如果不配置,调用接口时程序会报错
spring.redis.lettuce.cluster.refresh.adaptive=true
spring.redis.lettuce.cluster.refresh.period=5000
# spring.redis.sentinel.master=mymaster
# spring.redis.sentinel.nodes=192.168.2.14:26379,192.168.2.15:26380,192.168.2.16:26381
spring.redis.cluster.nodes=192.168.2.14:8001,192.168.2.15:8002,192.168.2.16:8003,192.168.2.17:8004,192.168.2.18:8005,192.168.2.19:8006

redis集群配置类,配置RedissionClient

package com.nwd.pressuretestutil.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;

/**
 * @ClassName RedisConfig
 * @Description TODO
 * @Author n
 * @Version 1.0
 */
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * 自定义缓存key的生成策略。默认的生成策略是看不懂的(乱码内容) 通过Spring 的依赖注入特性进行自定义的配置注入并且此类是一个配置类可以更多程度的自定义配置
     *
     * @return
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 缓存配置管理器
     */
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory factory) {
        //以锁写入的方式创建RedisCacheWriter对象
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
        //创建默认缓存配置对象
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        RedisCacheManager cacheManager = new RedisCacheManager(writer, config);
        return cacheManager;
    }

    /**
     * redissionClient配置
     */
 @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        if (redisProperties.getCluster() != null) {
            //集群模式配置
            List<String> nodes = redisProperties.getCluster().getNodes();
            List<String> clusterNodes = new ArrayList<>();
            for (int i = 0; i < nodes.size(); i++) {
                clusterNodes.add("redis://" + nodes.get(i));
            }
            ClusterServersConfig clusterServersConfig = config.useClusterServers()
                    .addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()]));
            if (!StringUtils.isEmpty(redisProperties.getPassword())) {
                clusterServersConfig.setPassword(redisProperties.getPassword());
            }
        } else {
            //单节点配置
            String address = "redis://" + redisProperties.getHost() + ":" + redisProperties.getPort();
            SingleServerConfig serverConfig = config.useSingleServer();
            serverConfig.setAddress(address);
            if (!StringUtils.isEmpty(redisProperties.getPassword())) {
                serverConfig.setPassword(redisProperties.getPassword());
            }
            serverConfig.setDatabase(redisProperties.getDatabase());
        }
        //看门狗的锁续期时间,默认30000ms,这里配置成15000ms
        config.setLockWatchdogTimeout(15000);
        return Redisson.create(config);
    }
    
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate <>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 在使用注解@Bean返回RedisTemplate的时候,同时配置hashKey与hashValue的序列化方式。
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

测试接口

/**
     * 测试redis集群连接
     * */
    @GetMapping("/saveRedisCluster")
    public String saveRedisCluster() {
        try{
            Object x = new Object();
            redisTemplate.opsForValue().set("1","123");
        }catch (Exception e){
            e.printStackTrace();
            return "err";
        }
        return "ok";
    }

Redis-Cluster集群调优

附上几个我认为不错的链接:
配置文件详细解读
调优干货

后续还会更新宕机反演、水平拓展节点等

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot+Redis-Cluster集群搭建及调优 的相关文章

随机推荐

  • 关于错误 TypeError: ‘list‘ object is not callable 的解决办法

    在使用类型转换的过程中 运行以下代码产生了错误 1 tuple 将一个序列转换成元组 list 10 20 30 tuple tuple list print tuple print type tuple 2 list 将一个序列转换成列表
  • ip68能达到什么程度防水_IP68级防水能防多少米

    IPX8级防水8是厂商自定义的 具体防水深度由客户根据对自身产品的了解以及要求而定 IP68是连接器防水等级标准的最高级别 大家都知道 看防水连接器防水性能如何 主要看IPXX的后面两位数字XX 第一位X是从0到6 最高等级为6 第2位X是
  • ERROR Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer) kafka.c

    kafka启动时报错如下 2021 12 28 23 35 02 165 ERROR Fatal error during KafkaServer startup Prepare to shutdown kafka server Kafka
  • 必须收藏!Node.js下载(全版本秒下载!)

    全版本都有包含 windows Linux 源码等 根据文件夹名称进行挑选 下载 网址 https nodejs org dist 如何解决了您的问题 欢迎关注我 还希望来JAVA WEB开发交流群 958923746 有问题欢迎共享 共同
  • GTSRB数据集

    GTSRB数据集数据集XML格式现已整理完毕
  • matlab经验模态分解代码_Matlab中的模态分析

    频响函数FRF是如何得这个问题很难吗 回忆了一下 其实对新手来说确实蛮难的 虽然课本上将了一堆模态分析 但是我们都是用较为成熟的商业软件进行 只需要对软件 点点点 即可 勒博其实为此困扰过很久 今天勒博就简单讲讲我们一般说的模态分析 1 勒
  • 互联网金融青年会成立一周年庆典在京举办

    2015年11月15日 互联网金融 北京 高峰论坛暨互联网金融青年会成立一周年庆典在京举办 2015年是互联网金融发展历程中颇具意义的一年 随着行业指导意见的发布 监管框架越来越明晰 在互联网金融即将告别无序进入有序的当下 本次活动以 路越
  • 机器学习——数据探索大致流程

    什么是EDA 在拿到数据后 首先要进行的是数据探索性分析 Exploratory Data Analysis 它可以有效的帮助我们熟悉数据集 了解数据集 初步分析变量间的相互关系以及变量与预测值之间的关系 并且对数据进行初步处理 如 数据的
  • 卷积和积分运算

    先看到卷积运算 知道了卷积就是把模版与图像对应点相乘再相加 把最后的结果代替模版中心点的值的一种运算 但是 近来又看到了积分图像的定义 立马晕菜 于是整理一番 追根溯源一下吧 1 卷积图像 1 1 源头 首先找到了一篇讲解特别好的博文 原文
  • 大学计算机高海波目录,华中师范大学

    个人简介 基本情况 性别 男 出生年月 1974年5月 籍贯 安徽省宿松县 职称 教授 研究方向 新闻传播史论 学历学位 博士研究生 工作单位 华中师范大学新闻传播学院 学习与工作经历 1993 9 1997 6 华中理工大学新闻系本科生
  • Linux环境中VScode无法进行函数跳转

    前言 我在Ubuntu中使用VScode阅读源码 发现无法进行函数跳转 查了很久 最后发现了一下原因 原因一 查看是否下载了clangd插件 原因二 查看是否关闭了intellisense 注意 必须是Disabled 而不是disable
  • 【深度学习与计算机视觉】6、图像分类与搜索

    文章目录 一 神经网络基础 从loss曲线和accuracy来判断如何调整训练参数 二 详解卷积操作 三 海洋鱼类分类 一 神经网络基础 从loss曲线和accuracy来判断如何调整训练参数 1 loss曲线 步长 学习率 batch s
  • 群晖服务器文件管理套件,群晖drive套件的使用教程

    摘要 群晖同步套件最近头脑一热组成了一台J3455的黑群晖1 安装群晖本站之前有分享相关的操作 https u nf za 45 htmlhttps u nf za 44 h 群晖同步套件 最近头脑一热组成了一台J3455的黑群晖 1 安装
  • leetcode第319场周赛

    T1 温度转换 这个题目就很简单 根据题意写代码即可 class Solution public vector
  • Vue实现TabBar底部导航栏灵活组件保姆级超详细

    Vue实现TabBar底部导航栏组件 标题项目介绍 需求 要求tabbar中的文字可动态更改 文字对应的图片动态更改动态增加 文字颜色对应更改 TabBarItem的图片动态更改和增加 整个项目灵活化 利用插槽 路由 父子组件的值传递 利用
  • Ts中泛型的使用

    泛型 指在定义函数 接口或类的时候 不预先指定具体的类型 而在使用的时候再指定具体类型的一种特性 引入 下面创建一个函数 实现功能 根据指定的数量 count 和数据 value 创建一个包含 count 个 value 的数组 不使用泛型
  • 嵌入汇编

    本文介绍内核C语言程序中接触到的嵌入式汇编 内联汇编 语句 具有输入和输出参数的嵌入式汇编语句的基本格式为 asm 汇编语句 输出寄存器 输入寄存器 会被修改的寄存器 除第一行外 后面带冒号的行若不使用就都可以省略 其实asm是内联汇编语句
  • 五十二:JDK动态代理和CGLIB动态代理

    JDK动态代理是利用反射机制生成一个实现代理接口的匿名类 在调用具体方法前调用InvokeHandler来处理 而cglib动态代理是利用asm开源包 对代理对象类的class文件加载进来 通过修改其字节码生成子类来处理 1 如果目标对象实
  • Redis-持久化策略,你确定你懂?又需要注意哪些知识点

    redis是一个内存数据库 一旦服务器宕机 内存中的数据将全部丢失 所以 对 Redis 来说 实现数据的持久化 避免从后端数据库中进行恢复 是至关重要的 目前 Redis 的持久化主要有两大机制 即 AOF Append Only Fil
  • SpringBoot+Redis-Cluster集群搭建及调优

    转载请注明出处 SpringBoot Redis Cluster集群搭建及调优 集群配置 服务器配置 具体搭建步骤 安装所必须的一些工具包 安装redis 集群搭建 安装其他redis节点 修改14上面的redis conf配置文件 复制修