首先,假设你已经在项目中引入了Jedis库。下面展示的是一个简化的秒杀务类(`SeckillService`),其中使用Redis分布式锁来保护库存扣减的操作:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class SeckillService {
private static final String REDIS_LOCK_KEY = "seckill_lock";
private static final int LOCK_EXPIRE_TIME_SECONDS = 60; // 锁过期时间,可根据实际需求调整
private final Jedis jedis; // 假设已经正确初始化Jedis客户端
public boolean seckill(String userId, String productId) {
// 尝试获取分布式锁
String lockValue = UUID.randomUUID().toString();
long acquireLockResult = jedis.set(REDIS_LOCK_KEY, lockValue, SetParams.setParams().nx().px(LOCK_EXPIRE_TIME_SECONDS * 1000));
if (acquireLockResult == 1) { // 获取锁成功
try {
// 执行秒杀逻辑(如扣除库存、生成订单等)
boolean seckillSuccess = doSeckill(userId, productId);
return seckillSuccess;
} finally {
// 无论如何,都要释放锁
String currentValue = jedis.get(REDIS_LOCK_KEY);
if (currentValue != null && currentValue.equals(lockValue)) {
jedis.del(REDIS_LOCK_KEY);
}
}
} else {
// 获取锁失败,可能是其他客户端已经持有锁,返回秒杀失败
return false;
}
}
private boolean doSeckill(String userId, String productId) {
// 实际的秒杀逻辑,如检查库存、扣除库存、生成订单等
// 这里仅做示例,返回一个随机的成功或失败结果
return Math.random() < 0.5; // 50%的成功概率
}
}
在这个示例中:
1. 定义了一个全局唯一的Redis键`REDIS_LOCK_KEY`作为分布式锁的标识。
2. 使用`Jedis.set()`方法(配合`SetParams.nx().px()`参数)尝试获取分布式锁。`nx`表示只有当键不存在时才设置值(保证互斥性),`px`设置锁的过期时间(防止死锁)。
3. 如果成功获取锁(`set()`方法返回`1`),则执行秒杀逻辑(`doSeckill()`方法)。这里只是一个简单的示例,实际应用中应包含检查库存、扣除库存、生成订单等操作。
4. 在`finally`块中,无论秒杀是否成功,都必须释放锁。通过检查当前锁值是否与获取锁时设置的值相等来确保不会误删其他客户端的锁。相等则删除键(释放锁)。
5. 如果获取锁失败(`set()`方法返回`0`),则直接返回秒杀失败,避免继续执行秒杀逻辑。