Zookeeper基础(五):分布式锁

分布式锁,主要得益于Zookeeper为我们保证了数据的强一致性

1、锁服务可分为两类,一类是保持独占,一类是控制时序

  • 保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁,通常的做法是把zk上的一个znode节点看做是一把锁,通过create znode的方式来实现,所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁;

  • 控制时序,就是所有试图来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了;做法和上面基本类似,只是这里 /distribute_lock 已经预先存在,客户端在它下面创建临时有序节点(这个可以通过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL来指定);Zk的父节点(/distribute_lock)维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序

2、分布式锁

  • 排他锁:Exclusive Locks,简称X锁,又称为写锁
    如果事务T1对数据对象T0加上了排他锁,那么在整个加锁期间,只允许事务T1对T0进行读取和更新操作,其他任何事务都不能在对这个数据对象进行任何类型的操作(不能再对该对象加锁),知道T1释放了排他锁
image.png
  • 共享锁:Share Locks,简称S锁,又称为读锁
    如果事务T1对数据对象T0加上了共享锁,那么T1只能对T0进行读操作,其他事务也能同时对T0加共享锁(不能是排他锁),直到T0上的所有共享锁都释放后T0才能被加排他锁
image.png

3、Curator分布式锁

Curator实现了以下各种类型的分布式锁:

  • InterProcessMutex 全局可重入锁
    客户端都可以请求锁,并且同一个客户端在拥有锁的同时,可以多次过去锁,不会被阻塞

  • InterProcessSemaphoreMutex 不可重入锁
    不能在同一个线程(客户端)中重入

  • InterProcessReadWriteLock 可重入读写锁
    一个读写锁管理一对相关的锁,一个负责读操作,一个负责写操作,读操作在写锁没被使用时,可同时由多个进程使用;而写锁使用时,不允许读(阻塞)
    可重入读写锁,是可重入的,一个拥有写锁的线程可重入读锁,但是读锁却不能重入写锁;这其实意味着,写锁可以降级为读锁,比如请求写锁——》请求读锁——》释放写锁(同一个线程操作);而读锁是不能升级成写锁的

  • InterProcessSemaphoreV2 信号量

  • InterProcessMultiLock 多锁对象
    InterProcessMultiLock 是一个锁的容器,当调用acquire时,所有的锁都会被acquire,如果请求失败,所有的锁都会被release;同样调用release时,所有的锁都会被release,如果请求失败,则忽略。
    基本上他就是组锁的代表,在它上面的请求释放操作,都会百传递给他包含的所有的锁

4、InterProcessMutex Demo

package com.xxx.api.curator.lock;

import com.xxx.ZookeeperUtil;
import org.apache.curator.RetryPolicy;
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.ExponentialBackoffRetry;

public class CuratorInterProcessMutex {
    RetryPolicy retryPolicy = new ExponentialBackoffRetry(2000, 5);//重试策略
    //工厂创建连接
    CuratorFramework   cf= CuratorFrameworkFactory.builder()
            .connectString(ZookeeperUtil.connectString)
            .sessionTimeoutMs(ZookeeperUtil.sessionTimeout)
            .retryPolicy(retryPolicy)
            .build();

     InterProcessMutex lock;
    public CuratorInterProcessMutex(String path) {
        lock=new InterProcessMutex(cf, path);
        cf.start();//链接
    }

    /***
     * 获取资源
     * @see org.apache.curator.framework.recipes.locks.LockInternals
     * @throws Exception
     */
    public void acquire() throws Exception {
        lock.acquire();
    }

    /****
     * 释放资源
     * @throws Exception
     */
    public void release() throws Exception {
        lock.release();
    }
}
package com.xxx.api.curator.lock;
import com.xxx.ZookeeperUtil;
import com.xxx.lock.DistributedLock;

public class LockTest implements  Runnable {
    static  int i=0;
    CuratorInterProcessMutex curatorInterProcessMutex=new CuratorInterProcessMutex("/root");

    @Override
    public void run() {
        try {
            curatorInterProcessMutex.acquire();
            for(int j=0;j<1000000;j++){
                i++;
            }
            curatorInterProcessMutex.release();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        LockTest lockTest=new LockTest();
        Thread thread=new Thread(lockTest);
        Thread thread2=new Thread(lockTest);
        thread.start();thread2.start();
        thread.join();thread2.join();
        System.out.println(i);
    }
}

Zookeeper

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 飞哥荐读本文从redis分布式锁的官方实现,讨论了分布式锁需要的考虑的问题,并分析了RedLock、zookeep...
    Fi的学习笔记阅读 11,017评论 0 39
  • 最近碰到几个业务场景,会遇到并发的问题。在单实例情况下,我们会通过java.util.concurrent包...
    菜鸟小玄阅读 6,687评论 0 5
  • 什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点。 原子性:要不全部成功,要不全部撤销 隔...
    jiangmo阅读 4,744评论 0 3
  • 人这一辈子,可能觉得活得很累!无论男女,从你到世界的那一刻起,你注定要度过你漫长的人生、经历无数的磨难。走在人生的...
    漂浮的流云阅读 1,594评论 0 3
  • 上平田朝耕上平田,暮耕上平田。借问问津者,宁知沮溺贤? 农人早晚不得闲,都要劳作,很辛苦吧。(或许也很享受这种,日...
    少叔夜阅读 3,741评论 0 4

友情链接更多精彩内容