Migrace aplikace z Amazon DynamoDB do Azure Cosmos DB
PLATÍ PRO: NoSQL
Azure Cosmos DB je škálovatelná globálně distribuovaná plně spravovaná databáze. Poskytuje zaručený přístup k datům s nízkou latencí. Další informace o službě Azure Cosmos DB najdete v článku s přehledem. Tento článek popisuje, jak migrovat aplikaci .NET z DynamoDB do služby Azure Cosmos DB s minimálními změnami kódu.
Koncepční rozdíly
Tady jsou klíčové koncepční rozdíly mezi Azure Cosmos DB a DynamoDB:
DynamoDB | Azure Cosmos DB |
---|---|
Nelze použít | Databáze |
Table | Kolekce |
Položka | Dokument |
Atribut | Pole |
Sekundární index | Sekundární index |
Primární klíč – klíč oddílu | Klíč oddílu |
Primární klíč – klíč řazení | Nepovinné |
Stream | Kanál změn |
Zápis výpočetní jednotky | Jednotka žádosti (flexibilní, lze ji použít pro čtení nebo zápisy). |
Čtení výpočetní jednotky | Jednotka žádosti (flexibilní, lze ji použít pro čtení nebo zápisy). |
Globální tabulky | Nevyžaduje se. Při zřizování účtu služby Azure Cosmos DB můžete přímo vybrat oblast (oblast můžete později změnit). |
Strukturální rozdíly
Azure Cosmos DB má ve srovnání s DynamoDB jednodušší strukturu JSON. Následující příklad ukazuje rozdíly.
DynamoDB:
Následující objekt JSON představuje formát dat v DynamoDB.
{
TableName: "Music",
KeySchema: [
{
AttributeName: "Artist",
KeyType: "HASH", //Partition key
},
{
AttributeName: "SongTitle",
KeyType: "RANGE" //Sort key
}
],
AttributeDefinitions: [
{
AttributeName: "Artist",
AttributeType: "S"
},
{
AttributeName: "SongTitle",
AttributeType: "S"
}
],
ProvisionedThroughput: {
ReadCapacityUnits: 1,
WriteCapacityUnits: 1
}
}
Azure Cosmos DB:
Následující objekt JSON představuje formát dat ve službě Azure Cosmos DB.
{
"Artist": "",
"SongTitle": "",
"AlbumTitle": "",
"Year": 9999,
"Price": 0.0,
"Genre": "",
"Tags": ""
}
Migrace kódu
Tento článek je vymezený tak, aby migroval kód aplikace do služby Azure Cosmos DB, což je důležitý aspekt migrace databáze. Následující části vám pomůžou snížit křivku učení a obsahují souběžné porovnání kódu mezi Amazon DynamoDB a ekvivalentním fragmentem kódu služby Azure Cosmos DB.
Pokud chcete stáhnout zdrojový kód, naklonujte následující úložiště:
git clone https://github.com/Azure-Samples/DynamoDB-to-CosmosDB
Požadavky
- .NET Framework 4.7.2
- Nejnovější sada Visual Studio s úlohou vývoje pro Azure Můžete začít s bezplatným integrovaným vývojovém prostředím sady Visual Studio Community. Během instalace sady Visual Studio povolte úlohu vývoje Pro Azure.
- Přístup k účtu Azure Cosmos DB for NoSQL
- Místní instalace Amazon DynamoDB
- Java 8
- Spusťte stáhnoutelnou verzi Amazon DynamoDB na portu 8000 (kód můžete změnit a nakonfigurovat).
Nastavení kódu
Do projektu přidejte následující balíček NuGet:
Install-Package Microsoft.Azure.Cosmos
Navázání připojení
DynamoDB:
V Amazon DynamoDB se k připojení používá následující kód:
AmazonDynamoDBConfig addbConfig = new AmazonDynamoDBConfig() ;
addbConfig.ServiceURL = "endpoint";
try { aws_dynamodbclient = new AmazonDynamoDBClient( addbConfig ); }
Azure Cosmos DB:
Pokud chcete připojit Službu Azure Cosmos DB, aktualizujte kód na:
client_documentDB = new CosmosClient(
"<nosql-account-endpoint>",
tokenCredential
);
Optimalizace připojení ve službě Azure Cosmos DB
Pomocí služby Azure Cosmos DB můžete pomocí následujících možností optimalizovat připojení:
ConnectionMode – Pomocí režimu přímého připojení se připojte k datovým uzlům ve službě Azure Cosmos DB. Režim brány použijte pouze k inicializaci a uložení logických adres do mezipaměti a aktualizaci aktualizací. Další informace najdete v režimech připojení.
ApplicationRegion – Tato možnost slouží k nastavení upřednostňované geograficky replikované oblasti, která se používá k interakci se službou Azure Cosmos DB. Další informace najdete v tématu globální distribuce.
ConsistencyLevel – Tato možnost slouží k přepsání výchozí úrovně konzistence. Další informace najdete v tématu Úrovně konzistence.
BulkExecutionMode – Tato možnost slouží ke spuštění hromadných operací nastavením AllowBulkExecution vlastnost na hodnotu true. Další informace najdete v hromadném importu.
client_cosmosDB = new CosmosClient(" Your connection string ",new CosmosClientOptions() { ConnectionMode=ConnectionMode.Direct, ApplicationRegion=Regions.EastUS2, ConsistencyLevel=ConsistencyLevel.Session, AllowBulkExecution=true });
Vytvoření kontejneru
DynamoDB:
Pokud chcete data uložit do Amazon DynamoDB, musíte nejprve vytvořit tabulku. V procesu vytváření tabulky; definujete schéma, typ klíče a atributy, jak je znázorněno v následujícím kódu:
// movies_key_schema
public static List<KeySchemaElement> movies_key_schema
= new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = partition_key_name,
KeyType = "HASH"
},
new KeySchemaElement
{
AttributeName = sort_key_name,
KeyType = "RANGE"
}
};
// key names for the Movies table
public const string partition_key_name = "year";
public const string sort_key_name = "title";
public const int readUnits=1, writeUnits=1;
// movie_items_attributes
public static List<AttributeDefinition> movie_items_attributes
= new List<AttributeDefinition>
{
new AttributeDefinition
{
AttributeName = partition_key_name,
AttributeType = "N"
},
new AttributeDefinition
{
AttributeName = sort_key_name,
AttributeType = "S"
}
CreateTableRequest request;
CreateTableResponse response;
// Build the 'CreateTableRequest' structure for the new table
request = new CreateTableRequest
{
TableName = table_name,
AttributeDefinitions = table_attributes,
KeySchema = table_key_schema,
// Provisioned-throughput settings are always required,
// although the local test version of DynamoDB ignores them.
ProvisionedThroughput = new ProvisionedThroughput( readUnits, writeUnits );
};
Azure Cosmos DB:
V Amazon DynamoDB musíte zřídit výpočetní jednotky pro čtení a výpočetní jednotky pro zápis. Zatímco ve službě Azure Cosmos DB zadáte propustnost jako jednotky žádostí (RU/s), které se dají použít pro všechny operace dynamicky. Data jsou uspořádaná jako databáze –> kontejner –> položka. Propustnost můžete zadat na úrovni databáze nebo na úrovni kolekce nebo na obou úrovních.
Vytvoření databáze:
await client_cosmosDB.CreateDatabaseIfNotExistsAsync(movies_table_name);
Vytvoření kontejneru:
await cosmosDatabase.CreateContainerIfNotExistsAsync(new ContainerProperties() { PartitionKeyPath = "/" + partitionKey, Id = new_collection_name }, provisionedThroughput);
Načtení dat
DynamoDB:
Následující kód ukazuje, jak načíst data v Amazon DynamoDB. FilmyArray se skládají ze seznamu dokumentů JSON a pak potřebujete iterovat a načíst dokument JSON do Amazon DynamoDB:
int n = moviesArray.Count;
for( int i = 0, j = 99; i < n; i++ )
{
try
{
string itemJson = moviesArray[i].ToString();
Document doc = Document.FromJson(itemJson);
Task putItem = moviesTable.PutItemAsync(doc);
if( i >= j )
{
j++;
Console.Write( "{0,5:#,##0}, ", j );
if( j % 1000 == 0 )
Console.Write( "\n " );
j += 99;
}
await putItem;
Azure Cosmos DB:
Ve službě Azure Cosmos DB můžete zvolit streamování a zápis pomocí moviesContainer.CreateItemStreamAsync()
. V této ukázce se ale JSON deserializuje do typu MovieModel , aby bylo možné předvést funkci přetypování typu. Kód je vícevláknový, který bude používat distribuovanou architekturu služby Azure Cosmos DB a zrychlit načítání:
List<Task> concurrentTasks = new List<Task>();
for (int i = 0, j = 99; i < n; i++)
{
try
{
MovieModel doc= JsonConvert.DeserializeObject<MovieModel>(moviesArray[i].ToString());
doc.Id = Guid.NewGuid().ToString();
concurrentTasks.Add(moviesContainer.CreateItemAsync(doc,new PartitionKey(doc.Year)));
{
j++;
Console.Write("{0,5:#,##0}, ", j);
if (j % 1000 == 0)
Console.Write("\n ");
j += 99;
}
}
catch (Exception ex)
{
Console.WriteLine("\n ERROR: Could not write the movie record #{0:#,##0}, because:\n {1}",
i, ex.Message);
operationFailed = true;
break;
}
}
await Task.WhenAll(concurrentTasks);
Vytvoření dokumentu
DynamoDB:
Zápis nového dokumentu v Amazon DynamoDB není bezpečný, následující příklad jako typ dokumentu používá newItem:
Task<Document> writeNew = moviesTable.PutItemAsync(newItem, token);
await writeNew;
Azure Cosmos DB:
Azure Cosmos DB poskytuje zabezpečení typů prostřednictvím datového modelu. Datový model s názvem MovieModel používáme:
public class MovieModel
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("title")]
public string Title{ get; set; }
[JsonProperty("year")]
public int Year { get; set; }
public MovieModel(string title, int year)
{
this.Title = title;
this.Year = year;
}
public MovieModel()
{
}
[JsonProperty("info")]
public MovieInfo MovieInfo { get; set; }
internal string PrintInfo()
{
if(this.MovieInfo!=null)
return string.Format("\nMovie with title:{1}\n Year: {2}, Actors: {3}\n Directors:{4}\n Rating:{5}\n", this.Id, this.Title, this.Year, String.Join(",",this.MovieInfo.Actors), this.MovieInfo, this.MovieInfo.Rating);
else
return string.Format("\nMovie with title:{0}\n Year: {1}\n", this.Title, this.Year);
}
}
Ve službě Azure Cosmos DB newItem bude Model MovieModel:
MovieModel movieModel = new MovieModel()
{
Id = Guid.NewGuid().ToString(),
Title = "The Big New Movie",
Year = 2018,
MovieInfo = new MovieInfo() { Plot = "Nothing happens at all.", Rating = 0 }
};
var writeNew= moviesContainer.CreateItemAsync(movieModel, new Microsoft.Azure.Cosmos.PartitionKey(movieModel.Year));
await writeNew;
Čtení dokumentu
DynamoDB:
Pokud chcete číst v Amazon DynamoDB, musíte definovat primitivy:
// Create Primitives for the HASH and RANGE portions of the primary key
Primitive hash = new Primitive(year.ToString(), true);
Primitive range = new Primitive(title, false);
Task<Document> readMovie = moviesTable.GetItemAsync(hash, range, token);
movie_record = await readMovie;
Azure Cosmos DB:
U služby Azure Cosmos DB je ale dotaz přirozený (LINQ):
IQueryable<MovieModel> movieQuery = moviesContainer.GetItemLinqQueryable<MovieModel>(true)
.Where(f => f.Year == year && f.Title == title);
// The query is executed synchronously here, but can also be executed asynchronously via the IDocumentQuery<T> interface
foreach (MovieModel movie in movieQuery)
{
movie_record_cosmosdb = movie;
}
Kolekce dokumentů v předchozím příkladu bude:
- bezpečný typ
- zadejte možnost přirozeného dotazu.
Aktualizace položky
DynamoDB: Aktualizace položky v Amazon DynamoDB:
updateResponse = await client.UpdateItemAsync( updateRequest );
Azure Cosmos DB:
Ve službě Azure Cosmos DB bude aktualizace považována za operaci Upsert, což znamená, že dokument vložte, pokud neexistuje:
await moviesContainer.UpsertItemAsync<MovieModel>(updatedMovieModel);
Odstranění dokumentu
DynamoDB:
Pokud chcete odstranit položku v Amazon DynamoDB, musíte znovu spadat na primitivy:
Primitive hash = new Primitive(year.ToString(), true);
Primitive range = new Primitive(title, false);
DeleteItemOperationConfig deleteConfig = new DeleteItemOperationConfig( );
deleteConfig.ConditionalExpression = condition;
deleteConfig.ReturnValues = ReturnValues.AllOldAttributes;
Task<Document> delItem = table.DeleteItemAsync( hash, range, deleteConfig );
deletedItem = await delItem;
Azure Cosmos DB:
Ve službě Azure Cosmos DB můžeme dokument získat asynchronně odstranit:
var result= ReadingMovieItem_async_List_CosmosDB("select * from c where c.info.rating>7 AND c.year=2018 AND c.title='The Big New Movie'");
while (result.HasMoreResults)
{
var resultModel = await result.ReadNextAsync();
foreach (var movie in resultModel.ToList<MovieModel>())
{
await moviesContainer.DeleteItemAsync<MovieModel>(movie.Id, new PartitionKey(movie.Year));
}
}
Dotazování na dokumenty
DynamoDB:
V Amazon DynamoDB se k dotazování dat vyžadují funkce api:
QueryOperationConfig config = new QueryOperationConfig( );
config.Filter = new QueryFilter( );
config.Filter.AddCondition( "year", QueryOperator.Equal, new DynamoDBEntry[ ] { 1992 } );
config.Filter.AddCondition( "title", QueryOperator.Between, new DynamoDBEntry[ ] { "B", "Hzz" } );
config.AttributesToGet = new List<string> { "year", "title", "info" };
config.Select = SelectValues.SpecificAttributes;
search = moviesTable.Query( config );
Azure Cosmos DB:
Ve službě Azure Cosmos DB můžete projekci a filtrování provádět v jednoduchém dotazu SQL:
var result = moviesContainer.GetItemQueryIterator<MovieModel>(
"select c.Year, c.Title, c.info from c where Year=1998 AND (CONTAINS(Title,'B') OR CONTAINS(Title,'Hzz'))");
Pro operace rozsahu, například "between", musíte provést kontrolu v Amazon DynamoDB:
ScanRequest sRequest = new ScanRequest
{
TableName = "Movies",
ExpressionAttributeNames = new Dictionary<string, string>
{
{ "#yr", "year" }
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":y_a", new AttributeValue { N = "1960" } },
{ ":y_z", new AttributeValue { N = "1969" } },
},
FilterExpression = "#yr between :y_a and :y_z",
ProjectionExpression = "#yr, title, info.actors[0], info.directors, info.running_time_secs"
};
ClientScanning_async( sRequest ).Wait( );
Ve službě Azure Cosmos DB můžete použít dotaz SQL a jednořádkový příkaz:
var result = moviesContainer.GetItemQueryIterator<MovieModel>(
"select c.title, c.info.actors[0], c.info.directors,c.info.running_time_secs from c where BETWEEN year 1960 AND 1969");
Odstranění kontejneru
DynamoDB:
Pokud chcete odstranit tabulku v Amazon DynamoDB, můžete zadat:
client.DeleteTableAsync( tableName );
Azure Cosmos DB:
Pokud chcete kolekci odstranit ve službě Azure Cosmos DB, můžete zadat:
await moviesContainer.DeleteContainerAsync();
Pokud potřebujete, odstraňte také databázi:
await cosmosDatabase.DeleteAsync();
Jak vidíte, Azure Cosmos DB podporuje přirozené dotazy (SQL), operace jsou asynchronní a mnohem jednodušší. Složitý kód můžete snadno migrovat do služby Azure Cosmos DB, což se po migraci zjednoduší.
Další kroky
- Přečtěte si o optimalizaci výkonu.
- Informace o optimalizaci čtení a zápisů
- Další informace o monitorování ve službě Azure Cosmos DB