使用zookeeper实现分布式锁


使用zk实现分布式锁原理机制:
1.定义锁:在通常的Java开发编程中,有两种常⻅的⽅式可以⽤来定义锁,分别是synchronized机制和JDK5提供的ReentrantLock。然⽽,在ZooKeeper中,没有类似于这样的API可以直接使⽤,⽽是通过 ZooKeepe上的数据节点来表示⼀个锁,例如/base/order_1节点就可以被定义为⼀个锁
2.获取锁:在需要获取排他锁时,所有的客户端都会试图通过调⽤ create()接⼝,在/base节点下创建临时⼦节点/base/order_1。ZooKeeper会保证在所有的客户端中,最终只有⼀个客户端能够创建成功,那么就可以认为该客户端获取了锁。同时,所有没有获取到锁的客户端就需要到/base 节点上注册⼀个⼦节点/base/order_1变更的Watcher监听,以便实时监听到lock节点的变更情况3.释放锁:/base/order_1是⼀个临时节点,因此在以下两种情况下,都有可能释放锁。当前获取锁的客户端机器发⽣宕机,那么ZooKeeper上的这个临时节点就会被移除。正常执⾏完业务逻辑后,客户端就会主动将⾃⼰创建的临时节点删除。⽆论在什么情况下移除了lock节点,ZooKeeper都会通知所有在/base节点上注册了⼦节点/base/order_1变更Watcher监听的客户端。这些客户端在接收到通知后,再次重新发起分布式锁获取,即重复获取锁过程。

引入依赖

		<dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.0.0</version>
        </dependency>

初始化zk链接

@Configuration
public class CuratorConfig {

    @Bean(initMethod = "start")
    CuratorFramework curatorFramework(){
        RetryPolicy exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);
        // 使用fluent编程风格
        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("ip:2181")
                .sessionTimeoutMs(50000)
                .connectionTimeoutMs(30000)
                .retryPolicy(exponentialBackoffRetry)
                .namespace("base")  // 独立的命名空间 /base
                .build();
        return client;
    }
}

使用curator来实现

	@Autowired
    private CuratorFramework curatorFramework;
/**
     * 分布式锁测试实例
     *
     * @return 结果
     */
    public boolean recharge(Integer userId, Integer orderId){
        boolean result = false;
        InterProcessMutex lock = new InterProcessMutex(curatorFramework, "/order_" + orderId);
        try{
            lock.acquire();
            result = accountDomainService.recharge(userId,orderId);
        }catch(Exception e){
            result=false;
            throw new RuntimeException("执行失败");
        }finally {
            try {
                lock.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return result;
    }

使用jemter测试

开了500个线程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看数据库可以知道balance只增加了10,说明500个线程只有一个线程成功增加10,其他线程在发现订单的status是1后就不增加了,分布式锁实现了,也可以自己手动写个实现类,用开篇的思路就可以

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值