博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redisson基本用法
阅读量:2116 次
发布时间:2019-04-30

本文共 15445 字,大约阅读时间需要 51 分钟。

1.  Redisson

Redisson是Redis官方推荐的Java版的Redis客户端。它提供的功能非常多,也非常强大,此处我们只用它的分布式锁功能。

1.1.  基本用法

1 
2
org.redisson
3
redisson
4
3.11.1
5

1.2.  Distributed locks and synchronizers

RedissonClient中提供了好多种锁,还有其它很多实用的方法

1.2.1.  Lock

默认,非公平锁

最简洁的一种方法

指定超时时间 

异步

1.2.2  Fair Lock 

1.2.3  MultiLock

1.2.4  RedLock

1.3.  示例

pom.xml

1 
2
4
4.0.0
5
6
org.springframework.boot
7
spring-boot-starter-parent
8
2.1.6.RELEASE
9
10
11
com.cjs.example
12
cjs-redisson-example
13
0.0.1-SNAPSHOT
14
cjs-redisson-example
15 16
17
1.8
18
19 20
21
22
org.springframework.boot
23
spring-boot-starter-data-jpa
24
25
26
org.springframework.boot
27
spring-boot-starter-data-redis
28
29
30
org.springframework.boot
31
spring-boot-starter-web
32
33 34
35
36
org.redisson
37
redisson
38
3.11.1
39
40 41 42
43
org.apache.commons
44
commons-lang3
45
3.9
46
47
48
com.alibaba
49
fastjson
50
1.2.58
51
52
53
org.apache.commons
54
commons-pool2
55
2.6.2
56
57 58
59
mysql
60
mysql-connector-java
61
runtime
62
63
64
org.projectlombok
65
lombok
66
true
67
68
69 70
71
72
73
org.springframework.boot
74
spring-boot-maven-plugin
75
76
77
78 79

application.yml

1 server: 2   port: 8080 3 spring: 4   application: 5     name: cjs-redisson-example 6   redis: 7     cluster: 8       nodes: 10.0.29.30:6379, 10.0.29.95:6379, 10.0.29.205:6379 9     lettuce:10       pool:11         min-idle: 012         max-idle: 813         max-active: 2014   datasource:15     url: jdbc:mysql://127.0.0.1:3306/test16     username: root17     password: 12345618     driver-class-name: com.mysql.cj.jdbc.Driver19     type: com.zaxxer.hikari.HikariDataSource

RedissonConfig.java

1 package com.cjs.example.lock.config; 2  3 import org.redisson.Redisson; 4 import org.redisson.api.RedissonClient; 5 import org.redisson.config.Config; 6 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Configuration; 8  9 /**10  * @author ChengJianSheng11  * @date 2019-07-2612  */13 @Configuration14 public class RedissonConfig {15 16     @Bean17     public RedissonClient redissonClient() {18         Config config = new Config();19         config.useClusterServers()20                 .setScanInterval(2000)21                 .addNodeAddress("redis://10.0.29.30:6379", "redis://10.0.29.95:6379")22                 .addNodeAddress("redis://10.0.29.205:6379");23 24         RedissonClient redisson = Redisson.create(config);25 26         return redisson;27     }28 29 }

CourseServiceImpl.java 

1 package com.cjs.example.lock.service.impl;  2   3 import com.alibaba.fastjson.JSON;  4 import com.cjs.example.lock.constant.RedisKeyPrefixConstant;  5 import com.cjs.example.lock.model.CourseModel;  6 import com.cjs.example.lock.model.CourseRecordModel;  7 import com.cjs.example.lock.repository.CourseRecordRepository;  8 import com.cjs.example.lock.repository.CourseRepository;  9 import com.cjs.example.lock.service.CourseService; 10 import lombok.extern.slf4j.Slf4j; 11 import org.apache.commons.lang3.StringUtils; 12 import org.redisson.api.RLock; 13 import org.redisson.api.RedissonClient; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.data.redis.core.HashOperations; 16 import org.springframework.data.redis.core.StringRedisTemplate; 17 import org.springframework.stereotype.Service; 18  19 import java.util.concurrent.TimeUnit; 20  21 /** 22  * @author ChengJianSheng 23  * @date 2019-07-26 24  */ 25 @Slf4j 26 @Service 27 public class CourseServiceImpl implements CourseService { 28  29     @Autowired 30     private CourseRepository courseRepository; 31     @Autowired 32     private CourseRecordRepository courseRecordRepository; 33     @Autowired 34     private StringRedisTemplate stringRedisTemplate; 35     @Autowired 36     private RedissonClient redissonClient; 37  38     @Override 39     public CourseModel getById(Integer courseId) { 40  41         CourseModel courseModel = null; 42  43         HashOperations
hashOperations = stringRedisTemplate.opsForHash(); 44 45 String value = hashOperations.get(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId)); 46 47 if (StringUtils.isBlank(value)) { 48 String lockKey = RedisKeyPrefixConstant.LOCK_COURSE + courseId; 49 RLock lock = redissonClient.getLock(lockKey); 50 try { 51 boolean res = lock.tryLock(10, TimeUnit.SECONDS); 52 if (res) { 53 value = hashOperations.get(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId)); 54 if (StringUtils.isBlank(value)) { 55 log.info("从数据库中读取"); 56 courseModel = courseRepository.findById(courseId).orElse(null); 57 hashOperations.put(RedisKeyPrefixConstant.COURSE, String.valueOf(courseId), JSON.toJSONString(courseModel)); 58 } 59 } 60 } catch (InterruptedException e) { 61 e.printStackTrace(); 62 } finally { 63 lock.unlock(); 64 } 65 } else { 66 log.info("从缓存中读取"); 67 courseModel = JSON.parseObject(value, CourseModel.class); 68 } 69 70 return courseModel; 71 } 72 73 @Override 74 public void upload(Integer userId, Integer courseId, Integer studyProcess) { 75 76 HashOperations
hashOperations = stringRedisTemplate.opsForHash(); 77 78 String cacheKey = RedisKeyPrefixConstant.COURSE_PROGRESS + ":" + userId; 79 String cacheValue = hashOperations.get(cacheKey, String.valueOf(courseId)); 80 if (StringUtils.isNotBlank(cacheValue) && studyProcess <= Integer.valueOf(cacheValue)) { 81 return; 82 } 83 84 String lockKey = "upload:" + userId + ":" + courseId; 85 86 RLock lock = redissonClient.getLock(lockKey); 87 88 try { 89 lock.lock(10, TimeUnit.SECONDS); 90 91 cacheValue = hashOperations.get(cacheKey, String.valueOf(courseId)); 92 if (StringUtils.isBlank(cacheValue) || studyProcess > Integer.valueOf(cacheValue)) { 93 CourseRecordModel model = new CourseRecordModel(); 94 model.setUserId(userId); 95 model.setCourseId(courseId); 96 model.setStudyProcess(studyProcess); 97 courseRecordRepository.save(model); 98 hashOperations.put(cacheKey, String.valueOf(courseId), String.valueOf(studyProcess)); 99 }100 101 } catch (Exception ex) {102 log.error("获取所超时!", ex);103 } finally {104 lock.unlock();105 }106 107 }108 }

StockServiceImpl.java

1 package com.cjs.example.lock.service.impl; 2  3 import com.cjs.example.lock.constant.RedisKeyPrefixConstant; 4 import com.cjs.example.lock.service.StockService; 5 import org.apache.commons.lang3.StringUtils; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.data.redis.core.HashOperations; 8 import org.springframework.data.redis.core.StringRedisTemplate; 9 import org.springframework.stereotype.Service;10 11 /**12  * @author ChengJianSheng13  * @date 2019-07-2614  */15 @Service16 public class StockServiceImpl implements StockService {17 18     @Autowired19     private StringRedisTemplate stringRedisTemplate;20 21     @Override22     public int getByProduct(Integer productId) {23         HashOperations
hashOperations = stringRedisTemplate.opsForHash();24 String value = hashOperations.get(RedisKeyPrefixConstant.STOCK, String.valueOf(productId));25 if (StringUtils.isBlank(value)) {26 return 0;27 }28 return Integer.valueOf(value);29 }30 31 @Override32 public boolean decrease(Integer productId) {33 int stock = getByProduct(productId);34 if (stock <= 0) {35 return false;36 }37 HashOperations
hashOperations = stringRedisTemplate.opsForHash();38 hashOperations.put(RedisKeyPrefixConstant.STOCK, String.valueOf(productId), String.valueOf(stock - 1));39 return true;40 }41 }

OrderServiceImpl.java

1 package com.cjs.example.lock.service.impl; 2  3 import com.cjs.example.lock.model.OrderModel; 4 import com.cjs.example.lock.repository.OrderRepository; 5 import com.cjs.example.lock.service.OrderService; 6 import com.cjs.example.lock.service.StockService; 7 import lombok.extern.slf4j.Slf4j; 8 import org.redisson.api.RLock; 9 import org.redisson.api.RedissonClient;10 import org.springframework.beans.factory.annotation.Autowired;11 import org.springframework.stereotype.Service;12 13 import java.util.Date;14 import java.util.UUID;15 import java.util.concurrent.TimeUnit;16 17 /**18  * @author ChengJianSheng19  * @date 2019-07-3020  */21 @Slf4j22 @Service23 public class OrderServiceImpl implements OrderService {24 25     @Autowired26     private StockService stockService;27     @Autowired28     private OrderRepository orderRepository;29     @Autowired30     private RedissonClient redissonClient;31 32     /**33      * 乐观锁34      */35     @Override36     public String save(Integer userId, Integer productId) {37         int stock = stockService.getByProduct(productId);38         log.info("剩余库存:{}", stock);39         if (stock <= 0) {40             return null;41         }42 43         //  如果不加锁,必然超卖44 45         RLock lock = redissonClient.getLock("stock:" + productId);46 47         try {48             lock.lock(10, TimeUnit.SECONDS);49 50             String orderNo = UUID.randomUUID().toString().replace("-", "").toUpperCase();51 52             if (stockService.decrease(productId)) {53 54                 OrderModel orderModel = new OrderModel();55                 orderModel.setUserId(userId);56                 orderModel.setProductId(productId);57                 orderModel.setOrderNo(orderNo);58                 Date now = new Date();59                 orderModel.setCreateTime(now);60                 orderModel.setUpdateTime(now);61                 orderRepository.save(orderModel);62 63                 return orderNo;64             }65 66         } catch (Exception ex) {67             log.error("下单失败", ex);68         } finally {69             lock.unlock();70         }71 72         return null;73     }74 75 }

OrderModel.java

1 package com.cjs.example.lock.model; 2  3 import lombok.Data; 4  5 import javax.persistence.*; 6 import java.io.Serializable; 7 import java.util.Date; 8  9 /**10  * @author ChengJianSheng11  * @date 2019-07-3012  */13 @Data14 @Entity15 @Table(name = "t_order")16 public class OrderModel implements Serializable {17 18     @Id19     @GeneratedValue(strategy = GenerationType.IDENTITY)20     private Integer id;21 22     @Column(name = "order_no")23     private String orderNo;24 25     @Column(name = "product_id")26     private Integer productId;27 28     @Column(name = "user_id")29     private Integer userId;30 31     @Column(name = "create_time")32     private Date createTime;33 34     @Column(name = "update_time")35     private Date updateTime;36 } 

数据库脚本.sql

1 SET NAMES utf8mb4; 2 SET FOREIGN_KEY_CHECKS = 0; 3  4 -- ---------------------------- 5 -- Table structure for t_course 6 -- ---------------------------- 7 DROP TABLE IF EXISTS `t_course`; 8 CREATE TABLE `t_course` ( 9   `id` int(11) NOT NULL AUTO_INCREMENT,10   `course_name` varchar(64) NOT NULL,11   `course_type` tinyint(4) NOT NULL DEFAULT '1',12   `start_time` datetime NOT NULL,13   PRIMARY KEY (`id`)14 ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;15 16 -- ----------------------------17 -- Table structure for t_order18 -- ----------------------------19 DROP TABLE IF EXISTS `t_order`;20 CREATE TABLE `t_order` (21   `id` int(11) NOT NULL AUTO_INCREMENT,22   `order_no` varchar(256) CHARACTER SET latin1 NOT NULL,23   `user_id` int(11) NOT NULL,24   `product_id` int(11) NOT NULL,25   `create_time` datetime NOT NULL,26   `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,27   PRIMARY KEY (`id`)28 ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;29 30 -- ----------------------------31 -- Table structure for t_user_course_record32 -- ----------------------------33 DROP TABLE IF EXISTS `t_user_course_record`;34 CREATE TABLE `t_user_course_record` (35   `id` int(11) NOT NULL AUTO_INCREMENT,36   `user_id` int(11) NOT NULL,37   `course_id` int(11) NOT NULL,38   `study_process` int(11) NOT NULL,39   PRIMARY KEY (`id`)40 ) ENGINE=InnoDB AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4;41 42 SET FOREIGN_KEY_CHECKS = 1; 

1.4  工程结构

 

1.5  Redis集群创建

1.6  测试

测试/course/upload

测试/order/create

2.  Spring Integration

用法与Redisson类似

1 
2
org.springframework.boot
3
spring-boot-starter-integration
4
5
6
org.springframework.integration
7
spring-integration-redis
8
1 package com.kaishustory.base.conf; 2  3 import org.springframework.context.annotation.Bean; 4 import org.springframework.context.annotation.Configuration; 5 import org.springframework.data.redis.connection.RedisConnectionFactory; 6 import org.springframework.integration.redis.util.RedisLockRegistry; 7  8 /** 9  * @author ChengJianSheng10  * @date 2019-07-3011  */12 @Configuration13 public class RedisLockConfig {14 15     @Bean16     public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {17         return new RedisLockRegistry(redisConnectionFactory, "asdf")18     }19 20 }
1 @Autowired 2 private RedisLockRegistry redisLockRegistry; 3  4 public void save(Integer userId) { 5  6     String lockKey = "order:" + userId; 7  8     Lock lock = redisLockRegistry.obtain(lockKey); 9     try {10         lock.lock();11 12         //todo13 14     } finally {15         lock.unlock();16     }17 18 }

3.  其它

 

来源:

转载地址:http://faqef.baihongyu.com/

你可能感兴趣的文章
source insight使用方法简介
查看>>
<stdarg.h>头文件的使用
查看>>
C++/C 宏定义(define)中# ## 的含义 宏拼接
查看>>
Git安装配置
查看>>
linux中fork()函数详解
查看>>
C语言字符、字符串操作偏僻函数总结
查看>>
Git的Patch功能
查看>>
分析C语言的声明
查看>>
TCP为什么是三次握手,为什么不是两次或者四次 && TCP四次挥手
查看>>
C结构体、C++结构体、C++类的区别
查看>>
进程和线程的概念、区别和联系
查看>>
CMake 入门实战
查看>>
绑定CPU逻辑核心的利器——taskset
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
逆序对的数量(递归+归并思想)
查看>>
数的范围(二分查找上下界)
查看>>