Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Azure Cosmos DB — это масштабируемая, глобально распределенная, полностью управляемая база данных. Она обеспечивает гарантированный доступ к данным с низкой задержкой. Дополнительные сведения об Azure Cosmos DB см. в этой обзорной статье. В этой статье приведены инструкции по переносу приложений Java, подключенных к Couchbase, к учетной записи API для NoSQL в Azure Cosmos DB.
Различия в номенклатуре
Ниже приведены основные функции, которые работают по-разному в Azure Cosmos DB по сравнению с Couchbase:
| Couchbase | Azure Cosmos DB (облачная база данных) |
|---|---|
| Сервер Couchbase | Счет |
| ведро | База данных |
| ведро | Контейнер или коллекция |
| Документ JSON | Элемент / документ |
Основные отличия
Azure Cosmos DB имеет поле "ID" в документе, в то время как Couchbase имеет идентификатор в составе контейнера. Поле "ID" уникально в разделе.
Azure Cosmos DB масштабируется с помощью метода секционирования или сегментирования. Это означает, что данные разделяются на несколько сегментов или секций. Эти разделы/шарды создаются на основе свойства ключа разделения, который вы предоставляете. Вы можете выбрать ключ раздела для оптимизации операций чтения, а также записи, или для оптимизации чтения и записи одновременно. Дополнительные сведения см. в статье о секционированиях .
В Azure Cosmos DB не требуется обозначать коллекцию на иерархическом верхнем уровне, так как имя коллекции уже существует. Эта функция упрощает структуру JSON. Ниже приведен пример, показывающий различия в модели данных между Couchbase и Azure Cosmos DB:
Couchbase: Идентификатор документа = "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" } ] }
Поддержка пакета SDK для Java
Azure Cosmos DB имеет следующие пакеты средств разработки программного обеспечения (SDK) для поддержки различных платформ Java:
- Async SDK
- Spring Boot SDK
В следующих разделах описывается, когда следует использовать каждый из этих пакетов SDK. Рассмотрим пример, в котором у нас есть три типа рабочих нагрузок:
Couchbase в качестве репозитория документов и пользовательских запросов на основе Spring Data
Если рабочая нагрузка, которую вы переносите, основана на пакете SDK Spring Boot Based, можно выполнить следующие действия.
Добавьте родительский элемент в файл POM.xml:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> </parent>Добавьте свойства в файл POM.xml:
<azure.version>2.1.6</azure.version>Добавьте зависимости в файл POM.xml:
<dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-cosmosdb-spring-boot-starter</artifactId> <version>2.1.6</version> </dependency>Добавьте свойства приложения в ресурсы и укажите следующее. Обязательно замените параметры URL-адреса, ключа и имени базы данных:
azure.cosmosdb.uri=<your-cosmosDB-URL> azure.cosmosdb.key=<your-cosmosDB-key> azure.cosmosdb.database=<your-cosmosDB-dbName>Определите имя коллекции в модели. Кроме того, можно указать дополнительные заметки. Например, ID, ключ раздела, для их явного обозначения:
@Document(collection = "mycollection") public class User { @id private String id; private String firstName; @PartitionKey private String lastName; }
Ниже приведены фрагменты кода для операций CRUD:
Операции вставки и обновления
Где _repo является объектом репозитория и документом является объект класса POJO. Можно использовать .save для вставки или upsert (если документ с указанным идентификатором найден). В следующем фрагменте кода показано, как вставить или обновить объект документации:
_repo.save(doc);
Операция удаления
Рассмотрим следующий фрагмент кода, в котором объект doc будет иметь идентификатор и ключ секции, обязательный для поиска и удаления объекта:
_repo.delete(doc);
Операция чтения
Вы можете прочитать документ с указанием ключа раздела или без него. Если ключ секции не указан, он рассматривается как межсекционный запрос. Рассмотрим следующие примеры кода, сначала будет выполняться операция с помощью поля идентификатора и ключа секции. Во втором примере используется регулярное поле и без указания поля ключа раздела.
_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.xxxx" и страна = 'Индия' и ANY m в визах SATISFIES m.type == "Multi-Entry" и m.Country IN ['India', 'Бутан'] 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.xxx.x" и c.country = "Индия" и m.type = "Multi-Entry" и m.Country IN ("Индия", "Бутан") 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. Рекомендуется не использовать пакет SDK Spring Data, если вы используете максимально настраиваемые запросы, так как это может иметь ненужные издержки на стороне клиента при передаче запроса в Azure Cosmos DB. Вместо этого у нас есть прямой пакет SDK для Async Java, который можно использовать гораздо эффективнее в этом случае.
Операция чтения
Используйте пакет SDK для Async Java, выполнив следующие действия.
Настройте следующую зависимость в файле 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>Создайте объект подключения для Azure Cosmos DB с помощью
ConnectionBuilderметода, как показано в следующем примере. Убедитесь, что это объявление помещено в 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);Чтобы выполнить запрос, необходимо выполнить следующий фрагмент кода:
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. Обратитесь к фрагменту подписки mono в операции вставки.
Операция удаления
Следующий фрагмент кода выполняет операцию удаления:
CosmosItem objItem= container.getItem(doc.Id, doc.Tenant);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);
Затем подпишитесь на mono, см. фрагмент подписки mono в операции вставки данных. Полный пример кода доступен в репозитории CouchbaseToCosmosDB-AsyncInSpring GitHub.
Couchbase в качестве пары "ключ-значение"
Это простой тип рабочей нагрузки, в которой можно выполнять поиски вместо запросов. Выполните следующие действия для пар "ключ-значение".
Рассмотрите возможность использования "/ID" в качестве первичного ключа, что гарантирует, что вы можете выполнять операцию поиска непосредственно в определенном разделе. Создайте коллекцию и укажите "/ID" в качестве ключа секции.
Отключите индексирование полностью. Поскольку вы будете выполнять операции подстановки, нет смысла нести накладные расходы на индексирование. Чтобы отключить индексирование, войдите на портал Azure, перейдите к учетной записи Azure Cosmos DB. Откройте обозреватель данных, выберите базу данных и контейнер. Откройте вкладку "Масштаб и параметры" и выберите политику индексирования. В настоящее время политика индексирования выглядит следующим образом:
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ] }Замените указанную выше политику индексирования следующим образом:
{ "indexingMode": "none", "automatic": false, "includedPaths": [], "excludedPaths": [] }Чтобы создать объект подключения, используйте следующий фрагмент кода. Объект подключения (разместить в @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 для переноса данных. Это наиболее рекомендуемый метод для переноса данных. Настройте источник как Couchbase и приемник как Azure Cosmos DB для NoSQL, см. статью соединитель Azure Cosmos DB Data Factory для подробных инструкций.
Дальнейшие шаги
- Чтобы выполнить тестирование производительности, см. статью Тестирование производительности и масштабирования с помощью Azure Cosmos DB.
- Чтобы оптимизировать код, см. статью Советы по повышению производительности для Azure Cosmos DB.
- Ознакомьтесь с Java Async V3 SDK и справочником по пакету SDK в репозитории GitHub.