SpringBoot集成Redis主从架构实现读写分离(哨兵模式)

news2025/1/10 11:00:50

一、前言

这里会使用到spring-boot-starter-data-redis包,spring boot 2的spring-boot-starter-data-redis中,默认使用的是lettuce作为redis客户端,也推荐使用lettuce,Redis使用哨兵集群,这里会通过lettuce连接到哨兵获取对应Redis节点地址从而操作Redis。

Redis主从复制哨兵模式部署:https://blog.csdn.net/weixin_44606481/article/details/133990331

二、集成配置

工程结构
在这里插入图片描述

2.1、POM

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--springboot中的redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- 使用jackson作为redis数据序列化 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.4</version>
        </dependency>
		<!-- SpringBoot测试包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.2、添加配置文件application.yml

因为我们用的spring-boot-starter-data-redis包会自动配置redis连接,在配置文件中添加对应配置即可

spring:
  #redis配置信息
  redis:
    sentinel:
      # 主节点名称 在哨兵配置文件中配置的
      master: mymaster
      # 哨兵ip地址和端口 有多个哨兵就填多个,只填一个其实也能使用
      nodes:
        - 10.0.20.13:26379
        - 10.0.20.13:26380
        - 10.0.20.13:26381
    ## Redis数据库索引(默认为0)
    database: 0
    ## Redis服务连接密码(默认为空)
    password: 123456
    ## 连接超时时间(毫秒)
    timeout: 5000
    lettuce:
      pool:
        ## 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        ## 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1
        ## 连接池中的最大空闲连接
        max-idle: 8
        ## 连接池中的最小空闲连接
        min-idle: 1
      shutdown-timeout: 1000ms

# 打印lettuce debug日志,方便查看读写分离效果
logging:
  pattern:
    console: '%date{yyyy-MM-dd HH:mm:ss.SSS} | %highlight(%5level) [%green(%16.16thread)] %clr(%-50.50logger{49}){cyan} %4line -| %highlight(%msg%n)'
  level:
    root: info
    io.lettuce.core: debug
    org.springframework.data.redis: debug

2.3、编写配置文件

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.lettuce.core.ReadFrom;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.HashSet;

@Configuration
public class RedisConfig{

    /**
     * 配置读写分离
     */
    @Bean
    public RedisConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties) {
        // 配置哨兵节点以及主节点
        RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration(
                redisProperties.getSentinel().getMaster(), new HashSet<>(redisProperties.getSentinel().getNodes())
        );

        // 配置读写分离
        LettucePoolingClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(getPoolConfig(redisProperties.getLettuce().getPool()))
                // ReadFrom.REPLICA_PREFERRED 优先读取从节点,如果从节点不可用,则读取主节点
                .readFrom(ReadFrom.REPLICA_PREFERRED)
                .build();

        return new LettuceConnectionFactory(redisSentinelConfiguration, lettuceClientConfiguration);
    }
    private GenericObjectPoolConfig<?> getPoolConfig(RedisProperties.Pool properties) {
        GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(properties.getMaxActive());
        config.setMaxIdle(properties.getMaxIdle());
        config.setMinIdle(properties.getMinIdle());
        if (properties.getTimeBetweenEvictionRuns() != null) {
            config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis());
        }
        if (properties.getMaxWait() != null) {
            config.setMaxWaitMillis(properties.getMaxWait().toMillis());
        }
        return config;
    }

    /**
     * retemplate相关配置,配置自定义序列化规则为jackson
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(factory);
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        // 值采用json序列化
        template.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();
        return template;
    }
}

2.4、编写启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class LettuceApplication {
    public static void main(String[] args) {
        SpringApplication.run(LettuceApplication.class);
    }
}

2.5、编写测试类测试是否连接成功以及读写分离效果

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes =  LettuceApplication.class)
public class LettuceTest {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Test
    public void t1(){
        String key = "key1";
        System.out.println("插入数据到redis");
        redisTemplate.opsForValue().set(key,"value1");
        Object value = redisTemplate.opsForValue().get(key);
        System.out.println("从redis中获取到值为 "+value);
        Boolean delete = redisTemplate.delete(key);
        System.out.println("删除redis中值 "+delete);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1128521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MCmod:冰与火之歌:龙骑士(一)

1.前言 1.投果结果 我在11天前&#xff08;约2023年10月5日&#xff09;发布了投票&#xff1a;更新选择。 链接&#xff1a;https://blink.csdn.net/details/1585093?spm1001.2014.3001.5501 植物大战僵尸各种僵尸攻略系列已经结束了&#xff0c;你们想要下一个更什么系列 …

1-08 移动端适配 rem+vm

移动端适配 remvm React配置postcss-px-to-viewport 安装依赖&#xff1a;在项目根目录下运行以下命令安装所需的依赖包&#xff1a; npm install postcss-px-to-viewport --save-dev配置代码 const path require(path);module.exports {webpack: {alias: {: path.resolv…

关于binwalk->sasquatch插件安装错误的缓解方案

一些相关报错&#xff1a; WARNING: Extractor.execute failed to run external extractor ‘sasquatch -p 1 -le -d ‘squashfs-root’ ‘%e’’: [Errno 2] No such file or directory: ‘sasquatch’, ‘sasquatch -p 1 -le -d ‘squashfs-root’ ‘%e’’ might not be in…

旋转设备实施预测性维护面临的挑战及解决方案

旋转设备是工业领域中至关重要的一类设备&#xff0c;然而&#xff0c;它们常常面临着各种故障和损耗&#xff0c;给生产运行和设备维护带来了诸多挑战。为了应对这些挑战&#xff0c;越来越多的企业开始采用预测性维护技术&#xff0c;以提前发现故障迹象并采取相应措施。本文…

PS软件 点击 “另存为 Web 所用格式” ,提示错误 无法完成操作 系统找不到指定路径

软件&#xff1a;Adobe Photoshop 问题&#xff1a; PS 点击 另存为 Web 所用格式 &#xff0c;提示错误 无法完成操作 系统找不到指定路径 解决&#xff1a; 如果是Win10以上的系统&#xff0c;出现这种情况基本就是被系统自带的杀毒软件阻止了&#xff0c;可以看一下电脑右…

嵌入式实时操作系统的设计与开发(互斥量学习)

一个无论多么小的系统&#xff0c;都会有大系统的缩影&#xff0c;就像俗话说“麻雀虽小五脏俱全”。 嵌入式实时操作系统中除了基本调度机制&#xff08;创建线程、调度线程、挂起线程等&#xff09;&#xff0c;事件处理机制&#xff08;中断管理、时钟管理&#xff09;、内…

JOSEF约瑟 分合闸电源监视继电器 ZZS-7G/1 220VAC/3S 导轨式安装

系列型号&#xff1a; ZZS-7G/1分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7G/11分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7G/23分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7G/24分闸、合闸、电源监视综合控制装置&#xff1b; ZZS-7/1G11分闸、…

2023年中国电动升降诊疗台产业链及市场规模分析[图]

电动升降诊疗台是一种医疗设备&#xff0c;通常用于医疗机构中&#xff0c;可以通过电动驱动实现高度的升降调整&#xff0c;以便医护人员更好地进行诊断、治疗或手术等操作。这种诊疗台的高度可调节性能&#xff0c;能够适应不同的工作需求和患者情况&#xff0c;提供更舒适和…

自组织映射Python实现

自组织映射&#xff08;Self-organizing map&#xff09;Python实现。仅供学习。 #!/usr/bin/env python3""" Self-organizing map """from math import expimport toolzimport numpy as np import numpy.linalg as LAfrom sklearn.base import…

Elasticsearch快速入门及结合Next.js案例使用

文章目录 什么是Elasticsearch安装Elasticsearch索引文档节点分片 使用Elasticsearch进行全文搜索连接到Elasticsearch创建索引和插入数据创建全文搜索页面测试全文搜索 结语 &#x1f389;欢迎来到Java学习路线专栏~Elasticsearch快速入门及结合Next.js案例使用 ☆* o(≧▽≦)…

Hbuilder打包安卓H5-APP,APP与程序分离,更新无需重新打包

一、目标 使用Hbuilder打包H5-APP 两个方式&#xff1a; 1、将自己的H5页面以及js全部打包进apk程序&#xff0c;后续如果更新&#xff0c;只能迭代apk版本&#xff0c;来进行APP更新升级。 2、使用HBuilder打个空包&#xff0c;修改应用入口页面(首页)地址&#xff0c;这里默…

Centos使用tomcat部署jenkins

jenkins的最新版本已经不在支持jdk8&#xff0c;支持的jdk环境如下&#xff1a; 安装jdk环境 yum -y install java-11-openjdk.x86_64 java-11-openjdk-devel.x86_64安装tomcat tomcat官网 cd /optwget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.82/bin/apache-tomcat…

HarmonyOS DevEso环境搭建

DevEco Studio 3.1配套支持HarmonyOS 3.1版本及以上的应用及服务开发&#xff0c;提供了代码智能编辑、低代码开发、双向预览等功能&#xff0c;以及轻量构建工具DevEco Hvigor 、本地模拟器&#xff0c;持续提升应用及服务开发效率。 1.下载 官方网站&#xff1a; HUAWEI De…

基于Java的校园论坛管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

【Docker从入门到入土 5】 使用Docker-compose一键部署Wordpress平台

Docker-compose 一、YAML 文件格式及编写注意事项&#xff08;重要&#xff09;1.1 简介1.2 yaml语法特性1.3 yaml文件格式1.4 json格式简介 二、Docker-compose2.1 简介2.2 docker-compose的三大概念2.3 docker-compose配置模板文件常用的字段2.4 docker-compose 常用命令 三、…

Java游戏修炼手册:2023 最新学习线路图

前言 有没有一种令人兴奋的学习方法&#xff1f;当然有&#xff01;绝对有&#xff01;而且我要告诉你&#xff0c;学习的快乐可以媲美游戏的刺激。 小学时代&#xff0c;我曾深陷于一款名为"八百万勇士的梦"的游戏。每当放学&#xff0c;我总是迫不及待地打开电脑&a…

【C刷题】day6

一、选择题 1、以下叙述中正确的是&#xff08; &#xff09; A: 只能在循环体内和switch语句体内使用break语句 B: 当break出现在循环体中的switch语句体内时&#xff0c;其作用是跳出该switch语句体&#xff0c;并中止循环体的执行 C: continue语句的作用是&#xff1a;在…

党建展馆vr仿真解说员具有高质量的表现力和互动性

随着虚拟数字人应用渐成趋势&#xff0c;以虚拟数字人为核心的营销远比其他更能加速品牌年轻化进程和认识&#xff0c;助力企业在激烈的市场竞争中脱颖而出&#xff0c;那么企业虚拟IP代言人解决了哪些痛点? 解决品牌与代言人之间的风险问题 传统代言人在代言品牌时&#xff0…

使用SecScanC2构建P2P去中心化网络实现反溯源

个人博客: xzajyjs.cn 前言 这款工具是为了帮助安全研究人员在渗透测试过程中防止扫描被封禁、保护自己免溯源的一种新思路。其利用到了区块链中的p2p点对点去中心化技术构建以来构建代理池。 工具链接&#xff1a;https://github.com/xzajyjs/SecScanC2 实验过程 该工具分为…

前端跨域相关

注&#xff1a;前端配置跨域后服务器端&#xff08;Nginx&#xff09;也需要配置&#xff0c;否则接口无法访问 vue跨域 配置文件 /vue.config.js devServer: { port: 7100, proxy: { /api: { target: http://域名, changeOrigin: true, logLevel: debug, pathRewrite: { ^/…