003-Zk使用场景

场景

注册中心

因为是树结构
且能动态感知到服务上线下线

提供者注册子节点
消费者监听父节点

Dubbo
接口
提供者
提供者ip
消费者
消费者ip

分布式节点名称

dns域名解析

服务创建后就创建zk临时节点

域名
ip

分布式ID生成器

  1. 有序节点 少量低并发(zk底层是同步按顺序生成的)
  2. 维护雪花算法的一部分内容
    雪花算法 是4部分组成:
    保留位
    时间戳 : 精确到毫秒
    机器id : zk维护
    序列号

分布式锁

高可用且并发量不太高的情况下
Redis可能有琐失效的问题,主节点加锁后挂掉锁就丢失了
zk是主节点会半数同步从节点后回复客户端

加锁:
创建临时节点
获取锁失败:
监听节点,并等待,可以借助锁的加锁和解锁实现

但是这样唤醒可能会出现线程饥饿问题
可以借助临时有序节点实现

加锁线程都创建有序的临时节点
然后比较最小的节点先获取锁

获取锁失败的线程:
监听前边的临时节点,如:02监听01,03监听02,01监听00
如果临时节点解锁后就一次唤醒节点

Curator框架提供了可重入的互斥锁

和redis锁有不同的是zk锁不能设置超时时间,但是zk锁没有如果机器意外挂掉,锁还要等待超时时间到了才能取消的问题,因为临时节点的特性

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>5.2.0</version>
        </dependency>
//加锁解锁
    private void lockBizDue() {
        InterProcessMutex lock = null;
        try {
            String lockKey = "lock/biz_code";
            //System.out.println("加锁");
            lock = this.lock(lockKey);
            this.bizDue();
        } catch (Exception e) {
            System.out.println("业务处理异常-异常为:" + Throwables.getStackTraceAsString(e));
        } finally {
            try {
                if (lock != null) {
                    lock.release();
                }
            } catch (Exception e) {
                System.out.println("解锁异常-异常为:" + Throwables.getStackTraceAsString(e));
            }
        }
    }

    //业务处理
    private void bizDue() {
        System.out.println("业务处理");
        this.count ++;
    }

    //创建zkClient
    private void buildCurator() {
        CuratorFramework curator = CuratorFrameworkFactory.builder()
                //.aclProvider(aclProvider)//防止其它操作误操作节点,加上权限限制
                //.authorization(authScheme, id.getBytes())//防止其它操作误操作节点,加上权限限制
                .connectString(connectString)//zk连接串
                .sessionTimeoutMs(Integer.parseInt(sessionTimeoutMs))//session 超时时间
                .connectionTimeoutMs(Integer.parseInt(connectionTimeoutMs)).defaultData("0".getBytes())//连接zk超时时间
                .retryPolicy(new ExponentialBackoffRetry(Integer.parseInt(baseSleepTimeMs), Integer.parseInt(maxRetries)))//连接zk重试次数以及重试间隔时间
                .maxCloseWaitMs(Integer.parseInt(maxCloseWaitMs))//关闭连接等待时间
                .build();
        curator.start();
        this.curatorFramework = curator;
        System.out.println("client已完成初始化");
    }

    //创建可重入锁
    private InterProcessMutex lock(String lockKey) throws Exception {
        //临时顺序节点的根节点
        String lockPath = "/lock1/" + lockKey;

        //申明可重入锁
        InterProcessMutex lock = new InterProcessMutex(curatorFramework, lockPath);

        //这里的acquire方法是阻塞方法,超时时间是3分钟
        if (lock.acquire(3, TimeUnit.MINUTES)) {
            //System.out.println("节点列表>>>" + lock.getParticipantNodes());
            Stat stat = curatorFramework.checkExists().forPath(lockPath);
            if (null != stat) {
                //System.out.println(lockPath + "节点信息>>>" + JSON.toJSONString(stat));
            }
        }
        //返回lock,说明成功获取到锁
        return lock;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值