1.  Redisson

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

https://github.com/redisson/redisson

1.1.  基本用法

1 <dependency>
2    <groupId>org.redisson</groupId>
3    <artifactId>redisson</artifactId>
4    <version>3.11.1</version>
5 </dependency>

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 <?xml version="1.0" encoding="UTF-8"?>2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">4     <modelVersion>4.0.0</modelVersion>5     <parent>6         <groupId>org.springframework.boot</groupId>7         <artifactId>spring-boot-starter-parent</artifactId>8         <version>2.1.6.RELEASE</version>9         <relativePath/> <!-- lookup parent from repository -->
10     </parent>
11     <groupId>com.cjs.example</groupId>
12     <artifactId>cjs-redisson-example</artifactId>
13     <version>0.0.1-SNAPSHOT</version>
14     <name>cjs-redisson-example</name>
15
16     <properties>
17         <java.version>1.8</java.version>
18     </properties>
19
20     <dependencies>
21         <dependency>
22             <groupId>org.springframework.boot</groupId>
23             <artifactId>spring-boot-starter-data-jpa</artifactId>
24         </dependency>
25         <dependency>
26             <groupId>org.springframework.boot</groupId>
27             <artifactId>spring-boot-starter-data-redis</artifactId>
28         </dependency>
29         <dependency>
30             <groupId>org.springframework.boot</groupId>
31             <artifactId>spring-boot-starter-web</artifactId>
32         </dependency>
33
34         <!-- https://github.com/redisson/redisson#quick-start -->
35         <dependency>
36             <groupId>org.redisson</groupId>
37             <artifactId>redisson</artifactId>
38             <version>3.11.1</version>
39         </dependency>
40
41
42         <dependency>
43             <groupId>org.apache.commons</groupId>
44             <artifactId>commons-lang3</artifactId>
45             <version>3.9</version>
46         </dependency>
47         <dependency>
48             <groupId>com.alibaba</groupId>
49             <artifactId>fastjson</artifactId>
50             <version>1.2.58</version>
51         </dependency>
52         <dependency>
53             <groupId>org.apache.commons</groupId>
54             <artifactId>commons-pool2</artifactId>
55             <version>2.6.2</version>
56         </dependency>
57
58         <dependency>
59             <groupId>mysql</groupId>
60             <artifactId>mysql-connector-java</artifactId>
61             <scope>runtime</scope>
62         </dependency>
63         <dependency>
64             <groupId>org.projectlombok</groupId>
65             <artifactId>lombok</artifactId>
66             <optional>true</optional>
67         </dependency>
68     </dependencies>
69
70     <build>
71         <plugins>
72             <plugin>
73                 <groupId>org.springframework.boot</groupId>
74                 <artifactId>spring-boot-maven-plugin</artifactId>
75             </plugin>
76         </plugins>
77     </build>
78
79 </project>

application.yml

 1 server:2   port: 80803 spring:4   application:5     name: cjs-redisson-example6   redis:7     cluster:8       nodes: 10.0.29.30:6379, 10.0.29.95:6379, 10.0.29.205:63799     lettuce:
10       pool:
11         min-idle: 0
12         max-idle: 8
13         max-active: 20
14   datasource:
15     url: jdbc:mysql://127.0.0.1:3306/test
16     username: root
17     password: 123456
18     driver-class-name: com.mysql.cj.jdbc.Driver
19     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 ChengJianSheng
11  * @date 2019-07-26
12  */
13 @Configuration
14 public class RedissonConfig {
15
16     @Bean
17     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 ChengJianSheng23  * @date 2019-07-2624  */25 @Slf4j26 @Service27 public class CourseServiceImpl implements CourseService {28 29     @Autowired30     private CourseRepository courseRepository;31     @Autowired32     private CourseRecordRepository courseRecordRepository;33     @Autowired34     private StringRedisTemplate stringRedisTemplate;35     @Autowired36     private RedissonClient redissonClient;37 38     @Override39     public CourseModel getById(Integer courseId) {40 41         CourseModel courseModel = null;42 43         HashOperations<String, String, String> 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     @Override74     public void upload(Integer userId, Integer courseId, Integer studyProcess) {75 76         HashOperations<String, String, String> 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 ChengJianSheng
13  * @date 2019-07-26
14  */
15 @Service
16 public class StockServiceImpl implements StockService {
17
18     @Autowired
19     private StringRedisTemplate stringRedisTemplate;
20
21     @Override
22     public int getByProduct(Integer productId) {
23         HashOperations<String, String, String> 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     @Override
32     public boolean decrease(Integer productId) {
33         int stock = getByProduct(productId);
34         if (stock <= 0) {
35             return false;
36         }
37         HashOperations<String, String, String> 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 ChengJianSheng
19  * @date 2019-07-30
20  */
21 @Slf4j
22 @Service
23 public class OrderServiceImpl implements OrderService {
24
25     @Autowired
26     private StockService stockService;
27     @Autowired
28     private OrderRepository orderRepository;
29     @Autowired
30     private RedissonClient redissonClient;
31
32     /**
33      * 乐观锁
34      */
35     @Override
36     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 ChengJianSheng
11  * @date 2019-07-30
12  */
13 @Data
14 @Entity
15 @Table(name = "t_order")
16 public class OrderModel implements Serializable {
17
18     @Id
19     @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_course6 -- ----------------------------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_order
18 -- ----------------------------
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_record
32 -- ----------------------------
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  工程结构

https://github.com/chengjiansheng/cjs-redisson-example

1.5  Redis集群创建

1.6  测试

测试/course/upload

测试/order/create

2.  Spring Integration

用法与Redisson类似

1 <dependency>
2     <groupId>org.springframework.boot</groupId>
3     <artifactId>spring-boot-starter-integration</artifactId>
4 </dependency>
5 <dependency>
6     <groupId>org.springframework.integration</groupId>
7     <artifactId>spring-integration-redis</artifactId>
8 </dependency>
 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 ChengJianSheng
10  * @date 2019-07-30
11  */
12 @Configuration
13 public class RedisLockConfig {
14
15     @Bean
16     public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
17         return new RedisLockRegistry(redisConnectionFactory, "asdf")
18     }
19
20 }
 1 @Autowired2 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         //todo
13
14     } finally {
15         lock.unlock();
16     }
17
18 }

3.  其它

https://github.com/redisson/redisson/wiki/8.-Distributed-locks-and-synchronizers

https://www.cnblogs.com/cjsblog/p/9831423.html

来源:Redisson基本用法 - 废物大师兄 - 博客园 (cnblogs.com)

Redisson基本用法相关推荐

  1. 【redis】redis Redisson 基本用法

    1.概述 转载:https://www.cnblogs.com/cjsblog/p/11273205.html 建议看原文 1. Redisson Redisson是Redis官方推荐的Java版的R ...

  2. 多级缓存分析篇(二) 常用分布式锁分析

    上篇主要讲了日常经常使用的哪些redis包及其配置的差异,这篇对基于redis的分布式锁,主要分享下自定义锁和redisson锁的使用和分析. 1.(自定义)Redis分布式锁 对于redis来说,非 ...

  3. Redisson--使用/教程/实例

    原文网址:Redisson--使用/教程/实例_IT利刃出鞘的博客-CSDN博客 简介 说明         本文用示例介绍Redisson的用法. 官网 官网:https://redisson.or ...

  4. java分布式锁终极解决方案之 redisson

    目前有很多项目还在使用redis的 setNx 充当分布式锁,然而这个锁是有问题的,redisson是java支持redis的redlock的唯一实现,.目前支持集群模式,云托管模式,单Redis节点 ...

  5. Redis进阶- Redisson分布式锁实现原理及源码解析

    文章目录 Pre 用法 Redisson分布式锁实现原理 Redisson分布式锁源码分析 redisson.getLock(lockKey) 的逻辑 redissonLock.lock()的逻辑 r ...

  6. Redisson 分布式锁实现分析(一)

    Why 分布式锁 java.util.concurrent.locks 中包含了 JDK 提供的在多线程情况下对共享资源的访问控制的一系列工具,它们可以帮助我们解决进程内多线程并发时的数据一致性问题. ...

  7. java redisson_Java使用Redisson分布式锁实现原理

    本篇文章摘自:https://www.jb51.net/article/149353.htm 由于时间有限,暂未验证 仅先做记录.有大家注意下哈(会尽快抽时间进行验证) 1. 基本用法 添加依赖 or ...

  8. 分布式锁中的王者方案:Redisson

    我们先来看下 Redis 官网对分布式锁的说法: 而 Java 版的 分布式锁的框架就是 Redisson. 本篇实战内容将会基于我的开源项目 PassJava 来整合 Redisson. 我把后端. ...

  9. 阿里云专访Redisson作者Rui Gu:构建开源企业级Redis客户端之路

    摘要: 本文为阿里云同学在RedisConf2018上对Redisson开源客户端作者Rui Gu做的一个专访,主要介绍了Rui Gu参与开启Redisson客户端开发的历程,同时也详细介绍了Redi ...

最新文章

  1. IE6,7,8中兼容css3圆角问题
  2. 021 设计模式之工厂方法模式,抽象工厂模式的区别
  3. POJ1785(笛卡尔树的构造)
  4. 盘点:最值得托付终身的星座
  5. 51单片机基本刷屏测试实验_基于单片机的发动机振动速度、位移和加速度测量方法...
  6. php设计模式原型模式,原型模式_设计模式_设计模式之原型模式 - Lane Blog
  7. pointer-events:none解决重叠元素不能感应鼠标事件的问题
  8. Java集合之List的equals方法
  9. sa密码不满足强密码要求_恢复丢失的SA密码
  10. hnu 暑期实训之挖掘机技术哪家强
  11. c++语言偶数分离,在C++的链表中分离偶数和奇数节点
  12. SAS安装时出现的问题:Diagram Control
  13. 【数据结构】二叉树经典习题
  14. MacBook Pro 设置Finder显示隐藏文件
  15. 基于51单片机制作超声波避障小车+舵机控制
  16. 如何设置Java环境变量
  17. linux usb 打印机命令
  18. Linux内核学习系列(7)——execve与需求加载
  19. 计算 2 的 1000次方
  20. 粒子动画,做礼物,雪花等特效

热门文章

  1. ༺ཌ༈常见浏览器介绍༈ད༻
  2. 搭建loganalyzer日志分析工具
  3. 7个好用到爆的音频、配乐素材网站,BGM都在这里了
  4. 如何用股票分红接口获取信息?
  5. 基于matlab图像复原技术解析
  6. sql增加字段,修改字段属性,设置字段不为空,设置默认值
  7. 个人收藏之 - 一些有趣网站
  8. Apache配置错误AH00558:无法可靠地确定服务器的标准域名
  9. 计算机游戏手机攻略,吃鸡秘籍排名第一:如何使用稳赢技巧,你不知道的真相在此!...
  10. 【渝粤教育】电大中专药理学基础 (3)作业 题库