精选文章 分布式锁

分布式锁

作者:飞火龙在天 时间: 2021-02-05 10:02:20
飞火龙在天 2021-02-05 10:02:20
【摘要】分布式主要是产生了多个虚拟机JVM,故同一个变量会同时存在多个虚拟机里 
分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题! 
分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consiste...

分布式主要是产生了多个虚拟机JVM,故同一个变量会同时存在多个虚拟机里

分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!

分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。有的时候,我们需要保证一个方法在同一时间内只能被同一个线程执行。

1.基于数据库实现分布式锁; 
2.基于缓存(Redis等)实现分布式锁; 
3.基于Zookeeper实现分布式锁;

一。

缺点:

1、这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。
2、这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
3、这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
4、这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。

解决方案:
1、数据库是单点?搞两个数据库,数据之前双向同步。一旦挂掉快速切换到备库上。
2、没有失效时间?只要做一个定时任务,每隔一定时间把数据库中的超时数据清理一遍。
3、非阻塞的?搞一个while循环,直到insert成功再返回成功。
4、非重入的?在数据库表中加个字段,记录当前获得锁的机器的主机信息和线程信息,那么下次再获取锁的时候先查询数据库,如果当前机器的主机信息和线程信息在数据库可以查到的话,直接把锁分配给他就可以了。
二。

缺点:

在这种场景(主从结构)中存在明显的竞态:
客户端A从master获取到锁,
在master将锁同步到slave之前,master宕掉了。
slave节点被晋级为master节点,
客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。安全失效

try{
lock = redisTemplate.opsForValue().setIfAbsent(lockKey, LOCK);
logger.info("cancelCouponCode是否获取到锁:"+lock);
if (lock) {
// TODO
redisTemplate.expire(lockKey,1, TimeUnit.MINUTES); //成功设置过期时间
return res;
}else {
logger.info("cancelCouponCode没有获取到锁,不执行任务!");
}
}finally{
if(lock){
redisTemplate.delete(lockKey);
logger.info("cancelCouponCode任务结束,释放锁!");
}else{
logger.info("cancelCouponCode没有获取到锁,无需释放锁!");
}
}

三。

缺点:
性能上可能并没有缓存服务那么高。因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上。

其实,使用Zookeeper也有可能带来并发问题,只是并不常见而已。考虑这样的情况,由于网络抖动,客户端可ZK集群的session连接断了,那么zk以为客户端挂了,就会删除临时节点,这时候其他客户端就可以获取到分布式锁了。就可能产生并发问题。这个问题不常见是因为zk有重试机制,一旦zk集群检测不到客户端的心跳,就会重试,Curator客户端支持多种重试策略。多次重试之后还不行的话才会删除临时节点。(所以,选择一个合适的重试策略也比较重要,要在锁的粒度和并发之间找一个平衡
以直接使用zookeeper第三方库Curator客户端,这个客户端中封装了一个可重入的锁服务。

public boolean tryLock(long timout, TimeUnit unit) throws InterrruptedException{
try{
return interProcessMutex. acquire (timout, unit);
) catch (Exception e) t
e.printstackTrace ();

}
return true;

}
public boolean  unlock(){

try{
interProcessMutex.release ();
} catch (Throwable e) {
Log.error (e.getMessage(),e);
}finally {
executorService.schedule (nw Cleaner(client, path), delayTlmeForClean, timeunit. MILL ISECONDS);

}
return true;

}

Curator提供的InterProcessMutex是分布式锁的实现。acquire方法用户获取锁,release方法用于释放锁。

使用ZK实现的分布式锁好像完全符合了本文开头我们对一个分布式锁的所有期望。但是,其实并不是,Zookeeper实现的分布式锁其实存在一个缺点,那就是性能上可能并没有缓存服务那么高。因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上。

其实,使用Zookeeper也有可能带来并发问题,只是并不常见而已。考虑这样的情况,由于网络抖动,客户端可ZK集群的session连接断了,那么zk以为客户端挂了,就会删除临时节点,这时候其他客户端就可以获取到分布式锁了。就可能产生并发问题。这个问题不常见是因为zk有重试机制,一旦zk集群检测不到客户端的心跳,就会重试,Curator客户端支持多种重试策略。多次重试之后还不行的话才会删除临时节点。(所以,选择一个合适的重试策略也比较重要,要在锁的粒度和并发之间找一个平衡。)

使用Zookeeper实现分布式锁的优点

有效的解决单点问题,不可重入问题,非阻塞问题以及锁无法释放的问题。实现起来较为简单。

使用Zookeeper实现分布式锁的缺点

性能上不如使用缓存实现分布式锁。

 

从理解的难易程度角度(从低到高)

数据库 > 缓存 > Zookeeper

从实现的复杂性角度(从低到高)

Zookeeper >= 缓存 > 数据库

从性能角度(从高到低)

缓存 > Zookeeper >= 数据库

从可靠性角度(从高到低)

Zookeeper > 缓存 > 数据库

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:MTK 平台工具

下一篇:iOS如何编译OpenSSL静态库(openssl版本:1.1.1b)

您可能感兴趣

  • 在vb中实现真正锁定的带自定义菜单的文本控件

    在vb中实现真正锁定的带自定义菜单的文本控件 //////这个东西的出台,是由于一个网友的帖子,太气人,我才写的,很匆忙,又什么问题,请指出!谢谢//QQ:9181729/mail:shawfile@163.net/http://shawls.yeah.net///      vb中的textbox控件,虽然可以设置locked属性来实现对文本的锁定,但是,如果用户使用右键菜单,那么就不起作...

  • OGSA:为分布式系统集成提出的开放式Grid Services体系结构(一)

    OGSA:为分布式系统集成提出的开放式Grid Services体系结构   Ian Foster , Carl Kesselman , Jeffrey M. Nick , Steven Tuecke   摘要: 在电子商务和e-科学研究里面,我们经常需要从一个企业的不同资源,或与服务提供商提供的外部共享资源之间形成一个分布的、异构的、动态的VO ( Virtual Organization...

  • 没头没尾--项目开发笔记:C#分布式工程的修改版本

    标题:没头没尾--项目开发笔记:C#分布式工程的修改版本 关键词:分布式开发 C# 项目分工 DELPHI与C#的混合开发        11月20号:有点兴奋有点困 说回忆实在有点麻烦,我还是直接跳到目前的项目状态来讲讲我们是怎么具体实现的吧。 接着昨天下午的写吧。我想首先对我们具体实现的工程过程用最简单的方式描述一下。 一开始我们给客户做一个ASP.NET的实现,然后根据我们的调研发现...

  • 分布式三层架构初步

    绪言 随着传统的客户机/服务器模式的发展,其存在的弊端也促进显现,现一代的企业级应用体系结构-分布式三层结构的出现,提供了开发应用程序的更大的灵活性和可扩展性。 其优点如下: 。将复杂的业务逻辑封装起来   使传统的面向对象提高到一个新的层次,在一个组件中实现一个服务使得业务需求改变时的维护得到了简化。 。独立于程序设计语言   基于com组件的技术是一组二进制标准,与具体语言无关 。减少项...

  • 用RMI和CORBA开发JAVA分布式程序(二)

    CORBA   CORBA是OMG组织针对企业应用上的分布式程序开发标准。重要的一点是CORBA仅仅是个规范。CORBA应用以ORB而知名。市场上已经出现了几个CORBA产品如VISIBROKE,ORBIX等。JAVAIDL是在JDK1。3及以上版本核心包的另一个应用。 CORBA设计的与平台和语言无关(注:与WEB SERVICE类似),因此CORBA能运行在任何平台上,能应用在任何网络里...

  • 面向对象的分布式开发系统 (三)

    返回首篇 前文:面向对象的分布式开发系统 (二) 3.3     分布式对象Distributed Object 在上文提到,SoftEngine 由不同种类的对象构造,在发布实施角度上看,可分为三种: 本地(Local)对象,远地(Remote) 对象,虚拟(Virtual) 对象 。 图表 6 Local, Remote and Virtual Object 在上图中: 本地对象Lo...

  • 领略分布式编程乐趣--[3]

    领略分布式编程乐趣 RedStar81 于9/9/2003~13/9/2003                                               81_RedStar81@163.com                                               TomHornson.student@www.sina.com.cn 首次修改时间:13...

  • 数据库事务和锁(一)

    简述     关系型数据库有四个显著的特征,即安全性、完整性、并发性和监测性。数据库的安全性就是要保证数据库中数据的安全,防止未授权用户随意修改数据库中的数据,确保数据的安全。在大多数数据库管理系统中,主要是通过许可来保证数据库的安全性。完整性是数据库的一个重要特征,也是保证数据库中的数据切实有效、防止错误、实现商业规则的一种重要机制。在数据库中,区别所保存的数据是无用的垃圾还是有价值的信息...

CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
分布式锁介绍:华为云为您免费提供分布式锁在博客、论坛、帮助中心等栏目的相关文章,同时还可以通过 站内搜索 查询更多分布式锁的相关内容。| 移动地址: 分布式锁 | 写博客