Migrowanie z bazy danych CouchBase do usługi Azure Cosmos DB for NoSQL
DOTYCZY: NoSQL
Azure Cosmos DB to skalowalna, globalnie rozproszona, w pełni zarządzana baza danych. Zapewnia gwarantowany dostęp do danych z małym opóźnieniem. Aby dowiedzieć się więcej na temat usługi Azure Cosmos DB, zobacz artykuł z omówieniem. Ten artykuł zawiera instrukcje dotyczące migrowania aplikacji Java połączonych z bazą danych Couchbase do konta interfejsu API dla noSQL w usłudze Azure Cosmos DB.
Różnice w nomenklaturze
Poniżej przedstawiono kluczowe funkcje, które działają inaczej w usłudze Azure Cosmos DB w porównaniu z bazą danych Couchbase:
Couchbase | Azure Cosmos DB |
---|---|
Serwer Couchbase | Klient |
Wiadro | baza danych |
Wiadro | Kontener/kolekcja |
Dokument JSON | Element/dokument |
Podstawowe różnice
Usługa Azure Cosmos DB ma pole "ID" w dokumencie, natomiast couchbase ma identyfikator jako część zasobnika. Pole "ID" jest unikatowe w obrębie partycji.
Usługa Azure Cosmos DB skaluje się przy użyciu techniki partycjonowania lub fragmentowania. Oznacza to, że dzieli dane na wiele fragmentów/partycji. Te partycje/fragmenty są tworzone na podstawie podanej właściwości klucza partycji. Możesz również wybrać klucz partycji, aby zoptymalizować operacje odczytu, a także operacje zapisu lub zoptymalizowane pod kątem odczytu/zapisu. Aby dowiedzieć się więcej, zobacz artykuł dotyczący partycjonowania .
W usłudze Azure Cosmos DB nie jest wymagane, aby hierarchia najwyższego poziomu oznaczała kolekcję, ponieważ nazwa kolekcji już istnieje. Ta funkcja sprawia, że struktura JSON jest prostsza. Poniżej przedstawiono przykład pokazujący różnice w modelu danych między bazą couchbase i usługą Azure Cosmos DB:
Couchbase: identyfikator dokumentu = "99FF4444"
{ "TravelDocument": { "Country":"India", "Validity" : "2022-09-01", "Person": { "Name": "Manish", "Address": "AB Road, City-z" }, "Visas": [ { "Country":"India", "Type":"Multi-Entry", "Validity":"2022-09-01" }, { "Country":"US", "Type":"Single-Entry", "Validity":"2022-08-01" } ] } }
Azure Cosmos DB: zapoznaj się z "identyfikatorem" w dokumencie, jak pokazano poniżej
{ "id" : "99FF4444", "Country":"India", "Validity" : "2022-09-01", "Person": { "Name": "Manish", "Address": "AB Road, City-z" }, "Visas": [ { "Country":"India", "Type":"Multi-Entry", "Validity":"2022-09-01" }, { "Country":"US", "Type":"Single-Entry", "Validity":"2022-08-01" } ] }
Obsługa zestawu JAVA SDK
Usługa Azure Cosmos DB ma następujące zestawy SDK (software development kit) do obsługi różnych struktur Języka Java:
- Asynchroniczny zestaw SDK
- Spring Boot SDK
W poniższych sekcjach opisano, kiedy należy używać każdego z tych zestawów SDK. Rozważmy przykład, w którym mamy trzy typy obciążeń:
Couchbase jako repozytorium dokumentów i zapytania niestandardowe oparte na danych spring
Jeśli migrowanie obciążenia jest oparte na zestawie SDK platformy Spring Boot, możesz wykonać następujące czynności:
Dodaj element nadrzędny do pliku POM.xml:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> </parent>
Dodaj właściwości do pliku POM.xml:
<azure.version>2.1.6</azure.version>
Dodaj zależności do pliku POM.xml:
<dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-cosmosdb-spring-boot-starter</artifactId> <version>2.1.6</version> </dependency>
Dodaj właściwości aplikacji w obszarze zasobów i określ następujące informacje. Pamiętaj, aby zastąpić parametry adresu URL, klucza i nazwy bazy danych:
azure.cosmosdb.uri=<your-cosmosDB-URL> azure.cosmosdb.key=<your-cosmosDB-key> azure.cosmosdb.database=<your-cosmosDB-dbName>
Zdefiniuj nazwę kolekcji w modelu. Możesz również określić dalsze adnotacje. Na przykład identyfikator, klucz partycji, aby oznaczyć je jawnie:
@Document(collection = "mycollection") public class User { @id private String id; private String firstName; @PartitionKey private String lastName; }
Poniżej przedstawiono fragmenty kodu dla operacji CRUD:
Operacje wstawiania i aktualizowania
Gdzie _repo jest obiektem repozytorium, a dokument jest obiektem klasy POJO. Możesz użyć .save
polecenia , aby wstawić lub upsert (jeśli dokument z określonym identyfikatorem został znaleziony). Poniższy fragment kodu pokazuje, jak wstawić lub zaktualizować obiekt dokumentu:
_repo.save(doc);
Operacja usuwania
Rozważmy następujący fragment kodu, w którym obiekt dokumentu będzie miał obowiązkowy identyfikator i klucz partycji, aby zlokalizować i usunąć obiekt:
_repo.delete(doc);
Operacja odczytu
Dokument można odczytać z kluczem partycji lub bez jego określania. Jeśli nie określisz klucza partycji, będzie on traktowany jako zapytanie obejmujące wiele partycji. Rozważmy następujące przykłady kodu, najpierw wykonasz operację przy użyciu pola identyfikatora i klucza partycji. W drugim przykładzie użyto zwykłego pola i bez określania pola klucza partycji.
_repo.findByIdAndName(objDoc.getId(),objDoc.getName());
_repo.findAllByStatus(objDoc.getStatus());
Teraz możesz używać aplikacji z usługą Azure Cosmos DB. Kompletny przykładowy kod dla przykładu opisanego w tym dokumentacji jest dostępny w repozytorium GitHub CouchbaseToCosmosDB-SpringCosmos .
Couchbase jako repozytorium dokumentów i używanie zapytań N1QL
Zapytania N1QL to sposób definiowania zapytań w bazie couchbase.
Zapytanie N1QL | Zapytanie usługi Azure Cosmos DB |
---|---|
SELECT META(TravelDocument ).id AS id, TravelDocument .* FROM TravelDocument WHERE _type = "com.xx.xxx.xxx.xxxx " and country = 'India' and ANY m in Visas SATISFIES m.type == 'Multi-Entry' and m.Country IN ['India', Bhutan'] ORDER BY Validity DESC LIMIT 25 OFFSET 0 |
SELECT c.id,c FROM c JOIN m in c.country='India' WHERE c._type = " com.xx.xx.xx.xxx.xxx.xxxx" and c.country = 'India' and m.type = 'Multi-Entry' and m.Country IN ('India', 'Bhutan') ORDER BY c.Validity DESC OFFSET 0 LIMIT 25 |
W zapytaniach N1QL można zauważyć następujące zmiany:
Nie musisz używać słowa kluczowego META ani odwoływać się do dokumentu pierwszego poziomu. Zamiast tego możesz utworzyć własne odwołanie do kontenera. W tym przykładzie uznaliśmy go za "c" (może to być wszystko). To odwołanie jest używane jako prefiks dla wszystkich pól pierwszego poziomu. Przykład, c.id, kraj c.itp.
Zamiast "ANY" można teraz wykonać sprzężenie w dokumentach podrzędnych i odwoływać się do niego za pomocą dedykowanego aliasu, takiego jak "m". Po utworzeniu aliasu dla dokumentu podrzędnego należy użyć aliasu. Na przykład m.Country.
Sekwencja przesunięcia różni się w zapytaniu usługi Azure Cosmos DB, najpierw musisz określić PRZESUNIĘCIE, a następnie LIMIT. Zaleca się, aby nie używać zestawu Spring Data SDK, jeśli używasz maksymalnych zapytań zdefiniowanych przez użytkownika, ponieważ może mieć niepotrzebne obciążenie po stronie klienta podczas przekazywania zapytania do usługi Azure Cosmos DB. Zamiast tego mamy bezpośredni zestaw JAVA SDK asynchroniczny, który w tym przypadku może być używany znacznie wydajnie.
Operacja odczytu
Użyj zestawu Async Java SDK, wykonując następujące czynności:
Skonfiguruj następującą zależność do pliku POM.xml:
<!-- https://mvnrepository.com/artifact/com.microsoft.azure/azure-cosmosdb --> <dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-cosmos</artifactId> <version>3.0.0</version> </dependency>
Utwórz obiekt połączenia dla usługi Azure Cosmos DB przy użyciu
ConnectionBuilder
metody, jak pokazano w poniższym przykładzie. Upewnij się, że ta deklaracja została umieszczona w fasoli, tak aby następujący kod został wykonany tylko raz:ConnectionPolicy cp=new ConnectionPolicy(); cp.connectionMode(ConnectionMode.DIRECT); if(client==null) client= CosmosClient.builder() .endpoint(Host)//(Host, PrimaryKey, dbName, collName).Builder() .connectionPolicy(cp) .key(PrimaryKey) .consistencyLevel(ConsistencyLevel.EVENTUAL) .build(); container = client.getDatabase(_dbName).getContainer(_collName);
Aby wykonać zapytanie, należy uruchomić następujący fragment kodu:
Flux<FeedResponse<CosmosItemProperties>> objFlux= container.queryItems(query, fo);
Teraz za pomocą powyższej metody można przekazać wiele zapytań i wykonać bez żadnych problemów. Jeśli wymagane jest wykonanie jednego dużego zapytania, które można podzielić na wiele zapytań, spróbuj wykonać poniższy fragment kodu zamiast poprzedniego:
for(SqlQuerySpec query:queries)
{
objFlux= container.queryItems(query, fo);
objFlux .publishOn(Schedulers.elastic())
.subscribe(feedResponse->
{
if(feedResponse.results().size()>0)
{
_docs.addAll(feedResponse.results());
}
},
Throwable::printStackTrace,latch::countDown);
lstFlux.add(objFlux);
}
Flux.merge(lstFlux);
latch.await();
}
Za pomocą poprzedniego kodu można uruchamiać zapytania równolegle i zwiększać liczbę rozproszonych wykonań w celu optymalizacji. Ponadto można również uruchomić operacje wstawiania i aktualizacji:
Operacja wstawiania
Aby wstawić dokument, uruchom następujący kod:
Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);
Następnie subskrybuj usługę Mono jako:
CountDownLatch latch=new CountDownLatch(1);
objMono .subscribeOn(Schedulers.elastic())
.subscribe(resourceResponse->
{
if(resourceResponse.statusCode()!=successStatus)
{
throw new RuntimeException(resourceResponse.toString());
}
},
Throwable::printStackTrace,latch::countDown);
latch.await();
Operacja upsert
Operacja upsert wymaga określenia dokumentu, który ma zostać zaktualizowany. Aby pobrać pełny dokument, możesz użyć fragmentu kodu wymienionego w operacji odczytu nagłówka, a następnie zmodyfikować wymagane pola. Poniższy fragment kodu upertuje dokument:
Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);
Następnie zasubskrybuj plik mono. Zapoznaj się z fragmentem kodu subskrypcji mono w operacji wstawiania.
Operacja usuwania
Wykonanie operacji usuwania następującego fragmentu kodu:
CosmosItem objItem= container.getItem(doc.Id, doc.Tenant);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);
Następnie zasubskrybuj mono fragment kodu subskrypcji w operacji wstawiania. Kompletny przykładowy kod jest dostępny w repozytorium GitHub CouchbaseToCosmosDB-AsyncInSpring .
Couchbase jako para klucz/wartość
Jest to prosty typ obciążenia, w którym można wykonywać wyszukiwania zamiast zapytań. Wykonaj następujące kroki dla par klucz/wartość:
Rozważ użycie wartości "/ID" jako klucza podstawowego, co gwarantuje, że możesz wykonać operację wyszukiwania bezpośrednio w określonej partycji. Utwórz kolekcję i określ wartość "/ID" jako klucz partycji.
Wyłącz indeksowanie całkowicie. Ponieważ wykonasz operacje wyszukiwania, nie ma sensu przenoszenia obciążenia indeksowania. Aby wyłączyć indeksowanie, zaloguj się do witryny Azure Portal, przejdź do konta usługi Azure Cosmos DB. Otwórz Eksploratora danych, wybierz bazę danych i kontener. Otwórz kartę Skalowanie i ustawienia i wybierz zasady indeksowania. Obecnie zasady indeksowania wyglądają następująco:
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ] }
Zastąp powyższe zasady indeksowania następującymi zasadami:
{ "indexingMode": "none", "automatic": false, "includedPaths": [], "excludedPaths": [] }
Użyj poniższego fragmentu kodu, aby utworzyć obiekt połączenia. Obiekt połączenia (do umieszczenia w @Bean obiekcie lub ustawić go jako statyczny):
ConnectionPolicy cp=new ConnectionPolicy(); cp.connectionMode(ConnectionMode.DIRECT); if(client==null) client= CosmosClient.builder() .endpoint(Host)//(Host, PrimaryKey, dbName, collName).Builder() .connectionPolicy(cp) .key(PrimaryKey) .consistencyLevel(ConsistencyLevel.EVENTUAL) .build(); container = client.getDatabase(_dbName).getContainer(_collName);
Teraz możesz wykonać operacje CRUD w następujący sposób:
Operacja odczytu
Aby odczytać element, użyj następującego fragmentu kodu:
CosmosItemRequestOptions ro=new CosmosItemRequestOptions();
ro.partitionKey(new PartitionKey(documentId));
CountDownLatch latch=new CountDownLatch(1);
var objCosmosItem= container.getItem(documentId, documentId);
Mono<CosmosItemResponse> objMono = objCosmosItem.read(ro);
objMono .subscribeOn(Schedulers.elastic())
.subscribe(resourceResponse->
{
if(resourceResponse.item()!=null)
{
doc= resourceResponse.properties().toObject(UserModel.class);
}
},
Throwable::printStackTrace,latch::countDown);
latch.await();
Operacja wstawiania
Aby wstawić element, możesz wykonać następujący kod:
Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);
Następnie subskrybuj plik mono jako:
CountDownLatch latch=new CountDownLatch(1);
objMono.subscribeOn(Schedulers.elastic())
.subscribe(resourceResponse->
{
if(resourceResponse.statusCode()!=successStatus)
{
throw new RuntimeException(resourceResponse.toString());
}
},
Throwable::printStackTrace,latch::countDown);
latch.await();
Operacja upsert
Aby zaktualizować wartość elementu, zapoznaj się z poniższym fragmentem kodu:
Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);
Następnie zasubskrybuj mono fragment kodu subskrypcji w operacji wstawiania.
Operacja usuwania
Użyj następującego fragmentu kodu, aby wykonać operację usuwania:
CosmosItem objItem= container.getItem(id, id);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);
Następnie zasubskrybuj mono fragment kodu subskrypcji w operacji wstawiania. Kompletny przykładowy kod jest dostępny w repozytorium GitHub CouchbaseToCosmosDB-AsyncKeyValue .
Migracja danych
Migrowanie danych za pomocą usługi Azure Data Factory . Jest to najbardziej zalecana metoda migracji danych. Aby uzyskać szczegółowe instrukcje, zobacz artykuł Dotyczący źródła jako bazy danych Couchbase i ujścia jako azure Cosmos DB for NoSQL. Aby uzyskać szczegółowe instrukcje, zobacz artykuł Dotyczący łącznika usługi Azure Cosmos DB Data Factory.
Następne kroki
- Aby przeprowadzić testowanie wydajności, zobacz artykuł Performance and scale testing with Azure Cosmos DB (Testowanie wydajności i skalowania za pomocą usługi Azure Cosmos DB ).
- Aby zoptymalizować kod, zobacz artykuł Porady dotyczące wydajności dla usługi Azure Cosmos DB .
- Zapoznaj się z zestawem JAVA Async V3 SDK, dokumentacją zestawu SDK w repozytorium GitHub.