竞争条件 - 使用一个数据库的多个应用程序实例
Race condition - multiple application instances using one database
我计划将我的 Rails 应用程序扩展到多个实例,但它们仍将使用相同的数据库。如果两个用户最终使用应用程序的两个不同实例,编辑同一个帐户,那么这肯定会在某处导致竞争条件 - 鉴于这是一个 Rails 应用程序,防止这种情况的最佳方法是什么?
我所知道的唯一与数据库相关的设置允许指定实际服务器 IP。如果一个程序可以以某种方式成为中间人,它就会解决问题......否则应用程序实例将不得不以某种方式相互通信,对吗??
除非有办法使用 Postgres 中的设置解决此问题...
如有任何帮助,我们将不胜感激!!谢谢!
我建议实施 optimistic locking 策略。 Rails 开箱即用。为此编写完整的教程超出了 Whosebug 答案的范围。请在线查找详细说明。
基础知识是:
对于您要保护的每个模型,您需要向模型的数据库 table 添加一个名为 lock_version
的整数列。另外,在每个表单中,您都需要添加一个包含此 lock_version 的隐藏字段。当然,如果您使用的是安全参数,则允许在控制器中使用 lock_version 参数。
每当您保存一条记录并且存在 lock_version 时,Rails 将确保 lock_version 与数据库中的记录相匹配。如果它们不匹配,这意味着同时发生了另一个更新,并且当前更新失败并显示 StaleObjectError
。
作为后备策略,我建议您向更新被拒绝的用户显示一条闪现消息。此外,使用数据库中的当前值(不是尝试的输入,因为您希望用户重新考虑他们的更改是否合适),呈现他们再次填写的相同表单。
(您可以通过在 ApplicationController
中定义 rescue_from
挂钩来在整个应用程序中实施回退策略。)
HTH!
我计划将我的 Rails 应用程序扩展到多个实例,但它们仍将使用相同的数据库。如果两个用户最终使用应用程序的两个不同实例,编辑同一个帐户,那么这肯定会在某处导致竞争条件 - 鉴于这是一个 Rails 应用程序,防止这种情况的最佳方法是什么?
我所知道的唯一与数据库相关的设置允许指定实际服务器 IP。如果一个程序可以以某种方式成为中间人,它就会解决问题......否则应用程序实例将不得不以某种方式相互通信,对吗??
除非有办法使用 Postgres 中的设置解决此问题...
如有任何帮助,我们将不胜感激!!谢谢!
我建议实施 optimistic locking 策略。 Rails 开箱即用。为此编写完整的教程超出了 Whosebug 答案的范围。请在线查找详细说明。
基础知识是:
对于您要保护的每个模型,您需要向模型的数据库 table 添加一个名为 lock_version
的整数列。另外,在每个表单中,您都需要添加一个包含此 lock_version 的隐藏字段。当然,如果您使用的是安全参数,则允许在控制器中使用 lock_version 参数。
每当您保存一条记录并且存在 lock_version 时,Rails 将确保 lock_version 与数据库中的记录相匹配。如果它们不匹配,这意味着同时发生了另一个更新,并且当前更新失败并显示 StaleObjectError
。
作为后备策略,我建议您向更新被拒绝的用户显示一条闪现消息。此外,使用数据库中的当前值(不是尝试的输入,因为您希望用户重新考虑他们的更改是否合适),呈现他们再次填写的相同表单。
(您可以通过在 ApplicationController
中定义 rescue_from
挂钩来在整个应用程序中实施回退策略。)
HTH!