使用什么更好的 redis 锁定机制来避免 rails 中的异步验证失败?



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

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

我在这里看到了可能与我的问题类似的响应之一 Ruby - Redis 基于互斥锁,具有过期实现,它说不需要插件,因为它可以像这样单独使用 Redis 来实现

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

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

提前致谢

您有几种可能性:

序列化保存操作

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

锁定保存操作

按住锁时不要进入保存操作。可以通过 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);

(假设邮政)

最新更新