1

我遇到了一个问题,其中在我们的一个模型中异步保存在应用程序级别声明的唯一性验证没有被所述验证阻止。由于我的应用程序上有一个可切换选项来启用/禁用唯一性验证,因此在数据库级别添加验证对我来说不是一个选项。

在搜索时,我发现 Redis 锁最适合这种情况,但是由于我对“Redis 锁”这个术语不熟悉,所以我需要一些关于哪个插件/实现更好地实现我需要的行为的建议。

我在这里看到了一个可能与我的问题类似的响应Ruby - Redis based mutex with expire implementation,它说不需要插件,因为它可以像这样单独使用 Redis 来实现

def lock(key, timeout)
  if @redis.set(key, Time.now, nx: true, px: timeout)
    begin
      yield
    ensure
      release key
    end
  end
end

而且我还看到有人推荐这个 redlock 插件在这里找到https://github.com/leandromoreira/redlock-rb但可能是一个矫枉过正。

提前致谢

4

1 回答 1

2

你有几种可能性:

序列化保存操作

假设您使用某种后台作业:将这些作业放入只有一个工作人员的队列中。

锁定保存操作

保持锁定时不要进入保存操作。可以通过 Redis 和 Redlocker 完成(不要自己做,请在此处查看有关 Redlocker 的评论和详细信息:https ://redis.io/commands/set )

但是两者都不能解决这个问题:当有两条记录并且其中一条无法保存时,你会怎么做?这是处理还是可以忽略?

请注意,Rails 的唯一性验证不是事务性的,您不能依赖它来强制执行唯一性(基本上它是插入/更新之前的选择)。见https://phraseapp.com/blog/posts/pitfalls-uniqueness-validation-for-uniqueness-using-rails-activerecord/

正确执行唯一性的唯一地方是数据库。我认为验证有利于向用户报告错误,但是当涉及到数据的完整性时,您应该将其保存在数据库中。

“可切换选项”对我来说似乎没有多大意义。一旦禁用唯一性检查,重复项将最终出现在数据库中。启用唯一性检查不会更改现有数据的这一点。

也许您可以添加部分索引?(https://www.postgresql.org/docs/current/indexes-partial.html

CREATE UNIQUE INDEX unique ON orders (some_column) WHERE (some_othercolumn is null);

(假设 Postgres)

于 2019-07-12T13:53:17.817 回答