Redisson之分布式锁解决商品秒杀简单示例

本文通过一个商品秒杀的例子,展示了如何利用Redisson分布式锁解决并发问题,防止同一用户重复下单。在未使用Redisson时,存在重复下单情况;引入Redisson后,通过tryLock()方法确保了并发安全,但在高并发下仍有遗漏,解决方案是使用ConcurrentHashMap或Redis缓存已秒杀成功的用户ID,确保集群部署下的安全性。

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

一般电商商品秒杀活动会面临大量用户同时下单的情况,不仅要面临高并发的问题,还要保证下单数量不超过商品数量和用户对同一商品不能重复下单(保证商品不被同一个用户抢购完,也就是防黄牛)。

面对这些问题,可以采用Redis分布锁来解决,通过Redis中setnx命令来保证同一时间只有一个线程能够正常下单,待订单创建成功后解锁,其余线程再来抢锁。

首先模拟一下未采用Redis加锁的代码实现,创建了3张表:用户表、商品表和订单表

 

 

maven依赖:

<dependencies>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--集成mysql数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!--springboot中的redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!--处理JSON格式-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.17</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot&l
### Redisson分布式锁的优点 Redisson 是一种基于 RedisJava 工具包,提供了多种分布式对象和服务。其分布式锁功能具有以下显著优势: 1. **自动续约机制** 当客户端获取到锁之后,在锁的有效期内如果操作未完成,则 Redisson 会通过内置的任务调度器定期延长锁的过期时间,从而防止因业务逻辑耗时较长而导致锁提前释放的情况发生[^4]。 2. **支持可重入锁** Redisson 提供了 `RLock` 接口来实现可重入锁的功能。这意味着同一个线程可以多次获得同一把锁而不会造成死锁问题。每次加锁都会增加计数器值,解锁则减少计数器值,直到计数值为零时才真正释放锁[^1]。 3. **高可用性和可靠性** 如果持有锁的节点突然宕机或者网络分区导致连接中断,那么其他等待中的节点可以在超时后重新尝试获取该锁,避免因为单点故障引发整个系统的不可用状态。 4. **丰富的特性集** - 支持公平锁(Fair Lock):按照请求顺序分配资源访问权限。 - 支持联锁(MultiLock): 同时锁定多个资源。 - 支持红锁(Redlock): 跨越多个独立实例提供更强的一致性保障[^3]。 --- ### Redisson分布式锁的局限性 尽管 Redisson 分布式锁有许多优点,但也存在一些潜在不足之处需要注意: 1. **依赖外部存储服务** Redisson 锁完全建立在 Redis 数据库之上,因此它的性能表现直接受限于底层 Redis 集群的表现情况。一旦 Redis 出现异常(如全量复制期间延迟增大),可能会影响应用层面对应的操作效率[^2]。 2. **复杂度提升** 对于简单的应用场景来说引入 Redisson 可能会造成不必要的技术栈膨胀,并增加了运维成本比如监控、备份等方面的工作负担。 3. **特定环境下的挑战** 在某些特殊架构环境下(例如 Redis 哨兵模式),可能会遇到诸如脑裂等问题影响正常工作流程。 --- ### 使用场景分析 考虑到上述优劣势对比,以下是适合采用 Redisson 分布式锁的一些典型场景描述: - **高频读写分离数据库表记录更新控制** 如电商秒杀活动商品库存扣减过程需要严格串行化处理以防超卖现象的发生; - **跨服务器间共享资源协调管理** 文件上传下载任务队列分发给不同物理机器执行完毕后再统一汇总结果文件; - **定时任务唯一性保证** 多台机器上运行相同 cronjob 计划程序却只允许其中一台实际触发具体动作以规避重复计算风险。 ```java // 获取锁示例代码片段 import org.redisson.api.RLock; import org.redisson.api.RedissonClient; public class DistributedLockExample { private final RedissonClient redissonClient; public void executeWithLock(String lockKey, Runnable task){ RLock lock = redissonClient.getLock(lockKey); try{ boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS); if(isLocked ){ System.out.println(Thread.currentThread().getName()+" acquired the lock."); // 执行任务... task.run(); System.out.println(Thread.currentThread().getName()+ " finished executing and releasing the lock."); }else{ System.err.println("Failed to acquire lock after waiting..."); } }catch(Exception e){ throw new RuntimeException(e.getMessage(),e ); }finally{ lock.unlock(); } } } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值