原文:https://blog.csdn.net/c_zyer/article/details/79415728java
本文主要跟你們分享在Springboot中集成Jedis和Redisson的方法。爲何要集成兩個redis客戶端?那是由於它們各有所長也各有所缺,合在一塊兒才能完善彼此。Jedis做爲Redis客戶端的java版實現實現了絕大部分的Redis原生功能,可是卻沒有對分佈式線程控制作很好的支持。而Redisson是Redis官方推薦的支持分佈式操做的Redis Java版客戶端,但它卻不支持一些基礎的Redis原生功能,因此Jedis和Redisson只有整合到一塊兒使用,才能更好的知足用戶的需求。node
接下來,分幾個步驟分享給你們如何在Springboot中集成Jedis和Redisson。git
首先,經過start.spring.io生成一個支持redis的web項目github
將生成的項目導入IDE,e.g., Intellij IDEA.web
在pom文件中加入redisson依賴 (添加完後,能夠作下Maven -> Reimport)redis
爲每一個環境建立一套配置文件spring
本地開發環境以-local結尾,測試環境以-test結尾,生產環境以-prod結尾。而後在application.yml配置文件中指定激活那個環境的配置文件api
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); } }