Firebase 中非常接近的事件的数据一致性
Posted
技术标签:
【中文标题】Firebase 中非常接近的事件的数据一致性【英文标题】:Data Consistency on very close events in Firebase 【发布时间】:2016-01-13 23:17:15 【问题描述】:我正在开发一款 ios 游戏。每个游戏室由两个用户构成。两个用户匹配后,我会在两台设备上显示“等待响应”计时器:他们需要在 8 秒内单击“我准备好了”按钮,否则他们都会被踢出房间 + 从 Firebase 中删除.
用户的正确状态(在他们每个人点击“我准备好了”按钮之前):
Parent
Matches
User 1
opponent : User2
state : "NotReady"
User 2
opponent : User1
state : "NotReady"
重要说明 - 两台设备上的计时器时间差为 +-2 秒,换句话说 - 一次设备计时器将在另一个之前结束
当用户按下“我准备好了”按钮时,我正在更新state : "userReady"
,并检查其他用户是否也准备好了(观察其state
值)。
如果两个用户都userReady - 开始游戏。
问题
所以我们已经清楚,在 100% 的情况下,两个设备之间的时间差很小。 但是,例如,
User1
点击了I'm Ready
按钮。所以现在User2
得到了一个ChildUpdate
事件,据他所知-User2
已经完全准备好了。
User1 timer
首先结束(事实),所以当他的计时器结束时,User2 timer
将保持1
秒。 现在, User1
时间刚刚达到零,因此他被踢出房间,并在每个用户节点上发送 removeValue
事件。当这种情况发生时,在这个非常小的“间隙”,(在User1 timer
结束的零时间,User2
时钟显示的 1 秒(事实)之间 - 他按下准备按钮。比他认为User1
已经准备好开始游戏了,而且他也准备好了——然后游戏开始了。
最终结果 -
两名玩家都已从 Firebase 中删除
用户 1 不在房间内
User2 开始游戏(他认为自己是对手)
我该如何解决这种最终情况?,我已经尝试仅在“UpdateChild 状态”完成时调用startGame
函数,但它仍然进入,可能是因为订单对于 updateChild 和 removeValue"?
有什么建议吗?非常感谢 Firebase 团队一直以来的努力!!!
【问题讨论】:
对于其他寻找数据一致性文档的人,请参阅event guarantees here 嘿@Kato。谢谢你的回复。已经读过这个(几次)呵呵,还没有想出一个解决方案.. 这与您的问题无关,但标题(数据一致性)是一个常见的话题,因此希望对其他人有所帮助。 @Kato ,知道了 - 谢谢。 对于下一个问题:请包含您已经尝试过的代码。如果你展示你已经做过的事情,就更容易回应(和推理)你的问题。 【参考方案1】:用户 1 接受然后过期是没有意义的。用户 2 应该是过期的,如果达到时间限制并且他还没有接受。
为了防止这种情况,您正在寻找transactions。当您要让用户“过期”时,请使用事务来执行此操作,这样就不会发生数据冲突。
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.child('Parent/Matches').child(user1).transaction(function(currentValue)
if( currentValue && currentValue.state === 'NotReady' )
return null; // delete the user
else
return undefined; // abort the transaction; status changed while we were attempting to remove it
);
可能很快就正确了:
var ref = Firebase(url: "https://<YOUR-FIREBASE-APP>.firebaseio.com/Parent/Matches/<user id>")
upvotesRef.runTransactionBlock(
(currentData:FMutableData!) in
if currentData && currentData.value["state"] != "NotReady"
return FTransactionResult.successWithValue(NSNull)
return FTransactionResult.abort();
);
此外,您可以简化事情并减少混乱的机会,方法是在两个用户都达到其接受时间限制之前不删除/过期记录,然后在事务中同时执行这两项操作。
【讨论】:
在我深入阅读之前快速评论一下——我有这种架构——大厅类别和比赛类别。如果用户 1 单击准备好,但时间过去了。我正在删除 match cat' 处的节点,并立即在 Lobby 创建新节点并搜索对手(就像澄清一样)。我会深入阅读答案并告诉您是否进一步 好的,首先谢谢您!其次 - 关于这个的两个任务。是否可以将其翻译为 ios(swift 更好,但目标 c 也可以)?如果没有,没有苛刻的嘿嘿。第二。 “用户 1 接受然后过期是没有意义的”。但是如果时间到了 0(我正在显示计时器,所以用户将触发我准备好了按钮),它缺乏设计和用户体验来让用户留在房间里(即使时间设置为零) .我指望 Firebase 服务器将差异 top 保持 2 秒,所以即使 6 秒按下我准备好按钮听起来也很公平。我只是想避免小的差距 iOS 事务是covered here。我会尝试将此添加到我的答案中。 谢谢加藤 - 你的帮助是无价的..!你能分解交易状态吗? ' if( currentValue && currentValue.state === 'NotReady' ) ' ,我不完全理解 if 语句。我正在使用事务来更新用户的状态?还是删除它?很抱歉造成混乱 谢谢加藤!我会让你知道实现是如何进行的以上是关于Firebase 中非常接近的事件的数据一致性的主要内容,如果未能解决你的问题,请参考以下文章