Bootiful Azure:使用 CosmosDB 進行全球規模資料存取 (3/6)

工程 | Josh Long | 2019 年 1 月 10 日 | ...

這是由六部分組成的系列文章的第 3 部分,每週一和週四都會發布新文章,介紹 Microsoft Azure 給 Spring 開發人員。 如果沒有 Microsoft 的 Asir Vedamuthu Selvasingh、Yitao Dong、Bruno Borges、Brian Benz 和 Theresa Nguyen 的投入,我就無法完成這篇文章。 您可以在 Github 上找到此系列的程式碼。 當您閱讀這些文章時,歡迎在 Twitter (@starbuxman) 上與我聯繫,提供任何回饋或問題。 您也可以在我的 Spring Tips (@SpringTipsLive) 文章 Bootiful Azure 中了解更多關於 Microsoft Azure 的資訊。

以下是所有文章

我可以聽到你在想 - 是的,即使是你最微弱的想法也逃不過我的耳朵! - 你們喜歡 Microsoft SQL Server,就像其他開發人員一樣,但你們可以在任何平台(雲端或其他平台)上自行運行它! 你們不需要 Microsoft 來為你們運行它。 對此我說,「是的!」(但 Microsoft 為我們運行它,這確實很好,不是嗎?)

我承認這一點。 Azure 可以為你做什麼? 你不必再尋找 Microsoft Azure CosmosDB 以外的任何東西。 CosmosDB 指的是一組技術。 它描述了一個可以以多種方式使用的單一產品。 它是一個單一、多模型、多模式的資料庫,支援文件資料、SQL 查詢、圖形資料存取等等。

根據 產品網頁:CosmosDB 從一開始就以全球分佈和水平擴展為核心而構建。 保證在第 99 個百分位數時的讀取和寫入延遲為個位數毫秒,並保證在全球任何地方透過多宿主實現 99.999% 的高可用性——所有這些都以業界領先、全面的服務等級協定 (SLA) 作為後盾。

項目和容器

在內部,CosmosDB 將「項目」儲存在「容器」中。 但您不必一定將項目或容器視為概念來處理,因為它們會在使用資料模型的語言中呈現,以供您使用資料。 例如,如果您將它用作文件儲存,如 MongoDB,則項目將被映射到集合中的文件。

容器被分組到資料庫中,資料庫是容器之上的一種命名空間。 容器強制執行唯一鍵約束,以確保資料的完整性。 但容器的功能遠不止於此。 您可以向每個容器請求一個變更的 feed; 您可以使用此 feed 來支援變更資料擷取 (CDC) 方案。 您可以使用此 feed 進行事件溯源。 feed 本身是持久儲存的,因此您可以根據需要重播變更。

您也可以為容器指定生存時間 (TTL) 值,讓 CosmosDB 在一段時間後自動刪除現有記錄。 您也可以覆寫特定項目的 TTL。

多模型、多範例資料儲存

首先,CosmosDB 是無架構的。 在使用它時請牢記這一點 - 如果你沒有做好準備,它可能會產生一些重要的影響。

CosmosDB 支援一種多模型、多範例的方法來構建應用程式。 客戶端可以使用 HTTP REST API 並使用類似 SQL 的語言來驅動它以進行查詢。 您也可以使用 SQL API 建立、更新和刪除容器。

您可以使用 MongoDB API 與 CosmosDB 通訊,支援集合作為容器,文件作為項目。

您可以使用 Gremlin API 與之通訊,支援圖形和容器,以及節點和邊緣作為項目。 根據 Gremlin 網站,「Gremlin 是 Apache TinkerPop 的圖形遍歷語言。 Gremlin 是一種函數式、資料流語言,它使用戶能夠簡潔地表達對其應用程式的屬性圖進行複雜的遍歷(或查詢)。” 所以,它基本上是一種在圖形中遍歷資料的方法。

您可以使用 Cassandra API 與 CosmosDB 通訊,支援表作為容器,行作為項目。 Cassandra API 甚至支援 Cassandra 查詢語言 (CQL)。

也可以使用 Azure 表格儲存 API 與之通訊,支援表格作為容器,項目作為...嗯...項目

CosmosDB 還嵌入了一個 JavaScript 引擎,因此您可以使用 JavaScript 來定義觸發器、使用者定義的函數(可以從 SQL 查詢語言中呼叫和擴充)和儲存程序。 儲存程序可以在單個符合 ACID 標準的交易中管理多個操作。

在 Microsoft Azure 上配置 CosmosDB

首先,您需要建立一個(可能在地理上分佈的)CosmosDB 實例,然後在其中建立一個資料庫實例。 然後,您需要建立一個集合來儲存記錄。 這是一個腳本。 唯一值得注意的是,我們不必像在 SQL Server 範例中那樣指定防火牆例外。 它只是有效 (TM)。

#!/bin/bash

# the name of the resource group
export rg=$1
export adminlogin=${rg}-cosmosdb

location='southcentralus'
accountname=${adminlogin}
databasename=bootiful
containername=reservations

# Create a SQL API Cosmos DB account with session consistency and multi-master enabled
az cosmosdb create \
    --resource-group $rg \
    --name $adminlogin \
    --kind GlobalDocumentDB \
    --default-consistency-level "Session" 

# Create a database
az cosmosdb database create \
    --resource-group $rg \
    --name $adminlogin \
    --db-name $databasename

# Create a SQL API container with a partition key and 1000 RU/s
az cosmosdb collection create \
    --resource-group $rg \
    --collection-name $containername \
    --name $adminlogin \
    --db-name $databasename \
    --partition-key-path /id \
    --throughput 1000

在這個腳本中,我們可以指定希望新資料庫可用的區域。 您也可以透過方便的地圖從 Azure Portal 方便地執行此操作。 只需點擊一個區域,它就會處理其餘的事情!

另請注意稍後使用的結果 $adminlogin 值。

現在,您需要取得所需的配置字串,以便將您的應用程式連接到您的新資料庫及其資料。 您可以篩選先前指令的輸出,但以下咒語會容易得多。

az cosmosdb list-keys --resource-group bootiful --name bootiful-cosmosdb

您需要記住先前指令中產生的 primaryMasterKey 屬性的值,以便稍後連接到 CosmosDB。

將 CosmosDB 引入您的 Spring 應用程式

讓我們看看 CosmosDB 在 Spring 應用程式中的使用情況。 理論上,您可以透過上述技術(如 MongoDB 和 Cassandra)的適當抽象來與 CosmosDB 通訊。 我更喜歡使用 Spring Data CosmosDB 抽象,您需要將其啟動器依賴項添加到建置檔案中。

CosmosDB 在歷史上被稱為 DocumentDB。 如果您看到這些名稱,它們幾乎是可以互換的。 由於歷史原因,您需要將引用舊專案名稱 com.microsoft.azure:azure-documentdb-spring-boot-starter 的 Maven 啟動器依賴項新增到您的建置檔案中。

然後您必須配置相關的連接資訊。 您可以將以下內容添加到應用程式的 application.properties 檔案中。

azure.documentdb.database=bootiful
azure.documentdb.key=THIS_IS_THE_KEY_FROM_BEFORE
azure.documentdb.uri=https://ADMINLOGIN.documents.azure.com:443/

database 屬性是指邏輯 CosmosDB 實例(bootiful-cosmosdb,這是我們在腳本中使用 $adminlogin 指定的)中的資料庫(bootiful,因為我們將資源組名稱用作資料庫名稱)。 鍵是指 az cosmosdb list-keys 指令中的 primaryMasterKey 值。 將屬性值替換為相關且適當的字串值。

我在 macOS 系統上可以正常執行這個專案,但在 Ubuntu 18.10 系統上執行時遇到了一個奇怪的問題。CosmosDB 的 Spring 客戶端函式庫在收集遙測資料時出現了一個奇怪的現象,導致 NPE (NullPointerException)。如果遇到這個問題,請將以下內容添加到 src/main/resources/application.properties 以停用遙測功能。

cosmosdb.telemetryAllowed=false 

接下來,您應該定義一個 Spring Data 實體,以對應到 CosmosDB 集合 (collection) 中的記錄,名稱為 reservations

package com.example.bootifulazure;

import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "reservations")
class Reservation {

        @PartitionKey
        private String id;
        private String name;
}

基本上,這看起來就像您之前看過的任何其他使用 Lombok 註解的 POJO (Plain Old Java Object)。特別要注意的是,此實體使用 Spring Data CosmosDB 模組中的 @Document 來指定此實體對應的 reservations 集合。此實體使用 CosmosDB 特定的註解 @PartitionKey,向資料庫發出訊號,指示在決定如何對容器中可能相關的資料進行分割 (邏輯上或物理上) 時,應使用哪個欄位作為分割區金鑰 (Partition Key)。最好使用 String 作為分割區金鑰。在行星級別的分散式系統中,單調遞增的主鍵不是一個好主意!

現在,基於 DocumentDbRepository 定義 Spring Data repository。

package com.example.bootifulazure;

import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;

interface ReservationRepository extends DocumentDbRepository<Reservation, String> {
}

DocumentDbRepository 可能對您來說是新的,但其他部分應該很容易理解。

package com.example.bootifulazure;

import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.stream.Stream;

@Log4j2
@Component
class CosmosDbDemo {

    private final ReservationRepository rr;

    CosmosDbDemo(ReservationRepository rr) {
        this.rr = rr;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void demo() throws Exception {

        this.rr.deleteAll();

        Stream.of("A", "B", "C")
            .map(name -> new Reservation(UUID.randomUUID().toString(), name))
            .map(this.rr::save)
            .forEach(log::info);

    }
}

取得 Spring 電子報

隨時關注 Spring 電子報

訂閱

搶先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進制檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部