FireBase - 维护/保证数据一致性 [英] FireBase - maintain/guarantee data consistency
问题描述
我正在尝试了解以下情况的正确方法:
I'm trying to understand what is the right approach for this following scenario :
多人游戏,每个游戏仅限
有两名球员。每个游戏/匹配将完全随机化
Multiplayer game,each game structured only
with two players. Each game/match will be completely randomized
让我们假设5个用户同时登录到我的应用程序中,每个用户搜索一个比赛。每个用户持有一个名为对手
的属性,该属性等于对手 uniqueID
(初始值等于
。到目前为止一直很好。
Lets assume 5 users "logs" the same time into my app, each one of them "searching" for a match. Each user hold a property named opponent
which equal the the opponent uniqueID
(initial value equal ""
. so far so good.
假设用户1与用户3匹配。用户1将更新自己的 oppoent
对用户3的价值 uniqueID
并对用户3执行相同操作
assuming user 1 matched with user 3. user 1 will update his own oppoent
value to user 3 uniqueID
and will do the same to user 3
问题
1)如果同时用户2试图与用户3相同怎么办?
2)如果在同一时刻,用户3试图对用户4这样做怎么办?
1) What if at the same moment, user 2 tried to to the same to user 3? 2) What if at the same moment, user 3 tried to do so to user 4?
主要点
是否可以锁定用户值?或者一旦改变就冻结它们?我的方法是错误的吗?
Is it possible to "lock" a user values? or freeze them once they changed? Am i going in the wrong approach?
我在考虑使用安全规则
和验证
为了创建一致性但我可能选择了错误的技术(FireBase)。有什么想法吗?
I was thinking using Security Rules
and Validation
in order to create consistency but i just may picked the wrong tech(FireBase). Any thoughts?
编辑
我尝试过的安全规则,某些原因使第三个设备改变已经改变了对手的价值。
Security rules i have tried, which still for some reason enable a third device change "already changed opponent" value.
{
"rules": {
".read": true,
".write": true,
"Users" :
{
"$uid" : {
"opponent" :
{
".write" : "data.val() == 'empty' || data.val() == null",
".validate": "data.val() == null || data.val() == 'empty' || newData.parent().parent().child(newData.val())
.child('opponent').val() == $uid"
}
,".indexOn": "state"
}
}
}
}
推荐答案
你可以用 Firebase安全规则。
例如,您可以如果对手目前没有对手,则只能写一个对手:
For example, you can say that an opponent can only be written if there currently is no opponent for the user:
"users": {
"$uid": {
"opponent: {
".write": "!data.exists()"
}
}
}
通过以下操作:
ref.child('users').child(auth.uid).child('opponent').set('uid:1234');
ref.child('users').child(auth.uid).child('opponent').set('uid:2345');
第二个 set()
操作将失败,因为对手
属性已经有一个值。
The second set()
operation will fail, because the opponent
property already has a value at that point.
你可以扩展它以验证对手必须互相引用:
You can expand that to also validate that the opponents must refer to each other:
"users": {
"$uid": {
"opponent: {
".write": "!data.exists()"
".validate": "newData.parent().parent().child(newData.val())
.child('opponent').val() == $uid"
}
}
}
- 从正在编写的
对手
中,我们上升两级回到用户
:newData.parent()。parent()
。 - 然后我们去进入对手的节点:
child(newData.val())
。 - 然后我们验证对手的
对手
属性匹配我们的uid:child('opponent')。val()== $ uid
。
- From the
opponent
that is being written, we go up two levels back tousers
:newData.parent().parent()
. - Then we go down into the opponent's node:
child(newData.val())
. - And we then validate that the opponent's
opponent
property matches our uid:child('opponent').val() == $uid
.
现在上面的两个写操作都会失败,因为它们一次只设置一个对手。要解决此问题,您需要执行所谓的多地点更新:
Now both of the write operations from above will fail, because they're only setting the opponent one at a time. To fix this, you'll need to perform a so-called multi-location update:
var updates = {};
updates['users/'+auth.uid+'/opponent'] = 'uid:1234';
updates['users/uid:1234/opponent'] = auth.uid;
ref.update(updates);
我们现在发送一个更新()
命令到Firebase服务器,它将uid写入两个对手。这将满足安全规则。
We're now sending a single update()
command to the Firebase server that writes the uids to both opponents. This will satisfy the security rule.
一些注释:
- 这些是只是一些让你入门的例子。虽然他们应该工作,但你需要编写自己的规则来满足你的安全需求。
- 这些规则只是处理对手的写作。您可能还想测试游戏结束时会发生什么,并且您需要清除对手。
- these are just some examples to get you started. While they should work, you'll need to write your own rules that meet your security needs.
- these rules just handle writing of opponents. You'll probably also want to testing what happens when the game is over and you need to clear the opponents.
这篇关于FireBase - 维护/保证数据一致性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!