AWS CloudWatch(2)システム運用における監視項目

AWSでシステム構築を行う場合、基本的にはこのCloudWawtchのみの監視で十分なことが多い。様々な監視項目が存在するが、システム運用を行う際に特に監視する必要のある項目は以下の通り。

DynamoDB

多くの項目がデフォルトで 1 分ごとにデータを送信するが、5 分間隔で送信されるデータも存在する。事前に設定した容量(スループット)が十分であるかを監視しておくと良い。

  • ProvisionedReadCapacityUnits
  • ConsumedReadCapacityUnits
  • ProvisionedWriteCapacityUnits
  • ConsumedWriteCapacityUnits

EC2

Amazon EC2 はデフォルトで 5 分ごとに CloudWatch にデータを送信する。インスタンスを作成する際に、「詳細モニタリングを有効」にチェックを入れることでこれを 1 分ごとに変更することができるCPU使用率を監視しておくと良い。メモリやディスクのメトリクスを取得するためには、CloudWatch Agentをインストールする必要がある

  • CPUUtilization

Kinesis

事前に設定した容量(シャード数)が十分であるかを監視しておくと良い。

  • PutRecords.Records
  • IncomingRecords
  • GetRecords.Bytes

AWS DynamoDB(2)AWS SDK for Javaとアトミックカウンター

JavaによるDynamoDBへのアクセス

AWS SDK for Javaを用いることで、JavaプログラムからDynamoDBにアクセスすることができる。DynamoDBはHashKeyでインデックス化されており、Itemの追加や更新には当該テーブルのHashKeyの情報が必要となる。

DynamoDBインスタンスを取得

Credentialsやテーブル名を指定してDynamoDBインスタンスを指定する。リージョンを明示的に指定しないとデフォルトではバージニア州が指定されてしまう。通常credentialsは、ホームディレクトリ直下の「.aws」ディレクトリ(~/.aws/credentials)に置かれている。

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;

// ProfileCredentialsProvider
credentialsProvider = new ProfileCredentialsProvider();
try {
    credentialsProvider.getCredentials();
} catch (Exception e) {
    throw new AmazonClientException("Cannot load the credentials from the credential profiles file. "
                    + "Please make sure that your credentials file is at the correct "
                    + "location (/Users/hoge/.aws/credentials), and is in valid format.", e);
}

// AmazonDynamoDBClient
AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient(credentialsProvider);
// リージョンの設定
dynamoDBClient.setRegion(Region.getRegion(Regions.fromName("ap-northeast-1")));
// DynamoDB
DynamoDB dynamoDB = new DynamoDB(dynamoDBClient);
// DynamoDB Table
Table dynamodbTable = dynamoDB.getTable(TABLE_NAME);

データの取得

getItemメソッドで、HashKeyを指定することでItemの取得が可能となる。HashKeyの「名称」と「値」を指定することで、Itemを取得できる。

dynamodbTable.getItem(HASH_KEY_NAME, HASH_KEY_VAL);

データの書き込み

DynamoDBは空文字を格納することができない。データを格納する前に空文字チェックを行っておく

データの挿入

putItemメソッドで、Itemの書き込みが可能となる。書き込みを行う際、HashKeyの「名称」と「値」の指定が必須である。なお、同じキーを持つ項目が存在している場合は、全ての値が更新(上書き)される。

Item item = new Item()
		.withPrimaryKey(HASH_KEY_NAME, HASH_KEY_VAL)
		.withString(key, val);
dynamodbTable.putItem(item);

データの更新

updateItemメソッドで、Itemを更新する。HashKeyの「名称」と「値」を指定することで、どのItemを更新するかが決定される。また更新内容は、SETやADD, REMOVEで始まる更新式によって指定する。なお、同じキーを持つ項目が存在している場合は、指定したAttributeのみ置換される。指定したキーが存在しない場合は、新規の項目が作成される。

// 更新するAttributeの名称(Key)
Map<String,String> resultExpressionAttributeNames = new HashMap<String,String>();
resultExpressionAttributeNames.put("#key", KEY_NAME);
// 更新するAttributeの値(Value)
Map<String,Object> resultExpressionAttributeValues = new HashMap<String,Object>();
resultExpressionAttributeValues.put(":val", VALUE);
// Attributeの更新
dynamodbTable.updateItem(
	HASH_KEY_NAME, HASH_KEY_VALUE, // 更新対象のItem(HASH_KEY, VALUE)
	"set #key = :val",
resultExpressionAttributeNames,
resultExpressionAttributeValues);

the provided key element does not match the schema javaというエラーが発生した場合は、誤ったHashKeyを指定している可能性があるので確認する。

アトミックカウンター

DynamoDBは、高い可用性やスケーラビリティ(BASE属性)を確保している一方で、厳密な一貫性や即時反映性(ACID属性)を諦めている。しかし、アトミックカウンター(一貫性のあるカウンタ)をサポートしているため、他の処理を妨げることなく並列に、一貫性のあるカウンタ処理を実施することは可能である。

アトミックカウンターをサポートとあるが、アトミックカウンターという特別に用意された機能が存在するわけでもない。updateItemメソッドを利用して以下のような記述をすると、アトミック性のあるカウンタを実装することができる。

    	Map<String,String> expressionAttributeNames = new HashMap<String,String>();
		expressionAttributeNames.put("#key", kEY_NAME);
		Map<String,Object> expressionAttributeValues = new HashMap<String,Object>();
		expressionAttributeValues.put(":val", 1);

		try {
			dynamodbTable.updateItem(
				    HASH_KEY_NAME, HASH_KEY_VAL,  
				    "ADD #key :val",
				    expressionAttributeNames, 
				    expressionAttributeValues);
		} catch (Exception e) {

		}

更新式にて単純に1を加算する処理を行っているだけであるので、プログラムを書き換えることで加算もできれば減算もできる。2を足す、3を引くといったことも可能である。

    	dynamodbTable.updateItem(
				    HASH_KEY_NAME, HASH_KEY_VAL,  
				    "SET #key = #key + :val",
				    expressionAttributeNames, 
				    expressionAttributeValues);

としてもよいが、SETアクションの場合、アイテムが事前に存在しない場合にエラーとなるので、ADDアクションで実装したほうがよい。

DynamoDB操作の違い

なお、DynamoDBのそれぞれの操作の差異は以下の通り。

操作 アクション 既にアイテムが存在している場合の挙動
putItem 全ての属性を消去した上で新たに属性を追加する
updateItem SET 対象の属性のみ更新される
updateItem REMOVE 対象の属性のみ削除される
updateItem ADD **対象の属性が数値の場合は値に追加される、セットデータの場合は要素が追加される**
updateItem DELETE 対象の属性のセットデータから要素が削除される

AWS DynamoDB(1)DynamoDBの概要

DynamoDBとは

DynamoDBは高速かつフレキシブルな、完全マネージド型のNoSQLデータベース。データはKey, Value型で保存される。高速なレスポンス、スケーラビリティ、ドキュメントデータモデル(JSON)をサポートしていることなどが特徴的。同一リージョン内の3つの設備で同期レプリケーションされるため障害にも強い。

管理不要で信頼性が高い

  • 単一障害点が存在しない構造
  • 同一リージョン内の3つの設備にデータが保存される
  • ストレージの自動パーティショニング

プロビジョンドスループット

  • Read/Writeの速度を指定できる
  • ただし、スケールダウンに関しては1日9回までの制限あり

1キャパシティユニットは、最大4KBの読み込み項目に対して、1秒あたり1回の強力な整合性のある読み込み、もしくは1秒あたり2回の結果整合性のある読み込み最大1KBの書き込み項目に対して、1秒あたり1回の書き込みを表す単位。読み込みや書き込みのリクエストがプロビジョニングしたスループットを超えた場合は、** HTTP 400 コード (Bad Request) : ProvisionedThroughputExceededExceptionのエラーレスポンスが返る。DynamoDB Auto Scaling**を用いることで、キャパシティを自動的に変更することが可能であるが、バーストトラフィックには対応できないので注意が必要である。

その他の特徴

  • 容量制限が存在しない
  • 結果整合性
    • 書き込みに関しては、2箇所への書き込みが完了した時点でACK
    • 読み込みに関しては、最新の結果が反映されていない可能性がある

複数のクライアントが同時にアクセスし値を更新するようなシナリオの場合は、「現在この値であれば値を更新する」といったような条件付き書き込みを行うことで、想定外のデータ上書きを防止することが可能である。

!(条件付き書き込み)[https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/update-yes-condition.png]

料金

  • 指定したスループットによる時間課金
  • 保存データ量による課金

DynamoDBへのアクセスにはHTTPおよびHTTPSが用いられる。HTTP/HTTPSによる通信はオーバヘッドが大きいため、ゲームアプリ等の早い応答速度が求められるサービスでは、DyamoDBではなくRDSなど他のデータベースを選択することが多い。シリアライズフォーマットとしては、JSON形式が使用される。

データモデル

DynamoDBのテーブルは複数のItemから構成され、Item内には、KeyValue型のデータ(Attributes)が格納されている。各Itemに格納されているAttributesの数は不ぞろいでも良く(スキーマレス)、あるアイテムにはuser-id, name, e-mail, ageの4つのAttributesが、別のItemにはuser-idのみが格納されているとことも可能である。格納するAttributesのうち1つにPartitionKeyを指定する。PartitionKeyはプライマリーキーとして利用でき、ハッシュインデックスを構築されるときのキーとなる。また、SortKeyを指定することもでき、この場合はPartitionKey + SortKeyでプライマリーキーとなる。

DynamoDBは、スカラー型、文字セット、バイナリ(圧縮ファイルや画像)などの多値型、リストやマップ(JSON)などのドキュメント型の3つの形式をサポートしている。格納することのできる値の範囲や制限事項などは、DynamoDB での制限 – Amazon DynamoDBを参照のこと。文字列や多値データセット型は空白や空白セットはサポートされていない。スカラー型の場合、NULL値を格納することは可能である。

パーティショニング

DynamoDBは、スループット性能を維持するためテーブルをパーティショニングする。パーティション間のデータ分散にはPartitionKeyを用いられ、またスループットは各パーティションに均等に配分されるために、特定のPartitionKeyにアクセスが偏ると性能が出ない場合がある

セカンダリインデックス(Secondary Index)

セカンダリインデックスは、SortKey以外に使用することのできる絞込み検索用のAttributesである。ローカルセカンダリインデックス(local Secondary Index)はSortKeyの代替となる検索用インデックスで、同一PartitionKeyのItem検索に利用できる。グローバルセカンダリインデックス(Glocal Secondary Index)は、PartitionKeyの代替となる検索用インデックスで、異なるPartitionKeyのItem検索にも利用できる。セカンダリインデックスは便利ではあるが、追加のスループットやストレージを必要とするためRDSで代替できないか検討すべきである。

テーブルあたり4つのグローバルセカンダリインデックスと5つのローカルセカンダリインデックスを定義することができる。

項目の操作

DynamoDB は、作成、読み込み、更新、削除 (CRUD) の 4 つの基本的なオペレーション機能を提供する。

  • PutItem – 項目の作成
  • GetItem – 項目の読み取り
  • UpdateItem – 項目の更新
  • DeleteItem – 項目の削除

また、Time to Live(TTL)を用いてテーブルの項目の有効期限を設定することが可能で、データベースから項目を自動的に削除することができる。指定する時刻はUnixtimeで、DynamoDBはこの期限から48時間以内に項目を削除する。有効期限すぐに削除されるとは限らないために、これを考慮したアプリケーション実装とすることが必要。

DynamoDB ストリーム

DynamoDBストリームは、DynamoDBテーブルのデータ変更イベントをキャプチャする。ストリームには24時間の有効期限があり、Lambdaや等を用いてこれらのストリームデータの処理を行うことができる。