原文: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); } }