DynamoDB-テーブルアクティビティ

DynamoDBストリームを使用すると、テーブルアイテムの変更を追跡して応答できます。この機能を使用して、ソース間で情報を更新することにより変更に応答するアプリケーションを作成します。大規模なマルチユーザーシステムの数千人のユーザーのデータを同期します。これを使用して、更新に関する通知をユーザーに送信します。そのアプリケーションは多様で実質的であることが証明されています。DynamoDBストリームは、この機能を実現するために使用される主要なツールとして機能します。

ストリームは、テーブル内のアイテムの変更を含む時系列のシーケンスをキャプチャします。彼らはこのデータを最大24時間保持します。アプリケーションはそれらを使用して、元のアイテムと変更されたアイテムをほぼリアルタイムで表示します。

テーブルで有効になっているストリームは、すべての変更をキャプチャします。すべてのCRUD操作で、DynamoDBは変更されたアイテムの主キー属性を使用してストリームレコードを作成します。前後の画像などの追加情報のストリームを構成できます。

ストリームには2つの保証があります-

  • 各レコードはストリームに1回表示され、

  • 各アイテムの変更により、変更と同じ順序のストリームレコードが生成されます。

すべてのストリームはリアルタイムで処理されるため、アプリケーションの関連機能に使用できます。

ストリームの管理

テーブルの作成時に、ストリームを有効にできます。既存のテーブルでは、ストリームの無効化または設定の変更が可能です。ストリームは非同期操作の機能を提供します。つまり、テーブルのパフォーマンスに影響はありません。

シンプルなストリーム管理のためにAWSマネジメントコンソールを利用します。まず、コンソールに移動して、Tables。[概要]タブで、Manage Stream。ウィンドウ内で、テーブルデータの変更に関するストリームに追加された情報を選択します。すべての設定を入力したら、Enable

既存のストリームを無効にする場合は、 Manage Stream、 その後 Disable

API CreateTableおよびUpdateTableを利用して、ストリームを有効化または変更することもできます。パラメータStreamSpecificationを使用して、ストリームを構成します。StreamEnabledはステータスを指定します。つまり、有効の場合はtrue、無効の場合はfalseを意味します。

StreamViewTypeは、ストリームに追加される情報(KEYS_ONLY、NEW_IMAGE、OLD_IMAGE、およびNEW_AND_OLD_IMAGES)を指定します。

ストリームリーディング

エンドポイントに接続してAPIリクエストを行うことにより、ストリームを読み取って処理します。各ストリームはストリームレコードで構成され、すべてのレコードはストリームを所有する単一の変更として存在します。ストリームレコードには、発行順序を示すシーケンス番号が含まれています。レコードは、シャードとも呼ばれるグループに属しています。シャードは、いくつかのレコードのコンテナとして機能し、レコードへのアクセスとトラバースに必要な情報も保持します。24時間後、レコードは自動的に削除されます。

これらのシャードは必要に応じて生成および削除され、長続きしません。また、通常は書き込みアクティビティの急増に応じて、複数の新しいシャードに自動的に分割されます。ストリームを無効にすると、開いているシャードが閉じます。シャード間の階層関係は、アプリケーションが正しい処理順序のために親シャードに優先順位を付ける必要があることを意味します。KinesisAdapterを使用してこれを自動的に行うことができます。

Note −変更が発生しない操作では、ストリームレコードは書き込まれません。

レコードにアクセスして処理するには、次のタスクを実行する必要があります-

  • ターゲットストリームのARNを決定します。
  • ターゲットレコードを保持しているストリームのシャードを決定します。
  • シャードにアクセスして、目的のレコードを取得します。

Note−シャードを一度に読み取るプロセスは最大2つ必要です。2プロセスを超えると、ソースを調整できます。

利用可能なストリームAPIアクションには次のものがあります

  • ListStreams
  • DescribeStream
  • GetShardIterator
  • GetRecords

次のストリーム読み取りの例を確認できます-

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsClient;

import com.amazonaws.services.dynamodbv2.model.AttributeAction;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;

import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeStreamRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeStreamResult;
import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;

import com.amazonaws.services.dynamodbv2.model.GetRecordsRequest;
import com.amazonaws.services.dynamodbv2.model.GetRecordsResult;
import com.amazonaws.services.dynamodbv2.model.GetShardIteratorRequest;
import com.amazonaws.services.dynamodbv2.model.GetShardIteratorResult;

import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.Record;

import com.amazonaws.services.dynamodbv2.model.Shard;
import com.amazonaws.services.dynamodbv2.model.ShardIteratorType;
import com.amazonaws.services.dynamodbv2.model.StreamSpecification;
import com.amazonaws.services.dynamodbv2.model.StreamViewType;
import com.amazonaws.services.dynamodbv2.util.Tables;

public class StreamsExample {
   private static AmazonDynamoDBClient dynamoDBClient =  
      new AmazonDynamoDBClient(new ProfileCredentialsProvider());  
   private static AmazonDynamoDBStreamsClient streamsClient =  
      new AmazonDynamoDBStreamsClient(new ProfileCredentialsProvider());  

   public static void main(String args[]) {  
      dynamoDBClient.setEndpoint("InsertDbEndpointHere");   
      streamsClient.setEndpoint("InsertStreamEndpointHere");    
      
      // table creation 
      String tableName = "MyTestingTable";  
      ArrayList<AttributeDefinition> attributeDefinitions =  
         new ArrayList<AttributeDefinition>();  
      
      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("ID") 
         .withAttributeType("N"));
         
      ArrayList<KeySchemaElement> keySchema = new 
         ArrayList<KeySchemaElement>(); 
      
      keySchema.add(new KeySchemaElement() 
         .withAttributeName("ID") 
         .withKeyType(KeyType.HASH));                       //Partition key

      StreamSpecification streamSpecification = new StreamSpecification(); 
      streamSpecification.setStreamEnabled(true); 
      streamSpecification.setStreamViewType(StreamViewType.NEW_AND_OLD_IMAGES);  
      CreateTableRequest createTableRequest = new CreateTableRequest() 
         .withTableName(tableName) 
         .withKeySchema(keySchema) 
         .withAttributeDefinitions(attributeDefinitions) 
         .withProvisionedThroughput(new ProvisionedThroughput() 
         .withReadCapacityUnits(1L) 
         .withWriteCapacityUnits(1L))
         .withStreamSpecification(streamSpecification);  
      
      System.out.println("Executing CreateTable for " + tableName); 
      dynamoDBClient.createTable(createTableRequest);  
      System.out.println("Creating " + tableName); 
      
      try { 
         Tables.awaitTableToBecomeActive(dynamoDBClient, tableName); 
      } catch (InterruptedException e) { 
         e.printStackTrace(); 
      } 
         
      // Get the table's stream settings 
      DescribeTableResult describeTableResult =
         dynamoDBClient.describeTable(tableName);  
      
      String myStreamArn = describeTableResult.getTable().getLatestStreamArn(); 
      StreamSpecification myStreamSpec =  
         describeTableResult.getTable().getStreamSpecification();  
      
      System.out.println("Current stream ARN for " + tableName + ": "+ myStreamArn);
      System.out.println("Stream enabled: "+ myStreamSpec.getStreamEnabled()); 
      System.out.println("Update view type: "+ myStreamSpec.getStreamViewType());  
      
      // Add an item 
      int numChanges = 0; 
      System.out.println("Making some changes to table data"); 
      Map<String, AttributeValue> item = new HashMap<String, AttributeValue>(); 
      item.put("ID", new AttributeValue().withN("222")); 
      item.put("Alert", new AttributeValue().withS("item!")); 
      dynamoDBClient.putItem(tableName, item); 
      numChanges++;  
      
      // Update the item         
      Map<String, AttributeValue> key = new HashMap<String, AttributeValue>(); 
      key.put("ID", new AttributeValue().withN("222")); 
      Map<String, AttributeValueUpdate> attributeUpdates =  
      new HashMap<String, AttributeValueUpdate>(); 
      
      attributeUpdates.put("Alert", new AttributeValueUpdate() 
         .withAction(AttributeAction.PUT) 
         .withValue(new AttributeValue().withS("modified item"))); 
      
      dynamoDBClient.updateItem(tableName, key, attributeUpdates); 
      numChanges++;   
      
      // Delete the item         
      dynamoDBClient.deleteItem(tableName, key);  
      numChanges++;
      
      // Get stream shards         
      DescribeStreamResult describeStreamResult =  
      streamsClient.describeStream(new DescribeStreamRequest() 
         .withStreamArn(myStreamArn)); 
      String streamArn =  
         describeStreamResult.getStreamDescription().getStreamArn(); 
      List<Shard> shards =  
         describeStreamResult.getStreamDescription().getShards();  
      
      // Process shards 
      for (Shard shard : shards) { 
         String shardId = shard.getShardId(); 
         System.out.println("Processing " + shardId + " in "+ streamArn);  
         
         // Get shard iterator 
         GetShardIteratorRequest getShardIteratorRequest = new 
            GetShardIteratorRequest() 
            .withStreamArn(myStreamArn) 
            .withShardId(shardId) 
            .withShardIteratorType(ShardIteratorType.TRIM_HORIZON); 
         
         GetShardIteratorResult getShardIteratorResult =  
            streamsClient.getShardIterator(getShardIteratorRequest); 
         String nextItr = getShardIteratorResult.getShardIterator();  
         
         while (nextItr != null && numChanges > 0) { 
            // Read data records with iterator                 
            GetRecordsResult getRecordsResult =  
               streamsClient.getRecords(new GetRecordsRequest(). 
               withShardIterator(nextItr));
               
            List<Record> records = getRecordsResult.getRecords(); 
            System.out.println("Pulling records...");  
               
            for (Record record : records) { 
               System.out.println(record); 
               numChanges--;
            } 
            nextItr = getRecordsResult.getNextShardIterator(); 
         } 
      } 
   } 
}