【问题标题】:Preventing multiple users from doing the same action防止多个用户执行相同的操作
【发布时间】:2012-01-05 14:22:49
【问题描述】:

我有一个摆动桌面应用程序,它安装在局域网内的许多桌面上。我有一个 mysql 数据库,所有这些都可以与之交谈。每天下午 5 点,每个应用程序中都会有一个线程唤醒并尝试将文件备份到远程服务器。我想阻止所有桌面应用程序做同样的事情。

我当时的想法是:

在下午 5 点醒来后,所有应用程序都会尝试在 MYSQL 表中写入一行。他们会写同样的信息。只有 1 会成功,其他会得到重复行异常。谁成功了,就继续运行备份程序。

我的问题是:

  1. 这是正确的做事方式吗?有没有更好(更简单)的方法? 我知道我们也可以使用套接字来做到这一点。但我不想走那条路……编码太多,我还需要确保所有系统都可以先相互通信(ping)

  2. 会不会支持mysql之类的功能。我的数据库是 INNO DB。所以我认为确实如此。通常,我在 LAN 中有大约 20-30 个用户。这会导致数据库处理的巨大开销吗?

【问题讨论】:

  • 为什么不使用未安装在桌面上的专用备份系统?
  • 只有一个客户端应该做备份?您要备份存储在桌面上的数据还是存储在服务器上的数据?
  • @Gandalf - 实际上很难做到。这是我们最初想到的一个好主意,但在备份期间有一些用户参与。如果专用用户不启动应用程序,则无法进行备份。
  • “在每个应用程序中尝试将文件备份到远程服务器”。 “in each”,听起来每个客户都会做备份。 “到远程服务器”听起来像是将存储在服务器中。这个问题写得很好。
  • @Puce - 备份数据应该存储在远程服务器上 - 实际上是 Amazon S3。所有客户端都可以访问相同的数据库和文件(在共享文件夹上)。因此,如果备份同时在所有用户的桌面上运行,那么他们基本上会一次又一次地备份相同的文件。

标签: java mysql swing


【解决方案1】:

如果您可以在应用程序和数据库之间放置一个中间类,该类会将结果排队并允许它们以有序的方式进行,那么您将把它敲掉。

听起来应用程序都直接针对数据库。您必须修改应用程序以避免此问题。

我有很多关于设计的问题:

  1. 为什么他们都写“同一行”?他们不是在为自己的个人实例编写信息吗?
  2. 为什么每个人都有完全相同的主键?如果有自动增量或时间戳,则不会出现此问题。
  3. 数据库连接上的隔离设置是什么?如果它设置为 SERIALIZABLE,您将强制每一个等待前一个完成,但会以性能为代价。
  4. 能否让他们都将文件写入一个公共目录并在以后有条不紊地拾取它们?

我现在只是在头脑风暴。

【讨论】:

  • 我想我可能没有在问题中明确表达自己。对不起。中间类是不可能的,因为它们是在不同桌面上运行的独立应用程序。所以不幸的是我不能排队请求。因此,我想使用数据库来决定谁实际获胜。谁先将记录写入数据库,谁就赢了!他们可以上传数据。其他人没有。
  • 是的,你可以创建一个中间类。它会在网络上监听,就像数据库一样。您的应用程序只会写入应用程序,而不是打开 JDBC 连接并写入数据库。该中介可以将请求排队。将其视为位于客户端和数据库之间的服务。您正在以这种方式进行面向服务的架构。您当前的设计,如所写,是有缺陷的 - 但你已经知道了。
  • 啊!好吧..这是一个好主意,但不幸的是,这会给我带来安装问题。我现在需要确保在运行数据库的服务器上也运行一个 java 程序。这个java程序需要创建为windows服务,并且必须随系统启动。
【解决方案2】:

您似乎想备份服务器数据而不是客户端数据。

我建议使用 Java EE 的 3 层架构。 您可以使用 Timer Service 然后触发备份。

虽然通常备份程序是一个独立的程序,例如由服务器上的 cron 作业启动。但同样:您需要一台服务器才能正确执行此操作,而不仅仅是共享文件夹。

【讨论】:

  • 对不起 Puce.. 我没听懂。我想将存储在客户端桌面上的数据备份到服务器上。我在客户端系统上安装的应用程序是一个摇摆应用程序。 Swing 应用程序需要将数据备份到服务器上——准确地说是 Amazon S3。
  • 再次:您要备份服务器数据(所有应用程序访问的共享文件夹上的数据,因此只应备份一次)或存储在客户端上的数据,在这种情况下您可能想要备份所有客户端的数据,而不仅仅是一个客户端?
  • 啊好吧..我们在谈论同样的事情。是的,我想将存储在共享文件夹中的数据备份到 Amazon S3。没有任何数据存储在我要备份的客户端桌面上。但正如 duffymo 对答案的评论中提到的那样,我发现很难在服务器上安装 cron 作业并从那里开始备份,因为用户参与了此操作。
【解决方案3】:

这是我的建议。与其让所有客户端同时唤醒并尝试执行备份,不如错开它们唤醒的时间。

所以当客户醒来时 - 它将检查您的数据库(MYSQL)中的某个表,以查看备份作业是否已完成或当前正在运行。如果工作完成,客户将继续其正常职责。您可以决定在作业运行时如何处理该案例。 - 如果客户端发现当天没有运行备份作业,它将启动备份作业。同时将修改该行以指示备份作业已开始。备份完成后,客户端将修改表以指示备份已完成。

这种方法可以防止网络活动激增,还可以提供一种基本形式的故障转移。因此,如果一个客户端出现故障,稍后另一个客户端可以尝试备份。 (不过这涉及到更多。基本上,它归结为客户在看到备份工作正在进行时应该做什么)。

【讨论】:

  • 这是个好主意。但是我们在实现这一点时遇到了问题。抱歉,在有人回答后,我一直在提出限制。要求是用户可以选择适合运行备份的时间。有一个主用户会选择何时从他的办公室进行备份。这将适用于办公室中的所有其他用户。但最终,其中之一应该成功。因此,尽管这个想法很棒,但它会否定用户的需求。你能告诉我我上面建议的方法有什么问题吗?
  • 那么为什么不让用户也指定一个客户端来处理备份呢?这样,用户就知道正在处理备份的机器,因此将确保它不会关闭等。您提到的方法没有问题。我猜你在某个表上有一个唯一的约束设置,所以只有一个客户端可以成功插入一行。这肯定会奏效,会在某个时间点突然爆发,但这应该由 MySQL 轻松处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 2021-07-25
相关资源
最近更新 更多