分布式锁在分布式系统中非常重要,主要用于解决多个进程/服务并发访问共享资源时的数据一致性问题。在日常开发中常用于:
1. 防止重复操作(幂等性控制)
场景:用户重复提交订单、重复支付、重复点击等。
示例:
用户快速点击“提交订单”按钮时,用 订单ID + 用户ID 作为锁的Key,确保同一订单不会被重复处理。2. 秒杀/抢购(库存扣减)
场景:高并发下扣减库存,防止超卖。
3. 定时任务调度(避免多实例重复执行)
场景:集群环境下,确保定时任务(如每天报表生成)只由一个节点执行。
4. 分布式系统并发控制
场景:多个服务实例同时操作共享资源(如文件、配置、数据库行)。
示例:
多个节点同时修改同一份配置文件时,通过分布式锁确保串行化修改。5. 缓存击穿保护
场景:高并发下缓存失效时,防止大量请求直接穿透到数据库。
6. 全局唯一流水号生成
场景:分布式系统中生成唯一订单号、交易号等。
示例:
通过锁保护Redis/LDB的自增序列,避免号段重复。7. 分布式事务协调
场景:在Saga、TCC等分布式事务模式中,作为协调资源竞争的手段。
Redission的使用
1.引入依赖:
<!--使用redisson作为所有分布式锁,分布式对象等功能框架-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.0</version>
</dependency>
2.完成配置,与Redis服务器建立连接:
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.IOException;/*** @author* @Desc:redisson配置* @create: 2024-06-08 17:54**/
@Configuration
public class MyRedissonConfig {@Bean(destroyMethod = "shutdown")public RedissonClient redisson()throws IOException{Config config=new Config();config.useSingleServer().setAddress("redis://192.168.56.10:6379");return Redisson.create(config);}
}
上面代码中@Bean(destroyMethod="shutdown"),destroyMethod="shutdown" 起到作用为:当Spring容器关闭时,会自动调用RedissonClient实例的shutdown()
方法来优雅地关闭Redisson客户端连接,关闭与Redis服务器的连接,释放所有相关资源,避免资源泄漏。
3.使用,在需要使用Redission的地方,使用注解完成资源注入:
@Autowiredprivate RedissonClient redissonClient;
具体使用示例:
@Autowiredprivate RedissonClient redissonClient;public static final String UPLOAD_LOCK = "seckill:upload:lock";// 每隔5秒执行一次@Scheduled(cron = "*/5 * * * * ?")public void uploadSeckillSkuLatest3Days() {log.info("上架最近三天的秒杀商品");// 加上分布式锁,避免多个定时任务同时执行RLock lock = redissonClient.getLock(UPLOAD_LOCK);// 最多等待10秒,上锁成功,则执行秒杀商品上架逻辑lock.lock(10, TimeUnit.SECONDS);try {seckillSkuService.uploadSeckillSkuLatest3Days();} finally {lock.unlock();}}
上面代码中有2处需特别注意:
1.上锁时间,等待时间,需结合业务代码执行时间进行设置,比业务代码执行时间多出1~2秒;
2. 在finally代码块中释放锁,无论执行成功与否或有异常产生,都要释放锁,防止出现死锁。
拓展
1.技术选型建议
-
Redis(Redisson):性能高,适合大多数场景(推荐)。
-
Zookeeper:强一致性,适合对可靠性要求极高的场景。
-
数据库乐观锁/悲观锁:简单但性能较差,适合低频竞争场景。
2.注意事项
-
锁的粒度:尽量细粒度(例如按订单ID锁,而非全局锁)。
-
超时时间:避免死锁,设置合理的超时(Redisson默认30秒)。
-
可重入性:确保锁支持同一线程重入(Redisson的
RLock
支持)。 -
容错性:考虑Redis集群故障时的降级方案(如本地锁+告警)。
分布式锁是分布式系统的核心基础组件,合理使用能有效解决并发冲突问题。