加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – ActiveRecord模型的互斥锁

发布时间:2020-12-16 19:21:04 所属栏目:百科 来源:网络整理
导读:我的用户模型有一个讨厌的方法,不应该同时为同一记录的两个实例调用.我需要连续执行两个http请求,同时确保任何其他线程不会同时为同一记录执行相同的方法. class User ... def nasty_long_running_method // something nasty will happen if this method is
我的用户模型有一个讨厌的方法,不应该同时为同一记录的两个实例调用.我需要连续执行两个http请求,同时确保任何其他线程不会同时为同一记录执行相同的方法.
class User
  ...
  def nasty_long_running_method
    // something nasty will happen if this method is called simultaneously
    // for two instances of the same record and the later one finishes http_request_1
    // before the first one finishes http_request_2.
    http_request_1 // Takes 1-3 seconds.
    http_request_2 // Takes 1-3 seconds.
    update_model
  end
end

例如,这会破坏一切:

user = User.first
Thread.new { user.nasty_long_running_method }
Thread.new { user.nasty_long_running_method }

但这没关系,应该允许:

user1 = User.find(1)
user2 = User.find(2)
Thread.new { user1.nasty_long_running_method }
Thread.new { user2.nasty_long_running_method }

确保同一记录的两个实例不同时调用该方法的最佳方法是什么?

解决方法

在为我的问题寻找解决方案时,我找到了一个宝石 Remote lock.它是一种在后端使用Redis的互斥解决方案.

它:

>可以访问所有进程
>不会锁定数据库
>在记忆中 – >快速而无IO

该方法现在看起来像这样

def nasty
  $lock = RemoteLock.new(RemoteLock::Adapters::Redis.new(REDIS))
  $lock.synchronize("capi_lock_#{user_id}") do
    http_request_1
    http_request_2
    update_user
  end
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读