1、Redis集群简介

1.1 RedisCluster概念

Redis的分布式解决方案,在3.0版本后推出的方案,有效地解决了Redis分布式的需求,当一个服务宕机可以快速的切换到另外一个服务。redis cluster主要是针对海量数据+高并发+高可用的场景。

2、SpringBoot整合Redis集群

2.1 核心依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${redis-client.version}</version>
</dependency>

2.2 核心配置

spring:
# Redis 集群
redis:
sentinel:
# sentinel 配置
master: mymaster
nodes: 192.168.0.127:26379
maxTotal: 60
minIdle: 10
maxWaitMillis: 10000
testWhileIdle: true
testOnBorrow: true
testOnReturn: false
timeBetweenEvictionRunsMillis: 10000

2.3 参数渲染类

@ConfigurationProperties(prefix = "spring.redis.sentinel")
public class RedisParam {
private String nodes ;
private String master ;
private Integer maxTotal ;
private Integer minIdle ;
private Integer maxWaitMillis ;
private Integer timeBetweenEvictionRunsMillis ;
private boolean testWhileIdle ;
private boolean testOnBorrow ;
private boolean testOnReturn ;
// 省略GET和SET方法
}

2.4 集群配置文件

@Configuration
@EnableConfigurationProperties(RedisParam.class)
public class RedisPool {
@Resource
private RedisParam redisParam ;
@Bean("jedisSentinelPool")
public JedisSentinelPool getRedisPool (){
Set<String> sentinels = new HashSet<>();
sentinels.addAll(Arrays.asList(redisParam.getNodes().split(",")));
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(redisParam.getMaxTotal());
poolConfig.setMinIdle(redisParam.getMinIdle());
poolConfig.setMaxWaitMillis(redisParam.getMaxWaitMillis());
poolConfig.setTestWhileIdle(redisParam.isTestWhileIdle());
poolConfig.setTestOnBorrow(redisParam.isTestOnBorrow());
poolConfig.setTestOnReturn(redisParam.isTestOnReturn());
poolConfig.setTimeBetweenEvictionRunsMillis(redisParam.getTimeBetweenEvictionRunsMillis());
JedisSentinelPool redisPool = new JedisSentinelPool(redisParam.getMaster(), sentinels, poolConfig);
return redisPool;
}
@Bean
SpringUtil springUtil() {
return new SpringUtil();
}
@Bean
RedisListener redisListener() {
return new RedisListener();
}
}

2.5 配置Redis模板类

@Configuration
public class RedisConfig {
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(factory);
return stringRedisTemplate;
}
}

3、模拟队列场景案例

生产者消费者模式:客户端监听消息队列,消息达到,消费者马上消费,如果消息队列里面没有消息,那么消费者就继续监听。基于Redis的LPUSH(BLPUSH)把消息入队,用 RPOP(BRPOP)获取消息的模式。

3.1 加锁解锁工具

@Component
public class RedisLock {
private static String keyPrefix = "RedisLock:";
@Resource
private JedisSentinelPool jedisSentinelPool;
public boolean addLock(String key, long expire) {
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
/*
* nxxx的值只能取NX或者XX,如果取NX,则只有当key不存在是才进行set,如果取XX,则只有当key已经存在时才进行set
* expx的值只能取EX或者PX,代表数据过期时间的单位,EX代表秒,PX代表毫秒。
*/
String value = jedis.set(keyPrefix + key, "1", "nx", "ex", expire);
return value != null;
} catch (Exception e){
e.printStackTrace();
}finally {
if (jedis != null) jedis.close();
}
return false;
}
public void removeLock(String key) {
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.del(keyPrefix + key);
} finally {
if (jedis != null) jedis.close();
}
}
}

3.2 消息消费

1)封装接口

public interface RedisHandler  {
/**
* 队列名称
*/
String queueName(); /**
* 队列消息内容
*/
String consume (String msgBody);
}

2)接口实现

@Component
public class LogAListen implements RedisHandler {
private static final Logger LOG = LoggerFactory.getLogger(LogAListen.class) ;
@Resource
private RedisLock redisLock;
@Override
public String queueName() {
return "LogA-key";
}
@Override
public String consume(String msgBody) {
// 加锁,防止消息重复投递
String lockKey = "lock-order-uuid-A";
boolean lock = false;
try {
lock = redisLock.addLock(lockKey, 60);
if (!lock) {
return "success";
}
LOG.info("LogA-key == >>" + msgBody);
} catch (Exception e){
e.printStackTrace();
} finally {
if (lock) {
redisLock.removeLock(lockKey);
}
}
return "success";
}
}

3.3 消息监听器

public class RedisListener implements InitializingBean {
/**
* Redis 集群
*/
@Resource
private JedisSentinelPool jedisSentinelPool;
private List<RedisHandler> handlers = null;
private ExecutorService product = null;
private ExecutorService consumer = null;
/**
* 初始化配置
*/
@Override
public void afterPropertiesSet() {
handlers = SpringUtil.getBeans(RedisHandler.class) ;
product = new ThreadPoolExecutor(10,15,60 * 3,
TimeUnit.SECONDS,new SynchronousQueue<>());
consumer = new ThreadPoolExecutor(10,15,60 * 3,
TimeUnit.SECONDS,new SynchronousQueue<>());
for (RedisHandler redisHandler : handlers){
product.execute(() -> {
redisTask(redisHandler);
});
}
}
/**
* 队列监听
*/
public void redisTask (RedisHandler redisHandler){
Jedis jedis = null ;
while (true){
try {
jedis = jedisSentinelPool.getResource() ;
List<String> msgBodyList = jedis.brpop(0, redisHandler.queueName());
if (msgBodyList != null && msgBodyList.size()>0){
consumer.execute(() -> {
redisHandler.consume(msgBodyList.get(1)) ;
});
}
} catch (Exception e){
e.printStackTrace();
} finally {
if (jedis != null) jedis.close();
}
}
}
}

3.4 消息生产者

@Service
public class RedisServiceImpl implements RedisService {
@Resource
private JedisSentinelPool jedisSentinelPool;
@Override
public void saveQueue(String queueKey, String msgBody) {
Jedis jedis = null;
try {
jedis = jedisSentinelPool.getResource();
jedis.lpush(queueKey,msgBody) ;
} catch (Exception e){
e.printStackTrace();
} finally {
if (jedis != null) jedis.close();
}
}
}

3.5 场景测试接口

@RestController
public class RedisController {
@Resource
private RedisService redisService ;
/**
* 队列推消息
*/
@RequestMapping("/saveQueue")
public String saveQueue (){
MsgBody msgBody = new MsgBody() ;
msgBody.setName("LogAModel");
msgBody.setDesc("描述");
msgBody.setCreateTime(new Date());
redisService.saveQueue("LogA-key", JSONObject.toJSONString(msgBody));
return "success" ;
}
}

(七)整合 Redis集群 ,实现消息队列场景的更多相关文章

  1. SpringBoot2.0 整合 Redis集群 ,实现消息队列场景

    本文源码:GitHub·点这里 || GitEE·点这里 一.Redis集群简介 1.RedisCluster概念 Redis的分布式解决方案,在3.0版本后推出的方案,有效地解决了Redis分布式的 ...

  2. SpringBoot整合Redis集群

    一.环境搭建 Redis集群环境搭建:https://www.cnblogs.com/zwcry/p/9174233.html 二.Spring整合Redis集群 1.pom.xml <proj ...

  3. Redis(七)-- SpringMVC整合Redis集群

    1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...

  4. 05.haproxy+mysql负载均衡 整合 redis集群+ssm

    本篇重点讲解haproxy+mysql负载均衡,搭建完成后与之前搭建的redis+ssm进行整合 (注:这里用到了两台mysql数据库,分别安装两台虚拟机上,已经成功实现主主复制,如果有需要,请查看我 ...

  5. Spring Boot2.0之 整合Redis集群

    项目目录结构: pom: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:// ...

  6. spring 整合redis集群中使用@autowire无效问题的解决办法

    1.视频参考黑马32期宜立方商城第6课 redis对于的代码 我们先变向一个redis客户端的接口文件 package com.test; public interface JedisClient { ...

  7. springboot2.x 整合redis集群的几种方式

    一.不指定redis连接池 #系统默认连接池 yml配置文件: spring: redis: cluster: nodes: - 192.168.1.236:7001 - 192.168.1.236: ...

  8. Redis集群教程(Redis cluster tutorial)

    本博文翻译自Redis官网:http://redis.io/topics/cluster-tutorial        本文档以温和的方式介绍Redis集群,不使用复杂的方式来理解分布式系统的概念. ...

  9. (转)理想化的 Redis 集群

    一个豁达的关键是正确乐观的面对失败的系统.不需要过多的担心,需要一种去说那又怎样的能力.因此架构的设计是如此的重要.许多优秀的系统没有进一步成长的能力,我们应该做的是去使用其他的系统去共同分担工作. ...

随机推荐

  1. Java学习日报8.6

    <构建之法:现代软件工程>读后感 比起一般的教学类书籍,这本书更像是一本传记小说,作者邹欣以自己或者说一些典型的软件工程师为例子,详细介绍了一个软件工程师的工作内容,全书给我的感觉就是以一 ...

  2. java线程与内核线程的关系,及怎么定义ThreadPoolExecutor相关参数

    p.p1 { margin: 0; font: 12px Menlo } p.p1 { margin: 0; font: 12px Menlo } p.p2 { margin: 0; font: 12 ...

  3. 关于一些视图的基本操作(结合YGGL.sql)

    二.操作题 1.创建视图emp_view2,包含员工编号,姓名,所在部门名称和收入. mysql> create or replace view emp_view2 -> as -> ...

  4. 简单TCP服务器和TCP客户端源码(Golang)

    以下代码为服务端,非最终版代码,服务端可以接受多个客户端的请求,且所有消息会显示在服务端上,服务端无法发送消息: package main import ( "fmt" " ...

  5. Python+MySQL随机试卷及答案生成程序

    一.背景 本文章主要是分享如何使用Python从MySQL数据库中面抽取试题,生成的试卷每一份都不一样. 二.准备工作 1.安装Python3 下载地址:https://www.python.org/ ...

  6. 【C++】《C++ Primer 》第十章

    第十章 泛型算法 一.概述 因为它们实现共同的操作,所以称之为"算法".而"泛型",指的是它们可以操作在多种容器类型上. 泛型算法并不直接操作容器,而是遍历由两 ...

  7. 【Flutter】可滚动组件之SingleChildScrollView

    前言 SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件. 接口描述 const SingleChildScrollView({ Key ke ...

  8. SpringBoot整合Shiro完成验证码校验

    SpringBoot整合Shiro完成验证码校验 上一篇:SpringBoot整合Shiro使用Redis作为缓存 首先编写生成验证码的工具类 package club.qy.datao.utils; ...

  9. jenkins 构建历史 显示版本号

    0   jenkins 安装此插件: 此插件名为 " groovy postbuild " 1  效果图: 2   安装插件: 系统管理 --> 插件管理 --> 可选 ...

  10. Springboot之文件监控

    背景:在实际环境部署构成中,由于特殊网络环境因素,有很多服务器之间的网络都是单向的,不能互相访问的,只有通过特定技术手段做到文件的单项摆渡,这就需要在两台服务器上分别写序列化程序和反序列化程序,这里不 ...