Redisson-MultiLock使用

本文介绍了在单机Redis环境下,如何利用Redisson实现多维度、分布式、原子性的批量加锁。通过SpringBoot整合Redisson,创建MultiLockService进行加锁操作,并在业务测试类中演示了加锁、解锁流程,证明了Redisson的multiLock支持批量加锁并保证原子性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境说明
由于测试条件有限以下测试都是使用的单机redis,官方推荐使用红锁是需要5台master。

背景说明:
最近的电商项目C端用户在购买商品时可以使用多种货币(余额、券、卡、积分)支付,同时B端商户也可以多这些货币进行管理(如 余额撤回、卡券作废、充值卡作废等),为了保证金额的安全问题,那么首选考虑的就是加锁,但是由于是多种货币可以同时使用且要保证则加锁得多维度批量加锁、支持分布式(B端和C端是在不同服务中)、保证批量加锁的原子性。
基于以上分析和考虑,则选用了Redisson的multiLock。

代码实现(springboot+redis):
pom依赖

        <!-- 导入 redission 依赖 -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.16.4</version>
        </dependency>

RedissonConfig(配置类):

@Configuration
public class RedissonConfig {

    /**
     * 单Redis节点模式配置方法
     * 其他配置參數,看:
     *
     * @return
     */
    @Bean
    public RedissonClient redisson() {
        Config config = new Config();
        //单机模式  依次设置redis地址和密码
        config.useSingleServer().setAddress("redis://192.168.40.130:6379").setPassword("123456");
        return Redisson.create(config);
    }

}

MultiLockService(加锁类):

@Component
public class MultiLockService {

    @Autowired
    private RedissonClient redissonClient;

    public RLock tryMultiLock(List<String> list){
        List<RLock> locks = new ArrayList<>();
        list.forEach(key ->{
            RLock rLock = redissonClient.getLock(key);
            locks.add(rLock);
        });
        RLock[] array = locks.stream().toArray(RLock[]::new);
        RLock multiLock = redissonClient.getMultiLock(array);
        boolean isLook = multiLock.tryLock();
        if(isLook){
            return multiLock;
        }
        return null;
    }
}

TestService(业务测试类)

@Component
@Slf4j
public class TestService {
    @Autowired
    private MultiLockService lockService;

    @Async
    public void multiLock(){
        log.info("multiLock 尝试加锁...lock1、lock2、lock3");
        List<String> list = new ArrayList<>();
        list.add("lock1");
        list.add("lock2");
        list.add("lock3");
        //加锁
        RLock multiLock = lockService.tryMultiLock(list);
        if(Objects.nonNull(multiLock)){
            log.info("multiLock 加锁成功,多锁为:lock1、lock2、lock3");
            try {
                Thread.sleep(5000);
            }catch (Exception e){
                log.error("休眠异常",e);
            } finally {
                log.info("multiLock 开始解锁...");
                multiLock.unlock();
            }
        } else {
            log.info("multiLock 尝试加锁失败...");
        }
    }

    @Async
    public void tryLock(){
        log.info("tryLock 尝试加锁...lock3、lock4、lock5");
        List<String> list = new ArrayList<>();
        list.add("lock3");
        list.add("lock4");
        list.add("lock5");
        //加锁
        RLock multiLock = lockService.tryMultiLock(list);
        if(Objects.nonNull(multiLock)){
            log.info("tryLock 加锁成功,多锁为:lock3、lock4、lock5");
            try {
                Thread.sleep(20000);
            }catch (Exception e){
                log.error("休眠异常",e);
            }finally {
                log.info("multiLock 开始解锁...");
                multiLock.unlock();
            }
        } else {
            log.info("tryLock 尝试加锁失败...");
        }
    }
}

测试步骤:

  1. 先执行multiLock()方法批量加锁 (lock1、lock2、lock3),在执行multiLock()加锁成功后5s内执行tryLock()尝试批量加锁(lock3、lock4、lock5),由于multiLock()中已经有lock3则tryLock批量加锁会全部失败,此时redis中会有3个key(lock1、lock2、lock3);
  2. 等待5s后multiLock()会执行解锁(此时redis中3个key也会同时被删掉),再执行tryLock()尝试批量加锁(lock3、lock4、lock5),则会加锁成功,此时redis中会有3个key(lock3、lock4、lock5);
  3. multiLock()加锁后等待10s,则会做解锁操作,同时redis中key(lock3、lock4、lock5)会删掉。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以上说明Redission的multiLock是完全支持批量加锁,并能保证批量加锁时的原子性(业务是在redis中用lua脚本实现);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值