다음을 통해 공유


CouchBase에서 Azure Cosmos DB for NoSQL로 마이그레이션

Azure Cosmos DB는 완벽하게 확장 가능한 글로벌 분산형 데이터베이스입니다. 데이터에 짧은 지연 시간으로 액세스할 수 있도록 보장합니다. Azure Cosmos DB에 대한 자세한 내용은 개요 문서를 참조하세요. 이 문서에서는 Couchbase에 연결된 Java 애플리케이션을 Azure Cosmos DB의 API for NoSQL 계정으로 마이그레이션하는 지침을 제공합니다.

명명법의 차이점

다음은 Couchbase와 비교할 때 Azure Cosmos DB에서 다르게 작동하는 주요 기능입니다.

Couchbase Azure Cosmos DB (애저 코스모스 DB)
Couchbase 서버 어카운트
버킷 데이터베이스
버킷 컨테이너/컬렉션
JSON 문서 항목/문서

주요 차이점

  • Azure Cosmos DB에는 문서 내의 "ID" 필드가 있는 반면 Couchbase에는 버킷의 일부로 ID가 있습니다. "ID" 필드는 파티션 전체에서 고유합니다.

  • Azure Cosmos DB는 파티셔닝 또는 셰딩 기술을 사용하여 크기를 조정합니다. 즉, 데이터를 여러 분할/파티션으로 분할합니다. 이러한 파티션/분할된 데이터베이스는 사용자가 제공하는 파티션 키 속성을 기반으로 만들어집니다. 파티션 키를 선택하여 읽기 및 쓰기 작업 또는 읽기/쓰기 최적화를 최적화할 수 있습니다. 자세한 내용은 분할 문서를 참조하세요.

  • Azure Cosmos DB에서는 컬렉션 이름이 이미 존재하기 때문에 최상위 계층 구조에서 컬렉션을 나타낼 필요가 없습니다. 이 기능을 사용하면 JSON 구조가 더 간단해집니다. 다음은 Couchbase와 Azure Cosmos DB 간의 데이터 모델 차이를 보여 주는 예제입니다.

    Couchbase: 문서 ID = "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: 아래와 같이 문서 내에서 "ID"를 참조하세요.

    {
      "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"
          }
        ]
      }
    

Java SDK 지원

Azure Cosmos DB에는 다양한 Java 프레임워크를 지원하기 위해 다음과 같은 SDK(소프트웨어 개발 키트)가 있습니다.

  • 비동기 SDK
  • Spring Boot SDK

다음 섹션에서는 이러한 각 SDK를 사용하는 시기를 설명합니다. 다음 세 가지 유형의 워크로드가 있는 예제를 생각해 보세요.

문서 리포지토리로서의 Couchbase 및 Spring 데이터 기반 사용자 지정 쿼리

마이그레이션하는 워크로드가 Spring Boot 기반 SDK를 기반으로 하는 경우 다음 단계를 사용할 수 있습니다.

  1. POM.xml 파일에 부모를 추가합니다.

    <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.1.5.RELEASE</version>
       <relativePath/>
    </parent>
    
  2. POM.xml 파일에 속성을 추가합니다.

    <azure.version>2.1.6</azure.version>
    
  3. POM.xml 파일에 종속성을 추가합니다.

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-cosmosdb-spring-boot-starter</artifactId>
        <version>2.1.6</version>
    </dependency>
    
  4. 리소스 아래에 애플리케이션 속성을 추가하고 다음을 지정합니다. URL, 키 및 데이터베이스 이름 매개 변수를 바꿔야 합니다.

       azure.cosmosdb.uri=<your-cosmosDB-URL>
       azure.cosmosdb.key=<your-cosmosDB-key>
       azure.cosmosdb.database=<your-cosmosDB-dbName>
    
  5. 모델에서 컬렉션의 이름을 정의합니다. 추가 주석을 지정할 수도 있습니다. 예를 들어 ID, 파티션 키를 사용하여 명시적으로 나타냅니다.

    @Document(collection = "mycollection")
        public class User {
            @id
            private String id;
            private String firstName;
            @PartitionKey
            private String lastName;
        }
    

CRUD 작업에 대한 코드 조각은 다음과 같습니다.

삽입 및 업데이트 작업

여기서 _repo 리포지토리의 개체이고 문서는 POJO 클래스의 개체입니다. 삽입하거나 upsert하는 데 사용할 .save 수 있습니다(지정된 ID가 있는 문서를 찾은 경우). 다음 코드 조각에서는 doc 개체를 삽입하거나 업데이트하는 방법을 보여 봅니다.

_repo.save(doc);

삭제 작업

다음 코드 조각을 고려합니다. 여기서 doc 개체는 개체를 찾아서 삭제하기 위해 ID 및 파티션 키를 필수로 사용합니다.

_repo.delete(doc);

읽기 작업

파티션 키를 지정하거나 지정하지 않고 문서를 읽을 수 있습니다. 파티션 키를 지정하지 않으면 파티션 간 쿼리로 처리됩니다. 다음 코드 샘플을 고려합니다. 먼저 ID 및 파티션 키 필드를 사용하여 작업을 수행합니다. 두 번째 예제에서는 파티션 키 필드를 지정하지 않고 일반 필드 & 를 사용합니다.

  • _repo.findByIdAndName(objDoc.getId(),objDoc.getName());
  • _repo.findAllByStatus(objDoc.getStatus());

이제 Azure Cosmos DB에서 애플리케이션을 사용할 수 있습니다. 이 문서에 설명된 예제의 전체 코드 샘플은 CouchbaseToCosmosDB-SpringCosmos GitHub 리포지토리에서 사용할 수 있습니다.

문서 리포지토리로 Couchbase 및 N1QL 쿼리 사용

N1QL 쿼리는 Couchbase에서 쿼리를 정의하는 방법입니다.

N1QL 쿼리 Azure Cosmos DB 쿼리
SELECT META(TravelDocument).id AS id, TravelDocument.* FROM TravelDocument WHERE _type = "com.xx.xx.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

N1QL 쿼리에서 다음과 같은 변경 내용을 확인할 수 있습니다.

  • META 키워드를 사용하거나 첫 번째 수준 문서를 참조할 필요가 없습니다. 대신 컨테이너에 대한 고유한 참조를 만들 수 있습니다. 이 예제에서는 "c"(무엇이든 될 수 있습니다)로 간주했습니다. 이 참조는 모든 첫 번째 수준 필드의 접두사로 사용됩니다. 예를 들어, c.id, c.country 등

  • 이제 "ANY" 대신 하위 문서에서 조인을 수행하고 "m"과 같은 전용 별칭으로 참조할 수 있습니다. 하위 문서의 별칭을 만든 후에는 별칭을 사용해야 합니다. 예: m.Country.

  • OFFSET 시퀀스는 Azure Cosmos DB 쿼리에서 다릅니다. 먼저 OFFSET 다음 LIMIT를 지정해야 합니다. Azure Cosmos DB에 쿼리를 전달하는 동안 클라이언트 쪽에서 불필요한 오버헤드가 있을 수 있으므로 최대 사용자 지정 정의 쿼리를 사용하는 경우 Spring Data SDK를 사용하지 않는 것이 좋습니다. 대신 이 경우 훨씬 효율적으로 활용할 수 있는 직접 비동기 Java SDK가 있습니다.

읽기 작업

다음 단계에 따라 비동기 Java SDK를 사용합니다.

  1. 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>
    
  2. 다음 예제와 같이 메서드를 사용하여 ConnectionBuilder Azure Cosmos DB에 대한 연결 개체를 만듭니다. 다음 코드가 한 번만 실행되도록 이 선언을 빈에 넣어야 합니다.

    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);
    
  3. 쿼리를 실행하려면 다음 코드 조각을 실행해야 합니다.

    Flux<FeedResponse<CosmosItemProperties>> objFlux= container.queryItems(query, fo);
    

이제 위 메서드의 도움으로 여러 쿼리를 전달하고 번거로움 없이 실행할 수 있습니다. 여러 쿼리로 분할할 수 있는 하나의 큰 쿼리를 실행해야 하는 경우 이전 코드 조각 대신 다음 코드 조각을 사용해 보세요.

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();
}

이전 코드를 사용하면 쿼리를 병렬로 실행하고 분산 실행을 늘려 최적화할 수 있습니다. 또한 삽입 및 업데이트 작업도 실행할 수 있습니다.

삽입 작업

문서를 삽입하려면 다음 코드를 실행합니다.

Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);

그런 다음 Mono를 다음과 같이 구독합니다.

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();

Upsert 작업

Upsert 작업을 수행하려면 업데이트해야 하는 문서를 지정해야 합니다. 전체 문서를 가져오려면 제목 읽기 작업 아래에 언급된 코드 조각을 사용한 다음 필수 필드를 수정할 수 있습니다. 다음 코드 스니펫은 문서를 업데이트 또는 삽입(업서트)합니다.

Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);

그런 다음 모노를 구독합니다. 삽입 작업의 mono 구독 조각을 참조하세요.

삭제 작업

다음 코드 조각은 삭제 작업을 수행합니다.

CosmosItem objItem= container.getItem(doc.Id, doc.Tenant);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);

그런 다음 Mono를 구독합니다. 삽입 작업에서 Mono 구독 코드 조각을 참조하세요. 전체 코드 샘플은 CouchbaseToCosmosDB-AsyncInSpring GitHub 리포지토리에서 사용할 수 있습니다.

키/값 쌍으로 Couchbase

쿼리 대신 조회를 수행할 수 있는 간단한 워크로드 유형입니다. 키/값 쌍에 대해 다음 단계를 사용합니다.

  1. "/ID"를 기본 키로 사용하는 것이 좋습니다. 이렇게 하면 특정 파티션에서 직접 조회 작업을 수행할 수 있습니다. 컬렉션을 만들고 파티션 키로 "/ID"를 지정합니다.

  2. 인덱싱을 완전히 끕니다. 조회 작업을 실행하므로 인덱싱 오버헤드를 수행할 수 없습니다. 인덱싱을 해제하려면 Azure Portal에 로그인하고 Azure Cosmos DB 계정을 사용합니다. 데이터 탐색기를 열고 데이터베이스컨테이너를 선택합니다. 크기 조정 및 설정 탭을 열고 인덱싱 정책을 선택합니다. 현재 인덱싱 정책은 다음과 같습니다.

    {
     "indexingMode": "consistent",
     "automatic": true,
     "includedPaths": [
         {
             "path": "/*"
         }
     ],
     "excludedPaths": [
         {
             "path": "/\"_etag\"/?"
         }
     ]
     }
    

    위의 인덱싱 정책을 다음 정책으로 바꿉다.

    {
     "indexingMode": "none",
     "automatic": false,
     "includedPaths": [],
     "excludedPaths": []
     }
    
  3. 다음 코드 조각을 사용하여 연결 개체를 만듭니다. 연결 개체(@Bean에 배치하거나 정적으로 만들기):

    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);
    

이제 다음과 같이 CRUD 작업을 실행할 수 있습니다.

읽기 작업

항목을 읽으려면 다음 코드 조각을 사용합니다.

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();

삽입 작업

항목을 삽입하려면 다음 코드를 수행할 수 있습니다.

Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);

그런 다음, mono를 다음과 같이 구독합니다.

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();

Upsert 작업

항목의 값을 업데이트하려면 아래 코드 조각을 참조하세요.

Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);

그런 다음 Mono를 구독합니다. 삽입 작업에서 Mono 구독 코드 조각을 참조하세요.

삭제 작업

다음 코드 조각을 사용하여 삭제 작업을 실행합니다.

CosmosItem objItem= container.getItem(id, id);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);

그런 다음 Mono를 구독합니다. 삽입 작업에서 Mono 구독 코드 조각을 참조하세요. 전체 코드 샘플은 CouchbaseToCosmosDB-AsyncKeyValue GitHub 리포지토리에서 사용할 수 있습니다.

데이터 마이그레이션

Azure Data Factory를 사용하여 데이터를 마이그레이션합니다. 데이터를 마이그레이션하는 가장 권장되는 방법입니다. 원본을 Couchbase로 구성하고 NoSQL용 Azure Cosmos DB로 싱크합니다. 자세한 단계는 Azure Azure Cosmos DB Data Factory 커넥터 문서를 참조하세요.

다음 단계