我们要悄悄地学习,然后惊艳所有人! —分布式锁详解

什么是分布式锁?分布式锁又可以解决哪些问题呢?

在我们的系统还没有使用分布式架构的时候,我们可以用同步锁或者Lock锁,来保证多线程并发的时候,同一时间只有一个线程修改共享变量或者执行代码块,但是当我们现在大部分系统都是分布式集群部署的,单纯的同步锁和Lock锁只能保证单个实例上的数据一致性,多实例就失去了作用。

这个时候就需要使用分布式锁来保证共享资源的原子性,比如我们电商系统里面的扣减库存,当单量小的时候问题不大,如果单量很大,同一时间多个实例都在并发处理扣减库存的业务的时候,就可能存在超卖的问题。

记得点赞收藏加关注哦 ,需要下载PDF版本和获取更多知识点、面试题的朋友

可以加q群:580763979  备注:简书   免费领取~

分布式锁的实现?

常见的分布式锁有数据库实现分布式锁、Zookeeper实现分布式锁、Redis实现分布式锁、Redisson实现。其中数据库实现分布式锁比较简单,也很容易理解,直接基于数据库实现就可以了,在一些分布式的业务中也经常使用,但是这种方式也是效率最低的,一般是不使用的,我们就着重介绍一下其他三种方式的实现。

Zookeeper实现分布式锁

使用Zookeeper来实现分布式锁就比较常见,比如很多项目就使用Zookeeper作为分布式注册中心,就喜欢用Zookeeper来实现分布式锁,这主要是借助于Zookeeper的两大特性:顺序临时节点、Watch机制。

顺序临时节点:熟悉Zookeeper的同学都知道,Zookeeper提供了多层级的节点命名空间,每个节点都是用斜杠分隔的路径来表示,类似于我们的文件夹。节点又分为持久节点和临时节点,节点还可以标记为有序,当节点被标记为有序性,这个节点就具有顺序自增的特点,我们就可以借助这个特点来创建我们所需的节点。

Watch机制:Watch机制是Zookeeper另一个重要的特性,我们可以在指定节点上注册一些Watcher,在一些特定的事情触发的时候,通知用户这个事件。

Zookeeper实现分布式锁的过程

我们先创建一个持久节点作为父节点,每当需要访问创建分布式锁的时候,就在这个父节点下创建相应的临时的顺序子节点,以临时节点名称、父节点名称和顺序号组成特点的名称。在建立子节点后,对父节点下以这个这个子节点名称开头的子节点进行排序,判断刚建立的节点顺序号是不是最小的,如果是最小的则获取锁,如果不是最小节点,则阻塞等待锁,并且在获取该节点的上一顺序节点注册Watcher,等待节点对应的操作获得锁。

当业务处理完之后,删除该节点,关闭zk,进而触发Watcher,释放该锁。

上图就是就是严格按照顺序访问的分布式锁实现,更多的时候我们引入一些框架来帮助我们实现,比如最常用的Curator框架,代码如下:

InterProcessMutex lock = new InterProcessMutex(client, lockPath);

if ( lock.acquire(maxWait, waitUnit) ) {

    try {

        // 业务处理

    }

    finally{

        lock.release();

    }

}

Zookeeper来实现分布式锁天然的优势就是,Zookeeper是集群实现的,我们生产环境一般也是集群部署的,可以避免单点问题,稳定性较好,能保证每次操作都可以释放锁。

缺点就是,频繁的创建删除节点,加上注册watch事件,对于zookeeper集群的压力比较大,性能这一块也比不上Redis实现的分布式锁。

Redis实现分布式锁

Redis实现的分布式锁,最为复杂,但是性能确是最佳的,所以在对性能要求更高的系统里,我们都选择使用Redis来实现分布式锁。利用Redis实现分布式锁,一般都是使用SETNX实现,举个简单的例子:

public static boolean getDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

    String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

    if ("OK".equals(result)) {

        return true;

    }

    return false;

}

SETNX方法保证设置锁和锁过期时间的原子性,但是对于锁的过期时间设置我们要注意,如果执行业务时间比较长,我们设置的过期时间又比较短的情况下就会造成,业务还没执行完,锁已释放的问题。所以我们需要根据实际业务处理来评估设置锁的过期时间,来保证业务可以正常的处理完。

Redisson实现分布式锁

Redisson是架设在Redis基础上的一个Java驻内存数据网格。Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。性能也比我们常用的jedis好一些。

Redisson不管是单节点模式还是集群模式,都很好的实现了分布式锁,一般用的多的都是集群模式,在集群模式下,Redisson使用RedLock算法,很好的处理了Master节点宕机时切换到另外一个Master节点过程中多个应用获得锁。

Redisson集群模式获取锁的实现就是,在不同节点上获取锁,每个节点上获取锁都有超时时间,如果获取锁超时就认为这个节点不可用,当成功获取锁的个数超过Redis节点的半数,且获取锁消耗的时间还没超过锁过期时间,则认为获取锁成功。获取锁成功后重新计算锁释放时间,由原来的锁释放时间减去获取锁消耗的时间,如果最终获取锁失败,已经获取锁成功的节点也会释放锁。

具体的代码实现:

引入依赖

<dependency>

    <groupId>org.redisson</groupId>

    <artifactId>redisson</artifactId>

    <version>3.13.1</version>

</dependency>


Redisson配置文件:

<dependency>

    <groupId>org.redisson</groupId>

    <artifactId>redisson</artifactId>

    <version>3.13.1</version>

</dependency>

获取锁操作:

<dependency>

    <groupId>org.redisson</groupId>

    <artifactId>redisson</artifactId>

    <version>3.13.1</version>

</dependency>

总结

实现分布式锁的方式不止这三种,最简单的就是数据库实现,Zookeeper实现也相对比较简单,但是性能最好的还是Redis实现,但是可靠性方面,Zookeeper基于分布式集群,具有天然的优势,可靠性相对更高。如果业务场景对性能要求不是很高的时候,优先使用Zookeeper实现分布式锁。

我这里准备了一线大厂面试资料和超硬核PDF技术文档,以及我为大家精心准备的多套简历模板(不断更新中),希望大家都能找到心仪的工作!

有需要的朋友可以加q群:580763979  备注:简书   免费领取~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容