google cloud firestore 1每秒写入文件的限制以及如何解决该问题

时间:2019-05-04 06:58:01

标签: google-cloud-firestore

在这段视频https://youtu.be/o7d5Zeic63s?t=145中,它说文档的每秒写限制为1。

如果您正在制作评论应用程序,并且希望保留餐厅文档的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星评级的文档计数时,如果有3万星的4星评级会像30k的读取账单吗?您如何在不收取3万次读取费用的情况下获得此计数?

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

编辑:我看过这篇文章:How to get a count of number of documents in a collection with Cloud Firestore

在这种情况下,所有提议的解决方案都无法使用。由于我们假设星级评分的计数每秒将增加/减少1次以上。

1 个答案:

答案 0 :(得分:0)

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

要解决此问题,我们可以按照以下说明使用分布式计数器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;
    });
}