[AWS]IoTのグローバル展開をする時にDynamoDB GlobalTableを使おうとなった話

# はじめに

みなさんDynamoDB使ってますか？
私はIoTに関係する案件に携わっていますので、デバイスからのストリームデータはDynamoDBに保存するようにしています。
今は日本向けのサービスを展開しているので東京リージョンだけで良いのですが、いざグローバル対応が必要になった時、問題が発生します。特に何が問題になるかというと、 **海外から東京リージョンにあるアプリケーションにアクセスする時のレイテンシーが遅くなる問題** です。

アプリケーションもAWSのアーキテクチャもすべて東京リージョンに構築しているので、まず海を超える分だけレイテンシーが遅くなります。要するに画面の表示が遅くなるので、UXガタ落ちです…
それじゃあ必要なリージョンごとにシステムを構築するの？いや、ナンセンスでしょ…
しかも閉域網でデータを処理したいじゃないですか…

そんなときに **DynamoDB GlobalTable** ですよ！

## こんな人に読んでほしい

* IoTやっててDBにDynamoDB使っているけど、グローバル展開するかもしれない…
* データは閉域網で流したい…

## DynamoDB GlobalTableってなに？

```text

Amazon DynamoDB グローバルテーブルは、マルチリージョンにマルチマスターデータベースをデプロイするための完全マネージド型のソリュー
ションです。独自のレプリケーションソリューションを構築および管理する必要はありません。グローバルテーブルを作成する際、そのテーブルの利用
を許可するAWSリージョンを指定します。DynamoDB は、これらのリージョンに同一のテーブルを作成するのに必要なすべてのタスクを実行し、変更
中のデータをすべてのテーブルに伝達します。
```

詳しくは[参考ページ(公式ドキュメント)](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GlobalTables.html)をご覧ください。

## 何が嬉しいのか？

要するにGlobalTableで作成したDynamoDBのテーブルは自動的に同期されるようになります。
リージョンAのテーブルに書き込まれた時にリージョンBのテーブルに自動的に反映されるという神機能です。
自前でDynamoDBStreamsでLambda関数を呼び出し、update/put等があった内容を他リージョンのテーブルに書き込む処理を書かないといけないということをしなくてもよくなります。
しかもAWSが持っている独自の専用線内で処理が実行されるようなので、インターネットに出ることはなさそうです。
何が嬉しいかというと、テーブルの情報を他リージョンにコピーする際に、現在はインターネットに出ないといけないのですが、それが **閉域網** でデータをコピーすることができる。という形になります。

## 注意点

2018/05/25時点の注意点は以下の通り

1. テーブルの中は空出ないといけない
2. DynamoDBStreamsを有効化しないといけない
3. 使用できるリージョンは、 `バージニア北部 / オハイオ / オレゴン / シンガポール / フランクフルト / アイルランド`

え、まだ東京使えへんやん……………(涙目)

## 仕方ない使えるリージョンで試そう

東京リージョンで使いたかったんですが、ないなら仕方ない……
いつ東京に来てもいいように、今から試しておこう！
ということで今回はフランクフルトとオレゴンでGlobalTableを作成し、LambdaからデータをPutすると、どのような動きをするのか検証してみます。

### GlobalTableを作成する

あらかじめデモ用のテーブルを作成しておいてください。
今回は `global-table-demo` というテーブルをフランクフルトリージョンに作成しました。

<img width="1312" alt="DynamoDB_GlobalTable-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/949a59f5-ec46-41f2-9b72-c910bf7d8409.png">

<img width="1275" alt="DynamoDB_GlobalTable-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/d3708d25-b56b-3971-03ce-698fcaf4b9cd.png">

<img width="1000" alt="DynamoDB_GlobalTable-3.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/cbc4b957-a83e-0692-0408-395b075c7903.png">

<img width="692" alt="DynamoDB_GlobalTable-4.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/18de1ae7-04f1-5efa-d8b3-ead93eee5d9f.png">

<img width="693" alt="DynamoDB_GlobalTable-5.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/b9868f5a-b01a-54a9-6ccb-bdceadfa1817.png">

これで作成成功です。

### Lambda関数を作成

デモ用のLambdaFunctionをフランクフルトリージョンに作成します。

ソースコード(Node.js 8.10.1)はこんな感じ

```js

const AWS = require("aws-sdk");
const DynamoDB = new AWS.DynamoDB.DocumentClient({region: "eu-central-1"});

exports.handler = async (event) => {
    try {
        const param = {
            TableName: "global-table-demo",
            Item: {
                ID: "demo-001",
                record_time: String(new Date())
            }
        };
        await DynamoDB.put(param).promise();
        return "put successed";
    } catch (err) {
        console.error(err);
        return "put failed";
    }
};
```

コンソールのテストから実行すると、こんな感じのレコードがPutされます。

```
{
    ID: "demo-001",
    record_time: Fri May 25 2018 02:14:44 GMT+0000 (UTC)
}
```

フランクフルトリージョンのテーブル

<img width="776" alt="DynamoDB_GlobalTable-6.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/d0168e56-6c84-1942-478a-1257a814ec91.png">


オレゴンリージョンのテーブル

<img width="859" alt="DynamoDB_GlobalTable-7.png" src="https://qiita-image-store.s3.amazonaws.com/0/95875/c1f3e9c8-5e68-835e-0d70-f3a57d914018.png">


## さいごに

なんで今回、フランクフルトとオレゴンだったかというと、SORACOM使ってる人はお気づきかもしれませんね。
SORACOMグローバルSIMは一度SORACOMさんのAWS環境( **フランクフルトリージョン** )　にリクエストが送信されるのです。せっかくデバイスからAWSまでSORACOMの機能を使って **閉域網** でデータを送信しているのに、そのあとインターネット出て行くしかないのかよ…となる未来が見えているので、上記の組み合わせで検証してみました。

タイムラグもほとんど感じられなかったので、素直に感動しましたね。
なので、 **東京リージョンはよ。** と強く訴えていきたいと思いますw

ではまた！