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关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?