单机环境用synchronized就够了,分布式环境就需要分布式锁。
这篇对比Redis和Zookeeper两种方案,分享实战经验。
一、什么场景需要分布式锁?
- 防止重复操作:用户快速点击两次下单
- 库存扣减:防止超卖
- 定时任务:集群中只有一个节点执行
- 分布式限流:全局计数
二、Redis分布式锁
2.1 基本实现
public class RedisLock {
private StringRedisTemplate redisTemplate;
/**
* 加锁
*/
public boolean lock(String key, String value, long expireTime) {
Boolean result = redisTemplate.opsForValue()
.setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
return Boolean.TRUE.equals(result);
}
/**
* 解锁(必须用Lua脚本保证原子性)
*/
public boolean unlock(String key, String value) {
String script =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
Long result = redisTemplate.execute(
new DefaultRedisScript<>(script, Long.class),Collections.singletonList(key),value);return Long.valueOf(1).equals(result);}}
2.2 使用示例
public void doSomething() {
String lockKey = "lock:order:123";
String lockValue = UUID.randomUUID().toString();
try {
// 加锁
boolean locked = redisLock.lock(lockKey, lockValue, 30000