Sdílet prostřednictvím


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