分布式锁与计数器具体实现
一、ZooKeeper实现(基于Curator框架)
- 分布式锁实现
// 引用Curator框架实现分布式锁(代码来自:ml-citation{ref="1,2" data="citationList"})
public class ZkDistributedLock {
private static final String LOCK_PATH = "/locks/resource_lock";
private InterProcessMutex lock;
public ZkDistributedLock(CuratorFramework client) {
this.lock = new InterProcessMutex(client, LOCK_PATH);
}
public void doTaskWithLock() throws Exception {
if (lock.acquire(3, TimeUnit.SECONDS)) { // 尝试获取锁,超时3秒:ml-citation{ref="2" data="citationList"}
try {
// 业务逻辑(如库存扣减)
System.out.println("Lock acquired, processing task...");
} finally {
lock.release(); // 释放锁:ml-citation{ref="1" data="citationList"}
}
}
}
public static void main(String[] args) {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.1.171:2181", retryPolicy);
client.start();
new ZkDistributedLock(client).doTaskWithLock();
}
}
关键点:
使用InterProcessMutex实现互斥锁,支持可重入和自动续期。
通过acquire()方法设置超时时间,避免死锁。
2. 分布式计数器实现
// 基于ZooKeeper版本号的计数器实现(参考:ml-citation{ref="2" data="citationList"}原理)
public class ZkDistributedCounter {
private static final String COUNTER_PATH = "/counters/resource_counter";
private CuratorFramework client;
public ZkDistributedCounter(CuratorFramework client) {
this.client = client;
}
public void increment() throws Exception {
while (true) {
Stat stat = new Stat();
byte[] data = client.getData().storingStatIn(stat).forPath(COUNTER_PATH);
int currentValue = Integer.parseInt(new String(data));
currentValue++;
try {
client.setData().withVersion(stat.getVersion()).forPath(COUNTER_PATH, String.valueOf(currentValue).getBytes());
break;
} catch (KeeperException.BadVersionException e) {
// 版本冲突,重试:ml-citation{ref="2" data="citationList"}
}
}
}
}
关键点:
通过节点版本号(withVersion())实现原子性更新。
使用循环重试机制解决并发冲突。
二、Redis实现(基于Redisson框架)
- 分布式锁实现
// Redisson实现分布式锁(参考:ml-citation{ref="3,5" data="citationList"})
public class RedisDistributedLock {
private RedissonClient redissonClient;
public RedisDistributedLock() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
this.redissonClient = Redisson.create(config);
}
public void doTaskWithLock() {
RLock lock = redissonClient.getLock("resource_lock");
try {
if (lock.tryLock(3, 30, TimeUnit.SECONDS)) { // 等待3秒,锁持有30秒:ml-citation{ref="3,5" data="citationList"}
// 业务逻辑(如订单处理)
System.out.println("Lock acquired, processing task...");
}
} finally {
lock.unlock(); // 释放锁:ml-citation{ref="5" data="citationList"}
}
}
}
关键点:
通过tryLock()支持超时等待和自动续期。
Redisson内置看门狗机制,防止任务未完成时锁过期。
2. 分布式计数器实现
// Redis原子计数器(参考:ml-citation{ref="3,4" data="citationList"})
public class RedisDistributedCounter {
private Jedis jedis;
public RedisDistributedCounter() {
this.jedis = new Jedis("127.0.0.1", 6379);
}
public long increment(String key) {
return jedis.incr(key); // 原子性递增:ml-citation{ref="3,4" data="citationList"}
}
public long decrement(String key) {
return jedis.decr(key); // 原子性递减:ml-citation{ref="3" data="citationList"}
}
}
关键点:
使用INCR和DECR命令实现原子操作。
无需额外事务,Redis单线程模型保证操作原子性。
三、实现对比与选型建议
维度 ZooKeeper(Curator) Redis(Redisson)
锁实现复杂度 需处理临时节点和监听机制 简单,依赖客户端框架(如Redisson)
计数器性能 低(依赖版本号循环重试) 高(单线程原子操作)
适用场景 强一致性场景(如金融交易) 高并发场景(如秒杀系统)
建议:
强一致性需求选择ZooKeeper,高并发场景选择Redis。
优先使用成熟框架(如Curator、Redisson)避免手动实现细节。
浙公网安备 33010602011771号