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

20 篇文章 0 订阅
16 篇文章 0 订阅

转载请注明出处

集群配置

3主3从,本文以3主3从为例子讲解,但最好大家在搭建用于公司生产环境的集群时,搭建3主6从,这样不会一个节点宕机导致全部宕机,可靠性更高,会搭3主3从就会搭3主6从。

服务器配置

六台(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集群调优

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

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

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
springboot:是一个基于Java开发的框架,简化了Spring应用的初始化配置和部署过程。它提供了一套开发规范和约定,帮助开发人员快速搭建高效稳定的应用程序。 mybatis-plus:是基于MyBatis的增强工具,提供了一些便捷的CRUD操作方法和代码生成功能,简化了数据库操作的开发工作。它能够轻松集成到SpringBoot应用中,提高开发效率。 springmvc:是一种基于MVC设计模式的Web框架,用于构建Web应用程序。它能够从URL中解析请求参数,并将请求分发给对应的Controller进行处理。SpringMVC提供了一套灵活的配置和注解方式,支持RESTful风格的API开发。 shiro:是一种用于身份验证和授权的框架,可以集成到SpringBoot应用中。它提供了一套简单易用的API,可以处理用户认证、角色授权、会话管理等安全相关的功能。Shiro还支持集成其他认证方式,如LDAP、OAuth等。 redis:是一种开源的内存数据库,采用键值对存储数据。Redis具有高性能、高并发和持久化等特点,常用于缓存、消息队列和分布式锁等场景。在企业级报表后台管理系统中,可以使用Redis来进行缓存数据,提高系统的响应速度和性能。 企业级报表后台管理系统:是一种用于统一管理和生成报表的系统。它通常包括用户权限管理、报表设计、报表生成、数据分析等功能。使用SpringBoot、MyBatis-Plus、SpringMVC、Shiro和Redis等技术,可以快速搭建一个可靠、高效的报表管理系统,满足企业对数据分析和决策的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值