简体   繁体   English

Azure Cosmos DB 的重写分区键策略

[英]Write-heavy partition key strategy for Azure Cosmos DB

We're using CosmosDB in production to store HTTP request/response audit data.我们在生产中使用 CosmosDB 来存储 HTTP 请求/响应审计数据。 The structure of this data generally looks as follows:这些数据的结构一般如下:

{
    "id": "5ff4c51d3a7a47c0b5697520ae024769",
    "Timestamp": "2019-06-27T10:08:03.2123924+00:00",
    "Source": "Microservice",
    "Origin": "Client",
    "User": "SOME-USER",
    "Uri": "GET /some/url",
    "NormalizedUri": "GET /SOME/URL",
    "UserAgent": "okhttp/3.10.0",
    "Client": "0.XX.0-ssffgg;8.1.0;samsung;SM-G390F",
    "ClientAppVersion": "XX-ssffgg",
    "ClientAndroidVersion": "8.1.0",
    "ClientManufacturer": "samsung",
    "ClientModel": "SM-G390F",
    "ResponseCode": "OK",
    "TrackingId": "739f22d01987470591556468213651e9",
    "Response": "[ REDACTED ],   <— Usually quite long (thousands of chars)
    "PartitionKey": 45,
    "InstanceVersion": 1,
    "_rid": "TIFzALOuulIEAAAAAACACA==",
    "_self": "dbs/TIFzAA==/colls/TIFzALOuulI=/docs/TIFzALOuulIEAAAAAACACA==/",
    "_etag": "\"0d00c779-0000-0d00-0000-5d1495830000\"",
    "_attachments": "attachments/",
    "_ts": 1561630083
}

We're currently writing around 150,000 - 200,000 of documents similar to the above a day with /PartitionKey as the partition key path that's configured on the container.我们目前每天编写大约 150,000 - 200,000 个与上述类似的文档,其中/PartitionKey作为在容器上配置的分区键路径。 The value of the PartitionKey is a randomly generated number in C#.net between 0 and 999. PartitionKey 的值是 C#.net 中随机生成的一个介于 0 到 999 之间的数字。

However, we are seeing daily hotspots where a single physical partition can hit a max of 2.5K - 4.5K RU/s and others are very low (around 200 RU/s).但是,我们看到每日热点,其中单个物理分区的最大值可以达到 2.5K - 4.5K RU/s,而其他的则非常低(大约 200 RU/s)。 This has a knock on to cost implications as we need to provision throughput for our largest utilised partition.这会影响成本,因为我们需要为最大的使用分区提供吞吐量。

The second factor is we're storing a fair bit of data, close to 1TB of documents, and we add a few GB each day.第二个因素是我们存储了相当多的数据,接近 1TB 的文档,我们每天增加几 GB。 As a result we have currently have around 40 physical partitions.因此,我们目前有大约 40 个物理分区。

Combining these two factors means we end up having to provision for at minimum somewhere between 120,000 - 184,000 RU/s.结合这两个因素意味着我们最终必须至少提供 120,000 - 184,000 RU/s 之间的某个地方。

I should mention that we barely ever need to query this data;我应该提一下,我们几乎不需要查询这些数据; apart from very occasional for ad-hoc manually constructed queries in Cosmos data explorer.除了在 Cosmos 数据浏览器中非常偶然的临时手动构造查询。

My question is... would we be a lot better off in terms of RU/s required and distribution of data by simply using the “id” column as our partition key (or a randomly generated GUID) - and then setting a sensible TTL so we don't have a continually growing dataset?我的问题是……通过简单地使用“id”列作为我们的分区键(或随机生成的 GUID),然后设置一个合理的 TTL,我们会在需要的 RU/s 和数据分布方面做得更好吗?所以我们没有不断增长的数据集?

I understand this would require us to re-create the collection.我知道这需要我们重新创建集合。

Thanks very much.非常感谢。

Max throughput per physical partition每个物理分区的最大吞吐量

While using the id or a GUID would give you better cardinality than the random number you have today, any query you run would be very expensive as it would always be cross-partition and over a huge amount of data.虽然使用 id 或 GUID 会为您提供比您今天拥有的随机数更好的基数,但您运行的任何查询都将非常昂贵,因为它总是跨分区并且需要处理大量数据。

I think a better choice would be to use a synthetic key that combines multiple properties that both have high cardinality and also are used to query for the data.我认为更好的选择是使用一个合成键,它结合了多个属性,这些属性既具有高基数,又用于查询数据。 Can learn more about these here, https://docs.microsoft.com/en-us/azure/cosmos-db/synthetic-partition-keys可以在此处了解有关这些的更多信息, https://docs.microsoft.com/en-us/azure/cosmos-db/synthetic-partition-keys

As far as TTL I would definitely set that for whatever retention you need for this data.至于 TTL,我肯定会为您需要的数据保留设置它。 Cosmos will TTL the data off with unused throughput so will never get in the way. Cosmos 将使用未使用的吞吐量对数据进行 TTL 处理,因此永远不会妨碍。

Lastly, you should also consider (if you haven't already) using a custom indexing policy and exclude any paths which are never queried for.最后,您还应该考虑(如果您还没有)使用自定义索引策略并排除任何从未查询过的路径。 Especially the "response" property since you say it is thousands of characters long.特别是“响应”属性,因为您说它有数千个字符长。 This can save considerable RU/s in write-heavy scenarios like yours.这可以在像您这样的大量写入场景中节省大量 RU/s。

From my experience what I see is cosmos tends to degrade with new data.根据我的经验,我看到宇宙会随着新数据而退化。 More data mean more physical partitons.更多的数据意味着更多的物理分区。 So you meed more throughput to be allocated to each of them .因此,您需要将更多的吞吐量分配给它们中的每一个。 Currently we are starting to archive old data into blob storage to avoid this kind of problems and keep the number of physical partition unchangeable.目前我们开始将旧数据归档到 blob 存储中,以避免此类问题并保持物理分区的数量不变。 We use cosmos as hot storage and then the old data go to blobs storage as cold storage.我们使用 cosmos 作为热存储,然后旧数据进入 blob 存储作为冷存储。 We reduce RU allocated to each physical partitions and we save money.我们减少了分配给每个物理分区的 RU,从而节省了资金。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM