热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于AmazonDynamoDB的分布式锁

AmazonDynamoDBLockClient是为DynamoDB构建的通用分布式锁定库。DynamoDBLockClient支持细粒度和粗粒度锁定,锁定

Amazon DynamoDB Lock Client是基于DynamoDB构建的通用分布式锁定库。DynamoDB Lock Client支持细粒度和粗粒度锁定,锁定键可以是任意字符串。DynamoDB Lock Client是一个开源项目,得到了社区的支持。

用例

该Lock Client的一个常见用例是:假设您有一个分布式系统,需要定期针对用户执行一些常规操作,您要确保不同服务实例不会同时处理同一个用户。解决此问题的一种简单方法是编写一个可以锁定客户的系统,但是细粒度的锁定是一个难题。

另一个用例是领导者选举。如果您只希望一台机器成为master,则此Lock Client客户端是选择master的一种好方法。当master发生故障时,通过Lock Client可以重新选出新的master。

入门

该组件的pom依赖如下:

<dependency>
<groupId>com.amazonawsgroupId>
<artifactId>dynamodb-lock-clientartifactId>
<version>1.2.0version>
dependency>


然后,您需要设置一个DynamoDB的表,该表具有一个名为key的哈希键为了方便起见,AmazonDynamoDBLockClient类中有一个名为createLockTableInDynamoDB的静态方法可用于设置表,但也可以在AWS控制台中设置该表。该表应提前创建,因为DynamoDB需要花费几分钟的时间来配置该表。

以下是一些示例代码,可帮助您入门:

import java.io.IOException;
import java.net.URI;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;

public class LockClientExample {
@Test
public void usageExample() throws InterruptedException, IOException {
// Inject client configuration to the builder like the endpoint and signing region
final DynamoDbClient dynamoDB = DynamoDbClient.builder()
.region(Region.US_WEST_2).endpointOverride(URI.create("http://localhost:4567"))
.build();
// Whether or not to create a heartbeating background thread
final boolean createHeartbeatBackgroundThread = true;
//build the lock client
final AmazonDynamoDBLockClient client = new AmazonDynamoDBLockClient(
AmazonDynamoDBLockClientOptions.builder(dynamoDB, "lockTable")
.withTimeUnit(TimeUnit.SECONDS)
.withLeaseDuration(10L)
.withHeartbeatPeriod(3L)
.withCreateHeartbeatBackgroundThread(createHeartbeatBackgroundThread)
.build());
//try to acquire a lock on the partition key "Moe"
final Optional<LockItem> lockItem =
client.tryAcquireLock(AcquireLockOptions.builder("Moe").build());
if (lockItem.isPresent()) {
System.out.println("Acquired lock! If I die, my lock will expire in 10 seconds.");
System.out.println("Otherwise, I will hold it until I stop heartbeating.");
client.releaseLock(lockItem.get());
} else {
System.out.println("Failed to acquire lock!");
}
client.close();
}
}

其他特性

自动心跳包发送

调用构造函数AmazonDynamoDBLockClient时,可以createHeartbeatBackgroundThread=true
 像上例中那样指定,它将生成一个后台线程,该线程会不断更新锁上的记录版本号,以防止锁过期(只要您的JVM正在运行,您的锁就不会过期,直到您调用releaseLock()或lockItem.close()

设置获取锁的超时时间

您可以通过两种不同的方法获取锁:acquireLock或tryAcquireLock。两种方法之间的区别在于,如果未获取锁,则tryAcquireLock将返回Optional.absent(),而AcquireLock将抛出LockNotGrantedException。两种方法都提供了可选参数,可以指定获取锁的超时时间。

以下代码将对DynamoDB实现间隔1秒的轮询,并最多持续5秒钟,以尝试获取锁:

LockItem lock = lockClient.acquireLock("Moe", "Test Data", 1, 5, TimeUnit.SECONDS);

获取锁而不阻塞用户线程

@Test
public void acquireLockNonBlocking() throws LockAlreadyOwnedException {
AcquireLockOptions lockOptiOns= AcquireLockOptions.builder("partitionKey")
.withShouldSkipBlockingWait(true).build();
LockItem lock = lockClient.acquireLock(lockOptions);
}

上述实现将尝试获取锁定,至少等待租约过期(在我们的情况下为15分钟)。如果该锁已经被其他worker持有。这实质上阻止了该线程处理队列中的其他消息。

因此,Lock Client提供了非阻塞获取锁定的实现。在尝试获取锁时,客户端可以选择设置shouldSkipBlockingWait = true 
从而防止用户线程在锁释放前被阻塞

@Test
public void acquireLockNonBlocking() throws LockAlreadyOwnedException {
AcquireLockOptions lockOptiOns= AcquireLockOptions.builder("partitionKey")
.withShouldSkipBlockingWait(true).build();
LockItem lock = lockClient.acquireLock(lockOptions);
}

如果该锁不存在,或者该锁已被获取但已过期,则可以成功获取该锁。否则将抛出

LockAlreadyOwnedException异常,通过捕获异常我们可以决定重试锁获取或者退出等待。


读取锁信息

可以在不获取锁的情况下读取锁中的数据,并找出谁拥有锁。就是这样:

LockItem lock = lockClient.getLock("Moe");

Lock Client如何处理时钟偏斜

锁定客户端永远不会在DynamoDB中存储绝对时间-只有相对的“租赁持续时间”时间存储在DynamoDB中。锁过期的方式是,对AcquisitionLock的调用读取当前锁,检查锁的RecordVersionNumber(它是GUID)并启动计时器。如果在租用期限过后该锁仍具有相同的GUID,则客户端将确定该锁已失效并过期。这就是说,即使两台不同的机器对现在的时间意见不一致,它们仍将避免破坏彼此的锁。



推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了三种方法来实现在Win7系统中显示桌面的快捷方式,包括使用任务栏快速启动栏、运行命令和自己创建快捷方式的方法。具体操作步骤详细说明,并提供了保存图标的路径,方便以后使用。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了如何清除Eclipse中SVN用户的设置。首先需要查看使用的SVN接口,然后根据接口类型找到相应的目录并删除相关文件。最后使用SVN更新或提交来应用更改。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
author-avatar
只为-娱乐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有