当路径不确定且可变时,在多路径更新期间具有一致性

时间:2017-02-14 13:59:06

标签: firebase firebase-realtime-database firebase-security

当我们对扇出数据进行多路径更新时,我需要帮助。当我们计算路径数然后更新时,如果在某处添加新路径,则新添加的路径中的数据将不一致。

例如,下面是博客文章的数据。帖子可以用多个术语标记,例如“tag1”,“tag2”。为了找到用特定标签标记了多少帖子,我也可以将帖子数据扇出到标签路径路径:

/posts/postid1/Title : “Title 1 modified”
/tags/tag1/postid1/Title : “Title 1 modified”
/tags/tag2/postid1/Title : “Title 1 modified”

现在同时考虑,

1a) User1想要修改postid1的标题,并建立以下多路径更新:

/posts/postid1/tags : {“tag1:true, “tag2”: true, “tag3”: true}
/tags/tag3/postid1: {“Title”:”Title 1”,  “body”: “About Firebase”}

1b)同时User2想要将tag3添加到postid1并构建以下多路径更新:

posts":{
  "$postid":{
    ".write":true,
    ".read":true,
    ".validate": "
      newData.hasChildren(['userId', 'updatedAt', 'lastUpdated', 'Title']) && (
        !data.exists() || 
        data.child('updatedAt').val() === newData.child('lastUpdated').val())"
  } 
}

显然这两个更新都可以一个接一个地成功,我们可以让标签/ tag3 / postid1数据不同步,因为它有旧标题。

我可以考虑安全规则来处理这个问题但不确定这是否正确或是否有效。

就像我们可以拥有updatedAt和lastUpdatedAt字段一样,我们检查是否正在更新我们自己阅读的帖子版本:

"tags":{
  "$tag":{
    "$postid":{
      ".write":true,
      ".read":true,
      ".validate": "
        newData.hasChildren(['userId', 'updatedAt', 'lastUpdated', 'Title']) && (
        newData.child('updatedAt').val() === root.child('posts').child('$postid').val().child('updatedAt').val())”            
    }
  }     
}

对于标签我们也不想再检查一下,我们可以检查/ tags / $ tag / $ postid / updatedAt是否与/ posts / $ postid / updatedAt相同。

{{1}}

通过这个“/ posts / $ postid”中有并发控制,用户可以编写自己的读取 此外/ posts / $ postid“成为事实的来源,休息其他扇出路径检查更新的字段是否与真实路径的主要来源匹配。

这会带来一致性还是仍有问题?或者在大规模完成时可以降低性能?

多路径更新和规则是否原子化我的意思是规则或两个规则是单独分别评估多路径更新,如上面的1a和1b?

1 个答案:

答案 0 :(得分:1)

不幸的是,Firebase不提供任何保证或机制来提供您正在寻找的确定性级别。我有一个最好的运气前端这样的更新与API堆栈(GCF和Lambda都很容易,无服务器的方法这样做)。可以在该层中进行更新,如果绝对必要,甚至可以序列化。但是在Firebase本身中没有一种安全的方法可以做到这一点。

有很多" hack"您可以申请的选项。例如,您可以使用专用集合来跟踪写锁定的简单锁定机制。在执行写入之前,客户端可以发布到锁集合,然后验证其密钥是该集合的唯一成员。但我希望您同意我的观点,即此类合作系统存在太多潜在的边缘情况,潜在的安全问题等等。在Firebase中,最好将其设计为首先不需要此组件。