AWS SDK를 사용하여 MREC를 보여주는 DynamoDB 글로벌 테이블 생성 및 관리 - AWS SDK 코드 예제

Doc AWS SDK 예제 GitHub 리포지토리에서 더 많은 SDK 예제를 사용할 수 있습니다. AWS

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

AWS SDK를 사용하여 MREC를 보여주는 DynamoDB 글로벌 테이블 생성 및 관리

다음 코드 예제에서는 여러 리전에서 복제본을 사용하여 DynamoDB 글로벌 테이블을 생성하고 관리하는 방법을 보여줍니다.

  • 글로벌 보조 인덱스 및 DynamoDB 스트림으로 테이블을 생성합니다.

  • 다른 리전에 복제본을 추가하여 글로벌 테이블을 생성합니다.

  • 글로벌 테이블에서 복제본을 제거합니다.

  • 테스트 항목을 추가하여 리전 간 복제를 확인합니다.

  • 전역 테이블 구성 및 복제본 상태를 설명합니다.

Java
SDK for Java 2.x

를 사용하여 글로벌 보조 인덱스 및 DynamoDB 스트림으로 테이블을 생성합니다 AWS SDK for Java 2.x.

public static CreateTableResponse createTableWithGSI( final DynamoDbClient dynamoDbClient, final String tableName, final String indexName) { if (dynamoDbClient == null) { throw new IllegalArgumentException("DynamoDB client cannot be null"); } if (tableName == null || tableName.trim().isEmpty()) { throw new IllegalArgumentException("Table name cannot be null or empty"); } if (indexName == null || indexName.trim().isEmpty()) { throw new IllegalArgumentException("Index name cannot be null or empty"); } try { LOGGER.info("Creating table: " + tableName + " with GSI: " + indexName); CreateTableRequest createTableRequest = CreateTableRequest.builder() .tableName(tableName) .attributeDefinitions( AttributeDefinition.builder() .attributeName("Artist") .attributeType(ScalarAttributeType.S) .build(), AttributeDefinition.builder() .attributeName("SongTitle") .attributeType(ScalarAttributeType.S) .build()) .keySchema( KeySchemaElement.builder() .attributeName("Artist") .keyType(KeyType.HASH) .build(), KeySchemaElement.builder() .attributeName("SongTitle") .keyType(KeyType.RANGE) .build()) .billingMode(BillingMode.PAY_PER_REQUEST) .globalSecondaryIndexes(GlobalSecondaryIndex.builder() .indexName(indexName) .keySchema(KeySchemaElement.builder() .attributeName("SongTitle") .keyType(KeyType.HASH) .build()) .projection( Projection.builder().projectionType(ProjectionType.ALL).build()) .build()) .streamSpecification(StreamSpecification.builder() .streamEnabled(true) .streamViewType(StreamViewType.NEW_AND_OLD_IMAGES) .build()) .build(); CreateTableResponse response = dynamoDbClient.createTable(createTableRequest); LOGGER.info("Table creation initiated. Status: " + response.tableDescription().tableStatus()); return response; } catch (DynamoDbException e) { LOGGER.severe("Failed to create table: " + tableName + " - " + e.getMessage()); throw e; } }

를 사용하여 테이블이 활성화될 때까지 기다립니다 AWS SDK for Java 2.x.

public static void waitForTableActive(final DynamoDbClient dynamoDbClient, final String tableName) { if (dynamoDbClient == null) { throw new IllegalArgumentException("DynamoDB client cannot be null"); } if (tableName == null || tableName.trim().isEmpty()) { throw new IllegalArgumentException("Table name cannot be null or empty"); } try { LOGGER.info("Waiting for table to become active: " + tableName); try (DynamoDbWaiter waiter = DynamoDbWaiter.builder().client(dynamoDbClient).build()) { DescribeTableRequest request = DescribeTableRequest.builder().tableName(tableName).build(); waiter.waitUntilTableExists(request); LOGGER.info("Table is now active: " + tableName); } } catch (DynamoDbException e) { LOGGER.severe("Failed to wait for table to become active: " + tableName + " - " + e.getMessage()); throw e; } }

를 사용하여 글로벌 테이블을 생성하거나 확장할 복제본을 추가합니다 AWS SDK for Java 2.x.

public static UpdateTableResponse addReplica( final DynamoDbClient dynamoDbClient, final String tableName, final Region replicaRegion, final String indexName, final Long readCapacity) { if (dynamoDbClient == null) { throw new IllegalArgumentException("DynamoDB client cannot be null"); } if (tableName == null || tableName.trim().isEmpty()) { throw new IllegalArgumentException("Table name cannot be null or empty"); } if (replicaRegion == null) { throw new IllegalArgumentException("Replica region cannot be null"); } if (indexName == null || indexName.trim().isEmpty()) { throw new IllegalArgumentException("Index name cannot be null or empty"); } if (readCapacity == null || readCapacity <= 0) { throw new IllegalArgumentException("Read capacity must be a positive number"); } try { LOGGER.info("Adding replica in region: " + replicaRegion.id() + " for table: " + tableName); // Create a ReplicationGroupUpdate for adding a replica ReplicationGroupUpdate replicationGroupUpdate = ReplicationGroupUpdate.builder() .create(builder -> builder.regionName(replicaRegion.id()) .globalSecondaryIndexes(ReplicaGlobalSecondaryIndex.builder() .indexName(indexName) .provisionedThroughputOverride(ProvisionedThroughputOverride.builder() .readCapacityUnits(readCapacity) .build()) .build()) .build()) .build(); UpdateTableRequest updateTableRequest = UpdateTableRequest.builder() .tableName(tableName) .replicaUpdates(replicationGroupUpdate) .build(); UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest); LOGGER.info("Replica addition initiated in region: " + replicaRegion.id()); return response; } catch (DynamoDbException e) { LOGGER.severe("Failed to add replica in region: " + replicaRegion.id() + " - " + e.getMessage()); throw e; } }

를 사용하여 글로벌 테이블에서 복제본을 제거합니다 AWS SDK for Java 2.x.

public static UpdateTableResponse removeReplica( final DynamoDbClient dynamoDbClient, final String tableName, final Region replicaRegion) { if (dynamoDbClient == null) { throw new IllegalArgumentException("DynamoDB client cannot be null"); } if (tableName == null || tableName.trim().isEmpty()) { throw new IllegalArgumentException("Table name cannot be null or empty"); } if (replicaRegion == null) { throw new IllegalArgumentException("Replica region cannot be null"); } try { LOGGER.info("Removing replica in region: " + replicaRegion.id() + " for table: " + tableName); // Create a ReplicationGroupUpdate for removing a replica ReplicationGroupUpdate replicationGroupUpdate = ReplicationGroupUpdate.builder() .delete(builder -> builder.regionName(replicaRegion.id()).build()) .build(); UpdateTableRequest updateTableRequest = UpdateTableRequest.builder() .tableName(tableName) .replicaUpdates(replicationGroupUpdate) .build(); UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest); LOGGER.info("Replica removal initiated in region: " + replicaRegion.id()); return response; } catch (DynamoDbException e) { LOGGER.severe("Failed to remove replica in region: " + replicaRegion.id() + " - " + e.getMessage()); throw e; } }

를 사용하여 복제를 확인하려면 테스트 항목을 추가합니다 AWS SDK for Java 2.x.

public static PutItemResponse putTestItem( final DynamoDbClient dynamoDbClient, final String tableName, final String artist, final String songTitle) { if (dynamoDbClient == null) { throw new IllegalArgumentException("DynamoDB client cannot be null"); } if (tableName == null || tableName.trim().isEmpty()) { throw new IllegalArgumentException("Table name cannot be null or empty"); } if (artist == null || artist.trim().isEmpty()) { throw new IllegalArgumentException("Artist cannot be null or empty"); } if (songTitle == null || songTitle.trim().isEmpty()) { throw new IllegalArgumentException("Song title cannot be null or empty"); } try { LOGGER.info("Adding test item to table: " + tableName); Map<String, software.amazon.awssdk.services.dynamodb.model.AttributeValue> item = new HashMap<>(); item.put( "Artist", software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder() .s(artist) .build()); item.put( "SongTitle", software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder() .s(songTitle) .build()); PutItemRequest putItemRequest = PutItemRequest.builder().tableName(tableName).item(item).build(); PutItemResponse response = dynamoDbClient.putItem(putItemRequest); LOGGER.info("Test item added successfully"); return response; } catch (DynamoDbException e) { LOGGER.severe("Failed to add test item to table: " + tableName + " - " + e.getMessage()); throw e; } }

를 사용하여 전역 테이블 구성 및 복제본을 설명합니다 AWS SDK for Java 2.x.

public static DescribeTableResponse describeTable(final DynamoDbClient dynamoDbClient, final String tableName) { if (dynamoDbClient == null) { throw new IllegalArgumentException("DynamoDB client cannot be null"); } if (tableName == null || tableName.trim().isEmpty()) { throw new IllegalArgumentException("Table name cannot be null or empty"); } try { LOGGER.info("Describing table: " + tableName); DescribeTableRequest request = DescribeTableRequest.builder().tableName(tableName).build(); DescribeTableResponse response = dynamoDbClient.describeTable(request); LOGGER.info("Table status: " + response.table().tableStatus()); if (response.table().replicas() != null && !response.table().replicas().isEmpty()) { LOGGER.info("Number of replicas: " + response.table().replicas().size()); response.table() .replicas() .forEach(replica -> LOGGER.info( "Replica region: " + replica.regionName() + ", Status: " + replica.replicaStatus())); } return response; } catch (ResourceNotFoundException e) { LOGGER.severe("Table not found: " + tableName + " - " + e.getMessage()); throw e; } catch (DynamoDbException e) { LOGGER.severe("Failed to describe table: " + tableName + " - " + e.getMessage()); throw e; } }

를 사용한 글로벌 테이블 작업의 전체 예제입니다 AWS SDK for Java 2.x.

public static void exampleUsage(final Region sourceRegion, final Region replicaRegion) { String tableName = "Music"; String indexName = "SongTitleIndex"; Long readCapacity = 15L; // Create DynamoDB client for the source region try (DynamoDbClient dynamoDbClient = DynamoDbClient.builder().region(sourceRegion).build()) { try { // Step 1: Create the initial table with GSI and streams LOGGER.info("Step 1: Creating table in source region: " + sourceRegion.id()); createTableWithGSI(dynamoDbClient, tableName, indexName); // Step 2: Wait for table to become active LOGGER.info("Step 2: Waiting for table to become active"); waitForTableActive(dynamoDbClient, tableName); // Step 3: Add replica in destination region LOGGER.info("Step 3: Adding replica in region: " + replicaRegion.id()); addReplica(dynamoDbClient, tableName, replicaRegion, indexName, readCapacity); // Step 4: Wait a moment for replica creation to start Thread.sleep(5000); // Step 5: Describe table to view replica information LOGGER.info("Step 5: Describing table to view replicas"); describeTable(dynamoDbClient, tableName); // Step 6: Add a test item to verify replication LOGGER.info("Step 6: Adding test item to verify replication"); putTestItem(dynamoDbClient, tableName, "TestArtist", "TestSong"); LOGGER.info("Global table setup completed successfully!"); LOGGER.info("You can verify replication by checking the item in region: " + replicaRegion.id()); // Step 7: Remove replica and clean up table LOGGER.info("Step 7: Removing replica from region: " + replicaRegion.id()); removeReplica(dynamoDbClient, tableName, replicaRegion); DeleteTableResponse deleteTableResponse = dynamoDbClient.deleteTable( DeleteTableRequest.builder().tableName(tableName).build()); LOGGER.info("MREC global table demonstration completed successfully!"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("Thread was interrupted", e); } catch (DynamoDbException e) { LOGGER.severe("DynamoDB operation failed: " + e.getMessage()); throw e; } } }