Synchronization Between Nodes

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

当两个或更多的软件模块访问同一个资源时,它们必须进行同步。这意味着一次只能有一个模块在处理该资源。如果没有这样的同步,就会发生冲突和冲突。当我们谈论不支持“原子”事务的“资源”时,这一点尤为真实。

为了解决这个问题并防止冲突,我们必须在图中引入另一个元素。在访问资源之前,所有软件模块都应该从一个集中服务器中“获取”一个锁。一旦对资源的操作完成,模块应该“释放”锁。当一个模块捕获锁时,其他模块将无法捕获它。这种方法非常简单和众所周知。然而,我没有找到任何云服务能够通过RESTful API提供这样的锁定和解锁服务。所以我决定创建一个——stateful.co

这是一个实际的例子。我有一个托管在Heroku的Java Web应用程序。有三个服务器(即“dynos”)运行相同的.war应用程序。为什么是三个?因为网络流量相当活跃,一个服务器的能力不足。所以我必须有三个。它们都运行完全相同的应用程序。

每个Web应用程序都与Amazon DynamoDB中的一个表进行交互。它更新表格,在其中放入新项目,有时删除一些项目,并选择它们。到目前为止,一切都很好,但冲突是不可避免的。这是一个典型的Web应用程序与DynamoDB之间的交互场景的例子(我正在使用jcabi-dynamo):

这里的逻辑很明显。首先,我从posts表中检索一项,然后读取它的salary,然后根据我的重新计算算法进行修改。问题在于,当我重新计算时,另一个模块可能开始执行相同的操作。它将从表中读取相同的初始值,并开始完全相同的重新计算。然后它将保存一个新值,而我也会保存一个新值。结果是,我们只修改了Jeff的薪水一次,而用户预期的是两次修改,因为他们通过两个不同的Web应用程序发起了两个交易。

在这里的正确方法是首先“锁定”DynamoDB表,甚至在读取薪水之前。然后进行修改,最后解锁。这就是stateful.co如何帮助我。我只需要在stateful.co的Web面板中创建一个新的命名锁定,获取我的身份验证密钥,并修改我的Java代码:

如你所见,我将这个关键的事务封装成了Callable,它将在隔离环境中执行。显然,这种方法不能保证事务的原子性——如果事务的一部分失败了,就不会有任何自动回滚,并且DynamoDB表将处于一个”损坏”的状态。

stateful.co的锁可以保证资源使用的隔离性,你可以使用任何类型的资源,包括NoSQL表、文件、S3对象、嵌入式软件等。

我不应该忘记将这个依赖添加到我的pom.xml中:

当然,你也可以做同样的事情;这项服务完全免费。而且你可以使用任何其他语言,不仅限于Java。顺便说一句,如果你有兴趣的话,可以用你喜欢的语言贡献自己的SDK;我会将其添加到GitHub收藏中。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-27 at 04:58

sixnines availability badge   GitHub stars