分布式锁与计数器‌具体实现

一、ZooKeeper实现(基于Curator框架)

  1. ‌分布式锁实现‌
// 引用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框架)

  1. ‌分布式锁实现‌
// 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)避免手动实现细节。

posted @ 2025-04-24 14:27  an森  阅读(20)  评论(0)    收藏  举报