一、背景与需求分析
1.1 分布式锁的重要性
分布式锁:在分布式系统中,多个节点需要对共享资源进行互斥访问,防止并发冲突(如库存超卖)。
Redis的角色:通过原子操作(如SET NX)实现高效分布式锁。
分布式锁在高并发场景下确保数据一致性和系统稳定性。
1.2 高并发场景需求
场景:电商库存扣减系统,处理商品库存更新,日活1000万,QPS 10万。
功能需求:
互斥访问:确保同一商品库存扣减的线程安全。
高性能:锁获取和释放延迟<1ms。
高可用:锁机制支持故障恢复。
防死锁:避免锁未释放导致系统阻塞。
非功能需求:
性能:P99延迟<10ms,吞吐量10万QPS。
可用性:99.99%(宕机<52分钟/年)。
资源效率:CPU利用率<80%,内存<16GB/节点。
可监控性:锁获取时间、冲突率实时监控。
数据量:
商品:1000万,单条库存约100B。
日请求:1亿(10万QPS × 3600s × 24h)。
锁冲突率:<0.1%。
1.3 技术挑战
锁正确性:确保互斥性,避免超卖。
性能:锁获取/释放低延迟。
死锁:防止锁未释放。
高可用:Redis故障场景下的锁可靠性。
监控:定位锁冲突和性能瓶颈。
1.4 目标
性能:P99延迟<10ms,QPS 10万。
稳定性:CPU/内存<80%,99.99%可用性。
正确性:零超卖,锁冲突率<0.1%。
可维护性:清晰锁逻辑,实时监控。
成本:单节点<0.01美元/QPS。
1.5 技术栈
组件技术选择优点
编程语言Java 21性能优异、生态成熟
框架Spring Boot 3.3集成Spring Data Redis
数据库Redis 7.2原子操作、高性能
客户端Lettuce 6.4异步、响应式支持
监控Micrometer + Prometheus 2.53实时指标、集成Grafana
日志SLF4J + Logback 1.5高性能、异步日志
容器管理Kubernetes 1.31自动扩缩容、高可用
CI/CDJenkins 2.426自动化部署
二、Redis分布式锁原理
2.1 分布式锁基本概念
定义:分布式锁允许多个节点互斥访问共享资源,通过一个中心化存储(如Redis)协调。
核心要求:
互斥性:同一时刻只有一个客户端持有锁。
可重入性(可选):同一客户端可多次获取锁。
防死锁:锁需自动过期。
高可用:锁服务需容错。
高效性:低延迟、高吞吐。
2.2 Redis实现分布式锁
Redis通过SET NX EX命令实现分布式锁:
命令:SET key value NX EX seconds
NX:仅在键不存在时设置(确保互斥)。
EX:设置过期时间(防死锁)。
value:唯一标识客户端(防止误释放)。
流程:
获取锁:
SET lock:product:456 "client1-uuid" NX EX 10
AI生成项目
redis
public boolean acquireLock(RedisTemplate<String, String> redisTemplate, String lockKey, String clientId, long expireSeconds) {
return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, expireSeconds, TimeUnit.SECONDS));
}
public void releaseLock(RedisTemplate<String, 16String.boats> redisTemplate, String lockKey, String clientId) {
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), List.of(lockKey), clientId);
}
返回OK表示获取成功。
执行业务:如扣减库存。
释放锁:使用Lua脚本确保原子性。
EVAL "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock:product:456 client1-uuid
AI生成项目
redis
public boolean acquireLockWithRetry(RedisTemplate<String, String> redisTemplate, String lockKey, String clientId, long expireSeconds, int ret6.boats, long retryIntervalMs) {
for (int i = 0; i < retries; i++) {
if (acquireLock(redisTemplate, lockKey.boats, clientId, expireSeconds)) {
return true;
}
Thread.sleep(retryIntervalMs);
}
return false;
}
复杂度:
获取/释放:O(1)。
网络延迟:约0.1-1ms。
2.3 锁的正确性
互斥性:SET NX保证单一客户端持有锁。
防死锁:EX设置过期时间。
安全释放:Lua脚本校验客户端标识。
可扩展性:Redis单实例支持10万QPS。