gpt4 book ai didi

ruby-on-rails - 似乎无法保持 redis 计数器正确

转载 作者:可可西里 更新时间:2023-11-01 11:12:00 24 4
gpt4 key购买 nike

我有一些计数器存储在 REDIS 中,这些计数器会根据 customer.rb 中的状态变化进行更新。我需要存储的东西是:

1) 与用户关联的客户数(用户有_很多客户)2) 状态为(使用 aasm_state)“打开”或“已认领”的客户数量3) 状态为(使用 aasm_state)“打开”的客户数量

每当客户的状态发生变化时,我都会相应地增加/减少 redis 计数器。但是,无论我尝试过什么,计数似乎总是在一段时间后消失。

我正在使用 Sidekiq,但我认为这不是并发问题,因为 REDIS 不应该受到并发问题的影响,对吗?

这是我的计数更新方法:

  def reset_stats
if aasm_state_was == 'open' && aasm_state == 'claimed' # open => assigned
# update company and user
user.redis_increment_my_customers_length
company.redis_decrement_open_customers_length

elsif user_id_changed? && aasm_state_was == 'claimed' && aasm_state == 'claimed' # assigned => assigned
# update users (assigner and assignee)
user_was = User.find(user_id_was)
user.redis_increment_my_customers_length
user_was.redis_decrement_my_customers_length

elsif aasm_state_was == 'claimed' && aasm_state == 'closed' # assigned => closed
# update company and user
user_was = User.find(user_id_was)
user_was.redis_decrement_my_customers_length
company.redis_decrement_all_customers_length

elsif aasm_state_was == 'closed' && aasm_state == 'claimed' # closed => assigned
# update company and user
user.redis_increment_my_customers_length
company.redis_increment_all_customers_length

elsif aasm_state_was == 'closed' && aasm_state == 'open' # closed => open
# update company
company.redis_increment_all_customers_length
company.redis_increment_open_customers_length

elsif aasm_state_was == 'open' && aasm_state == 'closed' # open => closed
# update company
company.redis_decrement_all_customers_length
company.redis_decrement_open_customers_length

end

在 user.rb 中:

def redis_length_key
"my_customers_length_for_#{id}"
end

def set_my_customers_length(l)
RED.set(redis_length_key, l)
l.to_i
end

def redis_increment_my_customers_length
RED.get(redis_length_key) ? RED.incr(redis_length_key) : my_customers_length
end

def redis_decrement_my_customers_length
RED.get(redis_length_key) ? RED.decr(redis_length_key) : my_customers_length
end

def my_customers_length
if l = RED.get(redis_length_key)
l.to_i
else
set_my_customers_length(my_customers.length)
end
end

在 company.rb 中:

def open_customers
customers.open
end

def redis_open_length_key
"open_customers_length_for_#{id}"
end

def set_open_customers_length(l)
RED.set(redis_open_length_key, l)
l.to_i
end

def redis_increment_open_customers_length
RED.get(redis_open_length_key) ? RED.incr(redis_open_length_key) : open_customers_length
end

def redis_decrement_open_customers_length
RED.get(redis_open_length_key) ? RED.decr(redis_open_length_key) : open_customers_length
end

def open_customers_length
if l = RED.get(redis_open_length_key)
return l.to_i
else
set_open_customers_length(open_customers.length)
end
end

def redis_all_length_key
"all_customers_length_for_#{id}"
end

def set_all_customers_length(l)
RED.set(redis_all_length_key, l)
l
end

def redis_increment_all_customers_length
RED.get(redis_all_length_key) ? RED.incr(redis_all_length_key) : all_customers_length
end

def redis_decrement_all_customers_length
RED.get(redis_all_length_key) ? RED.decr(redis_all_length_key) : all_customers_length
end

def all_customers_length
if l = RED.get(redis_all_length_key)
l.to_i
else
set_all_customers_length(open_or_claimed_customers.length)
end
end

def open_or_claimed_customers
customers.open_or_claimed
end

是否有更好的模式来实现我想要完成的目标?这非常令人沮丧,因为一段时间后计数似乎总是不正确。请帮忙!

最佳答案

在调用 set_my_customers_length(my_customers_length + 1) 和调用 RED.set(redis_open_length_key, l) 之间存在竞争条件。

  1. 两个进程启动。
  2. 当第一次调用两个进程时,my_customers_length 为 5。
  3. 第一个进程进行第二次调用并将 Redis 设置为 6。
  4. 第二个进程进行第二次调用并再次将 Redis 设置为 6。
  5. Redis 值实际上应该是 7。

考虑使用 Redis 的 INCR 和 DECR 函数以原子方式更新值。

关于ruby-on-rails - 似乎无法保持 redis 计数器正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31127285/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com