栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

zookeeper实现分布式锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

zookeeper实现分布式锁

1.四种方法保证数据安全

分布式锁 保证分布式领域中共享数据安全问题

1、数据库实现(效率低,不推荐)

2、redis实现(使用redission实现,但是需要考虑思索,释放问题。繁琐一些)

3、Zookeeper实现 (使用临时节点,效率高,失效时间可以控制)

4、Spring Cloud 实现全局锁(内置的)

2.应用场景

在分布式情况,生成全局订单号ID

3.什么是分布式锁

分布式锁一般用在分布式系统或者多个应用中,用来控制同一任务是否执行或者任务的执行顺序。在项目中,部署了多个tomcat应用,在执行定时任务时就会遇到同一任务可能执行多次的情况,我们可以借助分布式锁,保证在同一时间只有一个tomcat应用执行了定时任务

4.实现Zookeeper分布式锁流程
  • 客户端连接上zookeeper,并在指定节点(locks)下创建临时顺序节点node_n
  • 客户端获取locks目录下所有children节点
  • 客户端对子节点按节点自增序号从小到大排序,并判断自己创建的节点是不是序号最小的,若是则获取锁;若不是,则监听比该节点小的那个节点的删除事件
  • 获得子节点变更通知后重复此步骤直至获得锁;
  • 执行业务代码,完成业务流程后,删除对应的子节点释放锁。
5.两种方式实现分布式锁 5.1原生方式

使用java和zk api书写以上逻辑实现分布式锁,操作zookeeper使用的是apache提供的zookeeper的包。通过实现Watch接口,实现process(WatchedEvent event)方法来实施监控,使CountDownLatch来完成监控,在等待锁的时候使用CountDownLatch来计数,等到后进行countDown,停止等待,继续运行。

5.2 Curator方式

Curator是Netflix公司一个开源的zookeeper客户端,在原生API接口上进行了包装,解决了很多ZooKeeper客户端非常底层的细节开发。同时内部实现了诸如Session超时重连,Watcher反复注册等功能,实现了Fluent风格的API接口,是使用最广泛的zookeeper客户端之一。

6.实现锁方法 6.1 普通方法
public class CreateCode {
    private static int count = 0;
    public static String getNumber(){
        try {
            Thread.sleep(300);
        } catch (Exception e) {
            // TODO: handle exception
        }
        SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return simpt.format(new Date()) + "-" + ++count;  //时间戳后面加了 count
    }
}

import com.dyt.utils.CreateCodeUtil;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class OrderService implements Runnable{
    //使用lock锁
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        getNumber();
        //getNumber1();
    }

    
    
//    public synchronized void getNumber1(){
//        String number = CreateCodeUtil.getNumber();
//        System.out.println(Thread.currentThread().getName()+"num"+number);
//    }
    
    
    public  void getNumber(){
        try {
            lock.lock();
            String number = CreateCodeUtil.getNumber();
            System.out.println(Thread.currentThread().getName()+"num"+number);
        }catch (Exception e){
            
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        OrderService orderService = new OrderService();
        for (int i = 0; i < 100; i++) {
            new Thread(orderService).start();
        }
    }
}
6.2 Curator框架实现分布式锁
  • 导入依赖

     
    
        org.apache.curator
        curator-framework
        4.0.1
    
    
        org.apache.curator
        curator-recipes
        4.0.1
    
    
  • zkLock类

    package com.dyt.utils;
    
    import org.apache.curator.framework.Curatorframework;
    import org.apache.curator.framework.CuratorframeworkFactory;
    import org.apache.curator.framework.recipes.locks.InterProcessMutex;
    import org.apache.curator.retry.RetryNTimes;
    
    import java.util.concurrent.TimeUnit;
    
    public class zkLock {
        private static final String ZK_ADDRESS = "192.168.100.188:2181";
        private static final String ZK_LOCK_PATH = "/zklock/lock0";
    
        private static void zklock(){
            final Curatorframework client = CuratorframeworkFactory.newClient(ZK_ADDRESS, new RetryNTimes(10, 5000));
            client.start();
            System.out.println(client.getState());
            System.out.println("zk client start successfully!");
            final InterProcessMutex mutex = new InterProcessMutex(client, ZK_LOCK_PATH);
    
            for (int i = 0; i < 3; i++) {
                Runnable myRunnable = new Runnable() {
                    public void run() {
                        doWithLock(client, mutex);
                    }
                };
                Thread thread = new Thread(myRunnable, "Thread-" + i);
                thread.start();
            }
        }
    
        private static void doWithLock(Curatorframework client, InterProcessMutex mutex) {
            try {
                String name = Thread.currentThread().getName();
                 
                if (mutex.acquire(1, TimeUnit.SECONDS)) {
    
                    System.out.println(name + " hold lock");
    
                    System.out.println(client.getChildren().forPath(ZK_LOCK_PATH));
    
                    Thread.sleep(5000L);
                    System.out.println(name + " release lock");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    mutex.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        
        public static void main(String[] args) {
            zkLock.zklock();
        }
        
    }
    
  • 启动三个线程去获取锁,线程1获取到锁sleep5秒,超时时间设置为1s,线程0和线程2阻塞等待1s后,便会抛出异常

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/632622.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号