千家信息网

如何使用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 ThreadLocal threadLocal = 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 以及分布式锁"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0