如何使用springboot集成redission 以及分布式锁
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,本篇内容主要讲解"如何使用springboot集成redission 以及分布式锁",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何使用springboo
千家信息网最后更新 2025年02月04日如何使用springboot集成redission 以及分布式锁
本篇内容主要讲解"如何使用springboot集成redission 以及分布式锁",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何使用springboot集成redission 以及分布式锁"吧!
目录
springboot集成redission及分布式锁的使用
1、引入jar包
2、增加Configuration类
3、使用redission分布式锁
Springboot整合Redisson 锁
一、依赖
二、配置文件
三、锁的使用
四、分布式秒杀
五、redis锁 单机版可用,分布式用Redisson
springboot集成redission及分布式锁的使用
1、引入jar包
org.redisson redisson 3.13.4
2、增加Configuration类
@Configurationpublic class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Value("${spring.redis.password}") private String password; @Bean public RedissonClient getRedisson() { Config config = new Config(); config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password); return Redisson.create(config); }}
3、使用redission分布式锁
@Autowiredprivate RedissonClient redissonClient;
//方法区String key = "aa:bb:cc:01";RLock rLock =redissonClient.getLock(key);try{
// 尝试加锁,最多等待1秒,上锁以后10秒自动解锁
// 没有Watch Dog ,10s后自动释放boolean res = rLock.tryLock(1,10, TimeUnit.SECONDS);if(!res){ return new GeneralVO<>(400, "请勿重复提交", false);}}finally{ rLock.unlock();}
private void redissonDoc() throws InterruptedException { //1. 普通的可重入锁 RLock lock = redissonClient.getLock("generalLock"); // 拿锁失败时会不停的重试 // 具有Watch Dog 自动延期机制 默认续30s 每隔30/3=10 秒续到30s lock.lock(); // 尝试拿锁10s后停止重试,返回false // 具有Watch Dog 自动延期机制 默认续30s boolean res1 = lock.tryLock(10, TimeUnit.SECONDS); // 拿锁失败时会不停的重试 // 没有Watch Dog ,10s后自动释放 lock.lock(10, TimeUnit.SECONDS); // 尝试拿锁100s后停止重试,返回false // 没有Watch Dog ,10s后自动释放 boolean res2 = lock.tryLock(100, 10, TimeUnit.SECONDS); //2. 公平锁 保证 Redisson 客户端线程将以其请求的顺序获得锁 RLock fairLock = redissonClient.getFairLock("fairLock"); //3. 读写锁 没错与JDK中ReentrantLock的读写锁效果一样 RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock"); readWriteLock.readLock().lock(); readWriteLock.writeLock().lock();}
Springboot整合Redisson 锁
Redisson是一个在Redis的基础上实现的Java驻内存数据网格
一、依赖
org.redisson redisson 3.15.4
二、配置文件
spring: redis: database: 7 host: 116.62.178.11 port: 6379 password: 1234qwer # spring-boot 1.0默认 jedis; spring-boot2.0 默认lettuce ,lettuce线程安全 lettuce: pool: # 连接池中的最大空闲连接 默认8 max-idle: 8 # 连接池中的最小空闲连接 默认0 min-idle: 500 # 连接池最大连接数 默认8 ,负数表示没有限制 max-active: 2000 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认-1 max-wait: -1 cache: type: redis
@Configurationpublic class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String password; @Bean(destroyMethod = "shutdown") RedissonClient redissonClient() throws IOException { Config config = new Config(); config.useSingleServer() .setPassword(password) .setAddress("redis://" + host + ":" + port).setDatabase(7); return Redisson.create(config); }}
三、锁的使用
读写锁
public class RedissionDemo { @Autowired private RedissonClient redissonClient; @Autowired private RedisTemplate redisTemplate; /** * 读写锁 总结 * * 读锁又叫共享锁 * 写锁又叫排他锁(互斥锁) * 读 + 读 相当于无锁,并发读,同时加锁成功 * 写 + 写 阻塞状态 * 写 + 读 等待写锁释放 * 读 + 写 等待读锁完,才写, */ public String writeValue() { String str = ""; RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("writeLock"); RLock rLock = readWriteLock.writeLock(); try { rLock.lock(); str = UUID.randomUUID().toString(); redisTemplate.opsForValue().set("uuid", str); Thread.sleep(30000); } catch (Exception e) { } finally { rLock.unlock(); } return str; } /** * 读锁 * * @return */ public String readValue() { String str = ""; RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("writeLock"); RLock rLock = readWriteLock.readLock(); rLock.lock(); str = (String) redisTemplate.opsForValue().get("uuid"); rLock.unlock(); return str; } }
信号量
public class RedissionDemo { @Autowired private RedissonClient redissonClient; @Autowired private RedisTemplate redisTemplate; /** * 信号量 * * @return */ //停车方法 @GetMapping("/park") public String park() throws InterruptedException { //这里是获取信号量的值,这个信号量的name一定要与你初始化的一致 RSemaphore park = redissonClient.getSemaphore("park"); //这里会将信号量里面的值-1,如果为0则一直等待,直到信号量>0 park.acquire(); //tryAcquire为非阻塞式等待 //park.tryAcquire(); return "ok"; } public String go() throws InterruptedException { //这里是获取信号量的值,这个信号量的name一定要与你初始化的一致 RSemaphore park = redissonClient.getSemaphore("park"); //这里会将信号量里面的值+1,也就是释放信号量 park.release(); return "ok"; }}
闭锁
public class RedissionDemo { @Autowired private RedissonClient redissonClient; @Autowired private RedisTemplate redisTemplate; /** * 闭锁,限流 * * @return * @throws InterruptedException */ //锁门 public String lockdoor() throws InterruptedException { RCountDownLatch door = redissonClient.getCountDownLatch("door"); //设置一个班级有20个同学 door.trySetCount(20); //需要等到20个同学全部离开,才锁门 door.await(); return "锁门了"; } public String leave(Long id) throws InterruptedException { RCountDownLatch door = redissonClient.getCountDownLatch("door"); //表示一个同学离开 door.countDown(); return "" + id + "号同学离开了"; }}
四、分布式秒杀
秒杀流程:
@Service@Slf4jpublic class DistributedSecKillBiz { @Autowired private RedisTemplate redisTemplate; @Autowired private RedissonClient redissonClient; /** * 分布式锁。唯一缺点 枷锁失效时间 * 枷锁院子操作, * 解锁,删除锁也是原子操作 瑕疵没有续命 * * @return */ public String doKill() { String lock = UUID.randomUUID().toString(); String goodsId = "10054"; boolean flag = redisTemplate.opsForValue().setIfAbsent(goodsId, lock, 30, TimeUnit.SECONDS); if (flag) { // 获取锁成功 try { Long stock = redisTemplate.opsForValue().decrement(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId); if (stock > 0) { redisTemplate.opsForValue().increment(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId); log.info("扣减库存成功,还剩:" + stock); } return "库存不足,该商品已抢购完!"; } catch (Exception e) { } finally { String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"; redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(goodsId), lock); } } return doKill(); } /** * 整合 redission * @return */ public String doKillDistributed() { String goodsId = "10054"; RLock lock = redissonClient.getLock(upActivityKey() + SecKillConstant.LOCK + goodsId); // 获取锁成功 try { //1 阻塞式等待,默认30秒时间 //2 自动续期,如果业务超长,续上新的30秒,不用担心过期时间,锁自动删除掉 //3 枷锁的业务运行完成,就不会给当前的锁自动续期,即使没有手动释放锁也会,30秒自动释放// lock.lock(30, TimeUnit.SECONDS); //不会自动续期需要注意 lock.lock(); Long stock = redisTemplate.opsForValue().decrement(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId); if (stock > 0) { redisTemplate.opsForValue().increment(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId); log.info("扣减库存成功,还剩:" + stock); } return "库存不足,该商品已抢购完!"; } catch (Exception e) { } finally { lock.unlock(); } return "fail"; } /** * 获取活动 * * @return */ public ActivityBo upActivity() { return new ActivityBo("七夕活动", "SEVEN_ACTIVITY", new Date(), new Date()); } /** * 活动公共key * * @return */ public String upActivityKey() { return SecKillConstant.SEC_KILL + upActivity().getActivityKey() + ":"; }}
五、redis锁 单机版可用,分布式用Redisson
package com.yang.yimall.seckill.app.seckill.biz;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.script.DefaultRedisScript;import org.springframework.stereotype.Service;import java.util.Collections;import java.util.UUID;import java.util.concurrent.TimeUnit;/** * redis 锁 集群有瑕疵 不能 续命 */@Servicepublic class RedisLock { @Autowired private RedisTemplate redisTemplate; private String lockName = "lockName"; private ThreadLocalthreadLocal = new ThreadLocal<>(); public void lock(String lockName) { if (tryLock(lockName)) { return; } lock(lockName); } public void lock() { if (tryLock(lockName)) { return; } lock(); } /** * 添加key 并且设置过期时间 原子操作 * * @param lockName * @return */ public boolean tryLock(String lockName) { String uuid = UUID.randomUUID().toString(); threadLocal.set(uuid); return redisTemplate.opsForValue().setIfAbsent(lockName, uuid, 30, TimeUnit.SECONDS); } /** * 如果查询有key,就删除, 原子操作 */ public void unlock() { String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"; redisTemplate.execute(new DefaultRedisScript (script, Long.class), Collections.singletonList(lockName), threadLocal.get()); }}
使用
public String doKillUp() { String goodsId = "10054"; redisLock.lock(goodsId); // 获取锁成功 try { Long stock = redisTemplate.opsForValue().decrement(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId); if (stock > 0) { redisTemplate.opsForValue().increment(upActivityKey() + SecKillConstant.CACHE_FOODS_COUNT + goodsId); log.info("扣减库存成功,还剩:" + stock); } return "库存不足,该商品已抢购完!"; } catch (Exception e) { } finally { redisLock.unlock(); } return "库存不足,该商品已抢购完!"; }
到此,相信大家对"如何使用springboot集成redission 以及分布式锁"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
分布式
信号
信号量
成功
库存
时间
同学
商品
阻塞
最大
原子
方法
枷锁
尝试
整合
活动
一致
业务
内容
单机
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
面向对象数据库技术难吗
宏杉科技服务器aa
市北区分销软件开发哪家做的好
excel做图片数据库
广西华圣互联网科技有限公司
暑假网络安全注意事项
网络安全教育张莉
杭州美容店软件开发
无线网络技术导论试卷
多久能学会软件开发
服务器装显卡有什么作用
胡桃复刻挤爆服务器
沐瑶部落文件服务器
网络安全活动周计划
我市网络安全宣传活动启动
2020年度网络安全工作
服务器清理向导怎么启动
网络技术方向包括的课程
互联网时代的科技公司
东航合同系统软件开发实施项目
黄梅容易就业的计算机软件开发
郑州 股指软件开发
打造智慧校园软件开发
计算机软件开发税率多少
天津ai服务器批发
应用软件开发个体户
榆林软件开发服务价格
时间和时间序列数据库
利用数据库配置生成枚举
请将数据库按照内容