首页 > 解决方案 > 多节点架构中并发导致的数据库设计问题

问题描述

我会尽力解决这个问题。请让我知道是否需要任何澄清。

环境:
应用程序部署在 AWS 上,多个实例连接到单个数据存储。
数据存储由表组成,

旧表:

instance_info (id, instance_details, ...)
task_info (id, task_id, ...)

新增表:

new_table (id, instance_info_id, task_info_id, ...)  

架构设计:

  1. id - 在所有表格中都是 PK。
  2. 在 new_table 列中,
    • task_info_id是表 task_info 的外键,并且,
    • instance_info_id是表instance_info。
    • 列instance_info_idtask_info_id上存在唯一约束。

问题:
当代码执行时,它会将其操作划分(分叉)为多个独立和并行执行的线程。完成后,这些线程加入并尝试将数据插入到旧表之一 - “ task_info ”。
现在,可能会出现这样的情况,即这些多个线程(在单个节点上同时运行)将成功地将多个条目填充到表中。

要求:
如果有多个线程,并行工作,那么只有一个线程在“task_info”表中插入一条记录,而其他线程只更新它。

限制:

  1. 无法向task_info表添加唯一约束,因为这种方法会破坏重试机制的现有(遗留代码)功能。
  2. 在写操作期间不能锁定整个表,因为这最终会给我们带来性能问题。
  3. 一种使用“直写”机制(分布式 Memcache)的深思熟虑的方法,但是,如果我们考虑停机时间似乎存在疑问,这可能会导致数据丢失。

是否有任何可以研究的有效设计方法(对遗留代码/设计进行最小/没有更改)?

更新

实施解决方案有一些真正严格的限制(由于添加额外资源的成本),如下所示,

  1. 支持的数据库是 Oracle、SQL Server、MySQL 和 MariaDB。因此,锁定机构必须是可互操作的。
  2. 可以使用的资源有限制 - 数据库和 Memcache。
  3. 该系统可以部署在云端和本地。
  4. 无法从应用程序中创建模块,或创建/依赖新的外部服务。我真的很喜欢 Rob 提出的想法,因为它们很优雅并且让框架为我处理了大部分复杂性。但是,这增加了添加和维护资源的成本。

我猜想改变它的架构和限制,使得找到正确且具有成本效益的解决方案变得复杂。

标签: javadesign-patternsdatabase-designarchitecturedistributed-computing

解决方案


您正在寻找一个分布式锁管理器。对此有很多选择,但由于您已经在使用 AWS,您应该考虑他们使用 DynamoDB 作为 lock-store 构建的那个。不过,三个是很多替代方案,如果您不喜欢 AWS 构建的一个,那么 ZooKeeper 之类的东西可以帮助维护分布式锁系统。


推荐阅读