1. Redisson
Redisson是Redis官方推荐的Java版的Redis客户端。它提供的功能非常多,也非常强大,此处我们只用它的分布式锁功能。
https://github.com/redisson/redisson
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: 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 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)) {
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 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
关注
打赏
热门博文
- ArrayList c.toArray might (incorrectly) not return Object[] (see 6260652)
- Spring框架实体bean转json返回前端报错:Null key for a Map not allowed in JSON (use a converting NullKeySerializer
- python将数据写入txt文本文件
- Python学习随笔:使用xlwings读取和操作Execl文件
- org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized t
- ‘gbk‘ codec can‘t decode byte 0x80 in position 2: illegal multibyte sequence
- SyntaxError: (unicode error) ‘unicodeescape‘ codec can‘t decode bytes in position 2-3: truncated \UX
- 关于Mybatis中keyProperty属性
- 解决 Mybatis 报错 org.apache.ibatis.ognl.NoSuchPropertyException: XXXCriteria$Criterion.noValue
- mysql报错 is longer than the server configured value of ‘wait_timeout‘
