Azure Cosmos DB:全球分布式多模型数据库

FreeGuideOnline 最新 2026-06-30

Azure Cosmos DB 全球分布式多模型数据库完全入门指南

什么是 Azure Cosmos DB?

Azure Cosmos DB 是微软提供的完全托管、全球分布式、多模型数据库服务。它专为现代应用设计,允许你在全球任意数量的 Azure 区域中无缝复制数据,并提供业界领先的吞吐量、延迟、可用性和一致性保障。不同于传统的关系型数据库,Cosmos DB 支持多种数据模型(文档、键值、图、列族),你可以使用自己熟悉的 API(SQL、MongoDB、Cassandra、Gremlin、Table)进行开发。

核心理念:将数据库基础结构的管理工作全部交给 Azure,开发者只需关注数据与应用逻辑,同时获得无限弹性扩展和全球触达能力。

为什么选择 Azure Cosmos DB?

  • 全球分布一键达成:只需点击按钮即可将数据复制到全球 50+ 个 Azure 区域,自动故障转移,最低延迟访问。
  • 多模型灵活选择:一套数据库引擎原生支持 JSON 文档、键值对、图关系和列族数据,适配不同业务场景。
  • SLA 保障的性能:任意规模都能保证 99.99% 的可用性,读写延迟在 10 毫秒以内(中位数),吞吐量按需缩放。
  • 无服务器与自动扩展:无需规划容量,可按请求单元(RU/s)弹性调整或选择无服务器模式,按实际用量付费。
  • 五种一致性级别:从强一致性到最终一致性,在性能与数据正确性之间精细权衡,无需牺牲可用性。
  • 集成 Azure 生态:与 Azure Functions、Azure Kubernetes Service、Event Hubs、Synapse Analytics 等原生集成,构建端到端方案。

核心概念与架构

全局分布与多区域写入

Cosmos DB 的资源层级为:Azure Cosmos DB 账户 → 数据库 → 容器。一个账户可以关联多个区域,每个区域都有完整的数据副本。你可以启用多区域写入,让应用在任何区域都能同时写入数据,由 Cosmos DB 内部处理冲突解决(基于最后写入者胜出或自定义冲突解决策略)。

当创建账户时,你需要选择:

  • 初始主区域
  • 要启用的额外区域(多区域读取)
  • 是否启用多区域写入

数据会在数分钟内复制到所有配置区域,并提供透明的自动故障转移。

多模型 API 一览

所有数据在底层以“原子记录序列”(ARS)存储,上层暴露不同 API 映射:

API 名称 数据模型 描述
Core (SQL) 文档 默认 API,使用类似 SQL 的查询语法操作 JSON 文档
MongoDB 文档 兼容 MongoDB 协议,轻松迁移现有 MongoDB 应用
Cassandra 宽列 兼容 Apache Cassandra 的 CQL 查询
Gremlin 基于属性图模型,使用 Gremlin 遍历语法
Table 键值 兼容 Azure Table Storage,键值对模式

选择 API 时需在账户创建时确定,一个账户只能使用一种 API(但可以通过不同账户满足不同模型需求)。

请求单元(RU)与性能

Cosmos DB 的性能成本通过**请求单元/秒(RU/s)**来度量。一个读 1 KB 文档的点读取大约消耗 1 RU,更复杂的查询或写入根据文档大小、索引策略和一致性级别消耗更多 RU。你可以以两种方式配置吞吐量:

  • 标准(预配置):手动设定 RU/s 容量,支持自动缩放,按小时计费。
  • 无服务器:无需管理容量,适合间歇性或低流量工作负载,按实际请求消耗付费。

分区与水平扩展

所有数据必须存储在容器内。容器中最关键的设置是分区键。Cosmos DB 利用分区键将数据分布到底层的多个物理分区,实现无限存储和吞吐量扩展。选择分区键时需确保:

  • 高基数(大量不同值,避免“热分区”)
  • 读/写请求均匀分布
  • 常见查询应尽量包含分区键以降低 RU 消耗

示例:如果容器存储用户订单,使用 userId 作为分区键通常是一个好选择。

动手实践:创建第一个 Cosmos DB 数据库

步骤 1:创建 Azure Cosmos DB 账户

  1. 登录 Azure 门户
  2. 搜索并选择“Azure Cosmos DB”,点击“创建”。
  3. 选择 API 类型。本教程选择 Core (SQL)
  4. 选择订阅、资源组,输入账户名称(全局唯一)。
  5. 选择位置(主区域)和容量模式(推荐无服务器用于测试)。
  6. 网络选项中,选择“所有网络”(开发测试)。
  7. 点击“审核+创建”并等待部署完成(约几分钟)。

步骤 2:添加数据库与容器

部署完成后,进入资源,点击“数据资源管理器”。选择“新建容器”:

  • 数据库 ID:ShopDB(可新建或使用已有)
  • 容器 ID:Orders
  • 分区键:/customerId(以斜杠开头,表示 JSON 中的 customerId 字段)
  • 容器吞吐量:若使用预配置模式,可选 400 RU/s(自动缩放);无服务器则无需设置

步骤 3:插入和查询数据

在数据资源管理器中,选中 Orders 容器,选择“项”。点击“新建项”并粘贴以下 JSON 文档:

{
  "id": "order1",
  "customerId": "cust100",
  "items": [
    { "productId": "p1", "name": "Laptop", "price": 999.99 },
    { "productId": "p2", "name": "Mouse", "price": 24.99 }
  ],
  "total": 1024.98,
  "orderDate": "2025-01-15T10:30:00Z"
}

点击“保存”。再插入第二条以不同 customerId 结尾的文档以观察分区行为。

现在打开“新建 SQL 查询”,执行:

SELECT * FROM c WHERE c.customerId = 'cust100'

此查询将高效地路由到对应物理分区,消耗较少 RU。

再试试跨分区的聚合查询(消耗可能较高):

SELECT COUNT(1) FROM c

深入理解一致性级别

Cosmos DB 提供了从强到最终的五种一致性模型,让开发者可以在数据一致性和读写延迟/可用性之间取舍:

一致性级别 说明 适用场景
读取保证返回最新已提交的写入,性能最低但无数据歧义 金融交易,库存扣减
有限过时 读取可能滞后写入若干版本或时间间隔,可预先设定滞后上限 跨区域协作,社交网络
会话(默认) 在同一客户端会话中保证单调读和写后读,跨会话可能看到过时数据 大多数 Web/移动应用
一致前缀 读取保证不会看到乱序写入,但可能落后于最新写入 事件流,消息队列
最终 无顺序保证,最终达到一致,读取延迟和可用性最高 用户评论、SEO 计数

创建账户时可选择默认一致性级别,账户下所有数据库和容器继承该设置,除非单独覆盖。对于初学者,建议保持“会话”一致性,它在绝大多数场景下提供了良好平衡。

查询文档数据(SQL API)

SQL API 使用类似 SQL 的查询语言,但专门针对 JSON 无模式数据设计。以下示例基于前述 Orders 容器。

基本查询

-- 选择所有订单
SELECT * FROM c

-- 根据 ID 点查
SELECT * FROM c WHERE c.id = 'order1'

-- 过滤与投影
SELECT c.total, c.orderDate FROM c WHERE c.total > 500

操作用户数组与子文档

当文档内包含数组时,可以使用 JOIN 展开:

-- 列出每个订单中的每个商品
SELECT o.id AS orderId, item.name, item.price
FROM c
JOIN item IN c.items
WHERE c.customerId = 'cust100'

内置函数与排序

-- 使用字符串函数
SELECT UPPER(c.id) FROM c

-- 排序
SELECT c.id, c.total FROM c ORDER BY c.total DESC

参数化查询防止注入

在生产代码中始终使用参数化查询。以 .NET SDK 为例:

var query = new QueryDefinition("SELECT * FROM c WHERE c.customerId = @custId")
    .WithParameter("@custId", "cust100");

以代码操控 Cosmos DB(.NET 示例)

环境准备

使用 NuGet 安装 Microsoft.Azure.Cosmos 包。

dotnet add package Microsoft.Azure.Cosmos

连接与初始化

using Microsoft.Azure.Cosmos;

string endpoint = "https://your-account.documents.azure.com:443/";
string key = "your-primary-key";
CosmosClient client = new CosmosClient(endpoint, key);
Database database = client.GetDatabase("ShopDB");
Container container = database.GetContainer("Orders");

创建文档

dynamic order = new
{
    id = "order2",
    customerId = "cust200",
    total = 150.75,
    orderDate = DateTime.UtcNow
};
ItemResponse<dynamic> response = await container.CreateItemAsync(order, new PartitionKey("cust200"));

读取文档

ItemResponse<dynamic> readResponse = await container.ReadItemAsync<dynamic>(
    "order2", new PartitionKey("cust200"));
Console.WriteLine(readResponse.Resource.total);

更新文档

dynamic existing = readResponse.Resource;
existing.total = 180.00;
await container.ReplaceItemAsync(existing, "order2", new PartitionKey("cust200"));

查询文档

var query = new QueryDefinition("SELECT * FROM c WHERE c.customerId = @custId")
    .WithParameter("@custId", "cust200");
using FeedIterator<dynamic> iterator = container.GetItemQueryIterator<dynamic>(query);
while (iterator.HasMoreResults)
{
    FeedResponse<dynamic> response = await iterator.ReadNextAsync();
    foreach (var item in response)
    {
        Console.WriteLine(item);
    }
}

索引策略与性能优化

默认情况下,Cosmos DB 自动为所有文档的所有属性建立索引,无需手动处理模式或索引。但对于特定场景,可以自定义索引策略以降低成本或提升写入速度。

示例:只想对 customerIdorderDate 建立索引,排除其他字段:

{
    "indexingMode": "consistent",
    "includedPaths": [
        { "path": "/customerId/?" },
        { "path": "/orderDate/?" }
    ],
    "excludedPaths": [
        { "path": "/*" }
    ]
}

通过 Azure 门户或 SDK 在容器级别设置。在优化前,评估是否真正需要排除索引,因为默认索引已经非常高效。

其他性能要点:

  • 使用点读取(ReadItemAsync)代替 SELECT * WHERE id = ... 查询,点读取约消耗 1 RU,且延迟更低。
  • 尽量让查询包含分区键,避免跨分区查询。
  • 为高频查询添加必要的复合索引。

监控与成本管理

Azure Monitor 指标

在 Azure 门户的 Cosmos DB 资源中,可以查看关键指标:

  • 总请求数:按状态码和区域拆分
  • 请求单元消耗:平均与峰值
  • 存储用量:数据和索引
  • 可用性:服务可用性百分比

可通过“警报”功能设置当 RU 消耗超过阈值或出现 429 错误时自动通知。

控制 RU 成本

  • 评估实际 RUs 消耗:使用 SDK 返回的 RequestCharge 属性。
  • 对无服务器模式,每个请求都有 RU 消耗,注意复杂查询或大文档写入的成本。
  • 使用自动化缩放,设定最大 RU/s 防止意外高价。
  • 定期清理陈旧数据或归档到冷存储(如 Azure Blob + Data Factory)。

常见应用场景

  • 物联网遥测数据:利用 Cassandra API 或 SQL API 存储大量时序数据,按设备 ID 分区。
  • 电子商务目录与购物车:SQL API 的灵活文档模型完美匹配商品结构,会话一致性保证用户看到自己的更新。
  • 社交图谱:Gremlin API 构建用户关注关系和推荐路径。
  • 游戏状态管理:低延迟全球分布确保各地玩家实时数据同步。
  • 无服务器后端:与 Azure Functions 搭配,几乎零管理成本实现轻量 API。

最佳实践建议

  1. 分区键设计要深思熟虑:一次性选定后无法更改。选择读取和写入均均匀分布的字段,避免产生“热点”。常见模式:用户 ID、设备 ID、租户 ID。
  2. 对于重要数据开启多区域写入或多区域读取:提升灾难恢复能力和本地访问延迟。
  3. 始终使用 SDK 的重试和断路机制:SDK 内置处理 429(请求速率限制)的重试逻辑,无需手动实现。
  4. 不要在生产中频繁调用 CreateDatabaseIfNotExistsCreateContainerIfNotExists,这些管理操作消耗 RUs,应仅在初始化时调用。
  5. 使用最新版本的 SDK:微软持续优化性能和修复问题。
  6. 安全方面:使用 RBAC 和资源令牌而非主密钥分发应用权限;开启 IP 防火墙和虚拟网络服务终结点。
  7. 数据生命周期管理:利用生存时间(TTL)自动删除过期文档,节省存储成本。

下一步学习路径

  • 官方文档:Azure Cosmos DB 文档
  • 深入学习:分区与数据建模指南,多区域写入冲突解决模式。
  • 动手实验:使用 Cosmos DB 与 Azure Functions 构建无服务器 API。
  • 认证路径:AZ-204:为 Azure 开发解决方案,其中包含 Cosmos DB 模块。

结论

Azure Cosmos DB 不仅是一个数据库,更是面向互联网规模应用的分布式数据平台。它消除了传统数据库在全球扩展、多模型适配和高可用保障方面的复杂性。通过本教程,你已掌握创建账户、设计分区、进行查询以及利用 .NET SDK 进行开发的基本技能。现在,你可以开始构建响应速度快、全球化且始终可用的新一代云原生应用了。