热门标签 | 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,则客户端将确定该锁已失效并过期。这就是说,即使两台不同的机器对现在的时间意见不一致,它们仍将避免破坏彼此的锁。



推荐阅读
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
  • com.hazelcast.config.MapConfig.isStatisticsEnabled()方法的使用及代码示例 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 在 Android 开发中,`android:exported` 属性用于控制组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)是否可以被其他应用组件访问或与其交互。若将此属性设为 `true`,则允许外部应用调用或与之交互;反之,若设为 `false`,则仅限于同一应用内的组件进行访问。这一属性对于确保应用的安全性和隐私保护至关重要。 ... [详细]
  • Unity3D 中 AsyncOperation 实现异步场景加载及进度显示优化技巧
    在Unity3D中,通过使用`AsyncOperation`可以实现高效的异步场景加载,并结合进度条显示来提升用户体验。本文详细介绍了如何利用`AsyncOperation`进行异步加载,并提供了优化技巧,包括进度条的动态更新和加载过程中的性能优化方法。此外,还探讨了如何处理加载过程中可能出现的异常情况,确保加载过程的稳定性和可靠性。 ... [详细]
  • Spring框架中枚举参数的正确使用方法与技巧
    本文详细阐述了在Spring Boot框架中正确使用枚举参数的方法与技巧,旨在帮助开发者更高效地掌握和应用枚举类型的数据传递,适合对Spring Boot感兴趣的读者深入学习。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • Oracle ERP系统用户指南:涵盖MRP模块详细操作说明
    《Oracle ERP系统用户指南》详细介绍了MRP模块的操作流程与功能。该手册涵盖了从基础设置到高级应用的全方位指导,旨在帮助用户高效地管理和优化物料需求计划。文档编号、受控状态及生效日期等信息均在手册中明确标注,确保内容的准确性和时效性。编制人忻滢对内容进行了全面审核与确认,以保障用户的使用体验。 ... [详细]
  • 深入解析Android GPS机制:第五部分 ... [详细]
  • 在Linux系统中避免安装MySQL的简易指南
    在Linux系统中避免安装MySQL的简易指南 ... [详细]
  • Flowable 流程图路径与节点展示:已执行节点高亮红色标记,增强可视化效果
    在Flowable流程图中,通常仅显示当前节点,而路径则需自行获取。特别是在多次驳回的情况下,节点可能会出现混乱。本文重点探讨了如何准确地展示流程图效果,包括已结束的流程和正在执行的流程。具体实现方法包括生成带有高亮红色标记的图片,以增强可视化效果,确保用户能够清晰地了解每个节点的状态。 ... [详细]
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社区 版权所有