有2个apis暴露给客户和商家..商家和客户都将使用相同的交易ID 打到他们各自的api。无论谁先来,我应该在db中创建具有交易ID和商家详细信息(如果商家是第一个)和第二个如果客户来了我应该用商家创建记录的交易ID更新记录的客户详细信息。
如何通过一次接受10,000次请求命中来处理它。它应该没有任何问题回复?请告诉我们如何在rails
中实施,是否可行。
提前谢谢..
答案 0 :(得分:0)
我正在嘲笑这个作为答案,但听起来你只需要锁定。改变你的表格,包括一个名为'owned_by'的列(或类似的东西)。
每当您的实例需要修改记录时,请让它发出如下更新:
UPDATE table_name SET owned_by = IF(owned_by IS NULL, 'uniq_id', owned_by) WHERE id = 1;
IF语句可以防止它在检查之间被锁定时窃取锁定。
然后重新查询该行,如果uniq_id设置为当前线程uniq_id,则表示您可以安全地编写,否则让它以增量方式休眠并重新查询,直到记录锁定释放为止。如果可以在没有锁的情况下完成某些事情,那就让它忽略该字段。工作流程看起来像这样(sudo代码):
def uniq_id
rand() #probably want something better here
end
def trylock_row
"UPDATE table_name SET owned_by = IF(owned_by IS NULL, '#{uniq_id}', owned_by) WHERE id = #{id};"
end
def release_lock
"UPDATE table_name SET owned_by = IF(owned_by == '#{uniq_id}', NULL, owned_by) WHERE id = #{id};"
end
def reget_row
"SELECT * FROM table_name WHERE id = #{id}"
end
def issue_update something
r = self
while(r.owned_by != uniq_id){
if r.owned_by.nil?
trylock_row
r = reget_row
break if r.owned_by == uniq_id
end
sleep(0.25) #arbitrary, keep it small
r = reget_row
}
#issue_updates
release_lock #Really should be in a ensure block just in case
end
答案 1 :(得分:0)
我将提供另一种处理方法。
正如Camway在回答中提到的,锁定是一种方法。这是一些额外的资源:
http://thelazylog.com/understanding-locking-in-rails-activerecord/
https://www.leighhalliday.com/avoid-race-conditions-with-postgres-locks
另一种处理方法是使用数据库级约束。虽然Rails级别竞争条件可能导致数据完整性失败,但在数据库级别上,记录仍然是一个接一个地插入(这是写入比读取慢的原因之一)。
因此,您只需在其中一个字段上添加唯一索引约束即可。由于您没有描述客户和商家如何匹配transaction_id,因此我无法告诉哪个字段添加约束。但你可以这样:
def find_or_create
# pseudocode here
transaction = Transaction.find_by_condition(...)
return transaction if transaction
Transaction.create!(...)
rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid => e
log_error
retry
end
我在生产中使用它,我们服务数百万个db事务没有问题。救援区通常只会执行几次,因为大部分时间你会找到记录并立即归还。