Springboot集成Jedis + Redisson(已自测)
原文:https://blog.csdn.net/c_zyer/article/details/79415728
本文主要跟大家分享在Springboot中集成Jedis和Redisson的方法。为什么要集成两个redis客户端?那是因为它们各有所长也各有所缺,合在一起才能完善彼此。Jedis作为Redis客户端的java版实现实现了绝大部分的Redis原生功能,但是却没有对分布式线程控制做很好的支持。而Redisson是Redis官方推荐的支持分布式操作的Redis Java版客户端,但它却不支持一些基础的Redis原生功能,所以Jedis和Redisson只有整合到一起使用,才能更好的满足用户的需求。
接下来,分几个步骤分享给大家如何在Springboot中集成Jedis和Redisson。
首先,通过start.spring.io生成一个支持redis的web项目

将生成的项目导入IDE,e.g., Intellij IDEA.

在pom文件中加入redisson依赖 (添加完后,可以做下Maven -> Reimport)

为每个环境创建一套配置文件

本地开发环境以-local结尾,测试环境以-test结尾,生产环境以-prod结尾。然后在application.yml配置文件中指定激活那个环境的配置文件

spring:
application:
name: demo
profiles:
active: '@profileActive@'
此处别忘了

在相应环境的application配置文件中添加相应的Redis配置(Redis服务做成了哨兵模式),比如,在application-local.yml加入

spring:
redis:
database: 0
password: 12345678 #密码
port: 6379
timeout: 0
pool:
max-active: 8 #最大连接数
max-idle: 8 #最大空闲连接数
max-wait: -1 #最大等待时间
min-idle: 0
sentinel:
master: master1
nodes: 172.16.33.216:16001,172.16.33.216:16002
server:
port: 9090
在相应环境的Redisson配置文件中加入Redisson的配置信息(配置来源Redisson官方,点击查看)

---
sentinelServersConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: 12345678
subscriptionsPerConnection: 5
clientName: null
loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
slaveSubscriptionConnectionMinimumIdleSize: 1
slaveSubscriptionConnectionPoolSize: 50
slaveConnectionMinimumIdleSize: 10
slaveConnectionPoolSize: 64
masterConnectionMinimumIdleSize: 10
masterConnectionPoolSize: 64
readMode: "SLAVE"
sentinelAddresses:
- "redis://172.16.33.216:16001"
- "redis://172.16.33.216:16002"
masterName: "master1"
database: 0
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
useLinuxNativeEpoll: false
配置文件配好后,还需要注册一个Springboot的启动类(DemoApplication.java)中注册一个RedissonClient Bean,方法如下:
@Autowired
private Environment env;
@Bean(destroyMethod = "shutdown")
public RedissonClient redissonClient() throws IOException {
String[] profiles = env.getActiveProfiles();
String profile = "";
if(profiles.length > 0) {
profile = "-" + profiles[0];
}
return Redisson.create(
Config.fromYAML(new ClassPathResource("redisson" + profile + ".yml").getInputStream())
);
}
Everything is ready. Now let's rock.
创建一个Controller类

@RestController
@RequestMapping("/demo")
public class DemoController {
private static Logger logger = LoggerFactory.getLogger(DemoController.class);
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private RedissonClient redissonClient;
@ResponseBody
@RequestMapping("/lock")
public String lock(@RequestParam("sid") String serverId) {
Long counter = redisTemplate.opsForValue().increment("COUNTER", 1);
RLock lock = redissonClient.getLock("TEST");
try {
lock.lock();
logger.info("Request Thread - " + counter + "[" + serverId +"] locked and begun...");
Thread.sleep(5000); // 5 sec
logger.info("Request Thread - " + counter + "[" + serverId +"] ended successfully...");
} catch (Exception ex) {
logger.error("Error occurred");
} finally {
lock.unlock();
logger.info("Request Thread - " + counter + "[" + serverId +"] unlocked...");
}
return "lock-" + counter + "[" + serverId +"]";
}
}
Code 完成,启动程序,在浏览器中试一把先
=================================================================
以下自己实现的
import java.io.IOException; import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component; @Component
public class RedissonClientConfig { @Autowired
private Environment env; @Bean(destroyMethod = "shutdown")
public RedissonClient redissonClient() throws IOException {
String[] profiles = env.getActiveProfiles();
String profile = "";
if(profiles.length > 0) {
profile = "-" + profiles[0];
}
return Redisson.create(Config.fromYAML(new ClassPathResource("redisson" + profile + ".yml").getInputStream()));
} }
配置文件 redisson-prod.yml
singleServerConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: null
subscriptionsPerConnection: 5
clientName: null
address: "redis://192.168.20.123:6379"
password: 123456
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 32
connectionPoolSize: 64
database: 15
dnsMonitoring: false
dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
"transportMode": "NIO"
controller
import java.util.concurrent.TimeUnit; import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("/demo")
public class DemoController { private static Logger logger = LoggerFactory.getLogger(DemoController.class); @Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private RedissonClient redissonClient; public static int COUNT = 3; @ResponseBody
@RequestMapping("/lock")
public String lock(@RequestParam("sid") String serverId) {
Long counter = redisTemplate.opsForValue().increment("COUNTER", 1);
redisTemplate.expire("COUNTER", 43200, TimeUnit.SECONDS); if (counter>3) {
return "大于3了";
}
RLock lock = redissonClient.getFairLock("TEST");
try {
lock.lock(5, TimeUnit.SECONDS); logger.info("Request Thread - " + counter + "[" + serverId +"] locked and begun...");
if (COUNT > 0) {
COUNT = COUNT - 1;
Thread.sleep(1000);
} else {
return "为0了";
}
logger.info("Request Thread - " + counter + "[" + serverId +"] ended successfully...");
} catch (Exception ex) {
logger.error("Error occurred");
} finally {
if (lock != null && lock.isLocked()) {
lock.unlock();
}
logger.info("Request Thread - " + counter + "[" + serverId +"] unlocked...");
} return "卖出lock-" + counter + "[" + serverId +"]" + COUNT;
} }
写个多线程测试
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch; import com.hyb.util.HttpClientUtil; //多线程的写法1
public class Thread12 { private static Map<String,String> parms = new HashMap<String,String>(); public static void main(String[] args) {
testCountDownLatch();
} public static void testCountDownLatch(){ int threadCount = 2000; final CountDownLatch latch = new CountDownLatch(threadCount);
for(int i=0; i< threadCount; i++){ new Thread(new Runnable() { @Override
public void run() { System.out.println("线程" + Thread.currentThread().getId() + "开始出发"); try {
parms.put("sid", "线程id=" +Thread.currentThread().getId());
String result = HttpClientUtil.doGet("http://192.168.20.234:8061/demo/lock", parms, 20000);
System.out.println("线程result" + result);
} catch (Exception e) {
e.printStackTrace();
} System.out.println("线程" + Thread.currentThread().getId() + "已到达终点"); latch.countDown();
}
}).start();
} try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(threadCount+"个线程已经执行完毕");
} }
import java.util.HashMap;
import java.util.Map; import com.hyb.util.HttpClientUtil; //多线程的写法1
public class Thread12 { public static void main(String args[]) { MyThread myThread =new MyThread();
//myThread.run();
//把这个MyThread包装称为Thread
Thread t1 =new Thread(myThread);
Thread t2=new Thread(myThread);
Thread t3=new Thread(myThread);
Thread t4=new Thread(myThread);
Thread t5=new Thread(myThread);
Thread t6=new Thread(myThread);
Thread t7=new Thread(myThread);
Thread t8=new Thread(myThread);
Thread t9=new Thread(myThread);
Thread t10=new Thread(myThread);
Thread t11=new Thread(myThread);
Thread t12=new Thread(myThread);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
t9.start();
t10.start();
t11.start();
t12.start();
} } class MyThread implements Runnable { private static Map<String,String> parms = new HashMap<String,String>(); @Override
public void run() {
parms.put("sid", Thread.currentThread().getName());
String result = HttpClientUtil.doGet("http://192.168.20.234:8061/demo/lock", parms, 20000);
System.out.println("返回:"+result);
} }
Springboot集成Jedis + Redisson(已自测)的更多相关文章
- SpringBoot 集成Jedis操作set
题外话: Redis是个有趣的东西,相信搞java的或多或少都会用到,面试时也总离不开问Redis,之前觉得redis只是用做缓存,飞快!也因为最初在封装底层的时候,使用Redisson,所以大部分都 ...
- [转帖]SpringBoot集成redisson分布式锁
SpringBoot集成redisson分布式锁 https://www.cnblogs.com/yangzhilong/p/7605807.html 前几天同事刚让增加上这一块东西. 百度查一下 啥 ...
- Windows环境下springboot集成redis的安装与使用
一,redis安装 首先我们需要下载Windows版本的redis压缩包地址如下: https://github.com/MicrosoftArchive/redis/releases 连接打开后如下 ...
- springboot集成websocket实现向前端浏览器发送一个对象,发送消息操作手动触发
工作中有这样一个需示,我们把项目中用到代码缓存到前端浏览器IndexedDB里面,当系统管理员在后台对代码进行变动操作时我们要更新前端缓存中的代码怎么做开始用想用版本方式来处理,但这样的话每次使用代码 ...
- 基于Springboot集成security、oauth2实现认证鉴权、资源管理
1.Oauth2简介 OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAu ...
- springBoot集成redisCluster
本文主要内容:springBoot简介,在SpringBoot中如何集成Redis,可配置Redis集群. 关于SpringBoot 你想要的,这里都有:https://spring.io/proje ...
- springBoot集成Redis遇到的坑(择库)源码分析为什么择库失败
提示: springboot提供了一套链接redis的api,也就是个jar包,用到的连接类叫做LettuceConnectionConfiguration,所以我们引入pom时是这样的 <de ...
- RabbitMQ学习笔记(一):安装及Springboot集成
前言 MQ,即消息队列Message Queue的缩写. RabbitMQ 是MQ的一种,就像招商银行是银行的一种一样.主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息 ...
- springboot集成swagger2构建RESTful API文档
在开发过程中,有时候我们需要不停的测试接口,自测,或者交由测试测试接口,我们需要构建一个文档,都是单独写,太麻烦了,现在使用springboot集成swagger2来构建RESTful API文档,可 ...
随机推荐
- [MySQL]You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
执行update语句,出现问题: 问题描述: You are using safe update mode and you tried to update a table without a WHER ...
- 关于HTML5 boilerplate 的一些笔记
最近在研究HTML5 boilerplate的模版,以此为线索可以有条理地学习一些前端的best practice,好过在W3C的文档汪洋里大海捞针……啊哈哈哈…… 开头的IE探测与no-js类是什么 ...
- eclipse svn 以一种访问权限不允许的方式做了一个访问套接字的尝试
以一种访问权限不允许的方式做了一个访问套接字的尝试 svn: Unable to connect http://xxx.xxx 安装插件是把Eclipse的网络访问禁止了,然后用svn就老提示[以一种 ...
- mogodb(1) 简介
1 引言 NoSQL,全称是“Not Only Sql”,指的是非关系型的数据库.这类数据库主要有这些特点:非关系型的.分布式.开源的.水平可扩展的.原始目的是为了大规模web应用,这场全新的数据库革 ...
- TCP(传输控制协议)
三次握手tcp是一种面向链接的.可靠的.基于字节流的传输层通信协议,提供可靠的连接服务,采用三次握手确认建立一个连接.位码即tcp标志位,有6种标示:1.SYN(synchronous建立连接)2.A ...
- thinkphp5.0架构总览
ThinkPHP5.0应用基于MVC(模型-视图-控制器)的方式来组织. MVC是一个设计模式,它强制性的使应用程序的输入.处理和输出分开.使用MVC应用程序被分成三个核心部件:模型(M).视图(V) ...
- PHP实现插入排序
插入排序思想: 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法. 它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描, 找到相应位置并插入.插入排序 ...
- 转:The Great DOM Fuzz-off of 2017
The Great DOM Fuzz-off of 2017 Posted by Ivan Fratric, Project Zero https://googleprojectzero.blogsp ...
- CodeForcs 797E Array Queries
$dp$预处理,暴力. 如果$k > sqrt(n)$,那么答案不会超过$sqrt(n)$,暴力模拟即可.如果$k <= sqrt(n)$,那么可以$dp$预处理打表. #include ...
- [C#] 实现可设置超时的 Task
前言 如何实现支持超时的 Task ? 关键点: Task.WhenAny 实现 一个扩展方法就可以搞定. // 有返回值 public static async Task<TResult> ...