【问题标题】:google cloud firestore 1 write per second limit for a document and how to get around itgoogle cloud firestore 1 每秒写入文件的限制以及如何绕过它
【发布时间】:2019-05-04 06:58:01
【问题描述】:

在此视频https://youtu.be/o7d5Zeic63s?t=145 中,它说文档的每秒写入次数限制。

如果您正在制作评论应用程序,并且您希望保留餐厅文档的 5、4、3、2、1 星级评分的评论数量,您将如何为具有大量并发用户的应用程序执行此操作然后?想想像foursquare这样的流行应用程序......我认为在这种情况下不可能像这样在餐厅文档本身中保留评分数量:

Restaurant:
 - name
 - address
 - ratings
  - 1 start: count
  - 2 stars: count
  - 3 starts: count
  - 4 stars: count
  - 5 starts count

如果同一家餐厅的星数更新尝试超过 1 次,这将失败,这在这个流行的应用案例中很有可能。

在这种情况下,我可以考虑保留一个 RATINGS 子集合并为每个评级记录一个评级文档。然后我可以获得 4 星评论的评分。但是,当我尝试计算具有 4 星评级的文档时,如果有 30k 4 星评级,是否会像 30k 阅读账单一样?如果不收取 30k 次读取费用,您如何获得此计数?

您将如何避免这种情况以及如何保持/更新餐厅的星级数量?

编辑:我看过这个帖子:How to get a count of number of documents in a collection with Cloud Firestore

在这种情况下,建议的解决方案都不起作用。因为我们假设星级评分的计数每秒增加/减少超过 1 个。

【问题讨论】:

    标签: google-cloud-firestore


    【解决方案1】:

    我想我找到了解决方案,我想与您分享。

    为了解决这个问题,我们可以使用 分布式计数器,如下所述:https://firebase.google.com/docs/firestore/solutions/counters

    写入吞吐量随着分片的数量线性增加,因此具有 10 个分片的分布式计数器可以处理 10 倍于传统计数器的写入。

    总而言之,您可以为每个星级评分创建分片。例如,我们可以为每个星级创建 10 个分片(总共 50 个分片),然后我们可以通过将这 10 个 4 星评分分片中的值相加得到 4 星评分。

    请记住这些限制:

    分片数 - 分片数控制分布式计数器的性能。如果分片太少,某些事务可能需要重试才能成功,这会减慢写入速度。如果分片过多,读取会变得更慢且成本更高。

    成本 - 读取计数器值的成本随着分片的数量线性增加,因为必须加载整个分片子集合。

    下面是我上面链接的 firestore 文档的示例代码。

    初始化一个分布式计数器:

    function createCounter(ref, num_shards) {
        var batch = db.batch();
    
        // Initialize the counter document
        batch.set(ref, { num_shards: num_shards });
    
        // Initialize each shard with count=0
        for (let i = 0; i < num_shards; i++) {
            let shardRef = ref.collection('shards').doc(i.toString());
            batch.set(shardRef, { count: 0 });
        }
    
        // Commit the write batch
        return batch.commit();
    }
    

    选择一个随机分片并增加计数:

    function incrementCounter(db, ref, num_shards) {
        // Select a shard of the counter at random
        const shard_id = Math.floor(Math.random() * num_shards).toString();
        const shard_ref = ref.collection('shards').doc(shard_id);
    
        // Update count
        return shard_ref.update("count", firebase.firestore.FieldValue.increment(1));
    }
    

    查询所有分片并对它们的计数字段求和:

    function getCount(ref) {
        // Sum the count of each shard in the subcollection
        return ref.collection('shards').get().then(snapshot => {
            let total_count = 0;
            snapshot.forEach(doc => {
                total_count += doc.data().count;
            });
    
            return total_count;
        });
    }
    

    【讨论】:

    • 如果这些字段是非索引字段怎么办?仍然,一秒钟的规则适用于他们?我很好奇,因为他们提到他们分别索引每个字段。所以让它们不被索引应该对我们有帮助。我现在知道权衡是我们无法查询这些字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-22
    • 2023-03-13
    • 2019-10-08
    • 2020-06-14
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多