AWS CLIを使ってKinesis Streamをリシャーディングしてみた

  • 7
    いいね
  • 0
    コメント

2016/7/27 追記有り

KinesisStreamのシャード分割・結合について、日本語の情報に不足を感じたので自分自身が戸惑った事象についてメモ。
環境やパスは適宜読み替えてください。

CLIこと始め

この辺を参考にインストールしてどうぞ。
AWS CLIをWindowsにインストール・初期設定する手順
Windows Server への AWS CLIのインストール
※cmdとPSの違いがありますが、インストールすればどちらも使えるようになります。私は面倒なのでcmd生で。

Streamの作成

# 作成
aws kinesis create-stream --stream-name MyStream --shard-count 1

# 確認
aws kinesis describe-stream --stream-name MyStream
# 作成中
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream",
        "Shards": [],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "CREATING"
    }
}
# 作成完了
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream",
        "Shards": [
            {
                "ShardId": "shardId-000000000000",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "0"
                },
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564038576867200623943064147577467982341808408192090114"
                }
            }
        ],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "ACTIVE"
    }
}

Put/Get

この記事を参考にお試しを。
本記事のメインはシャードの分割結合なのでココはサボります。

Shardの分割

基本構文

aws kinesis split-shard --stream-name MyStream --shard-to-split {ShardId} --new-starting-hash-key {HashKey}

{ShardId}
分割対象のシャードIDを指定します。
今回は作成したばかりの shardId-000000000000 を使います。
{HashKey}
シャードを分割する位置・INDEXを指定します。
HashKeyはデカい数字で表わされるので、分割数によって手動で計算することになります。
今回は 340282366920938463463374607431768211455 がEndingHashKeyなので、

  • 例えば2分割する場合は…170141183460469231731687303715884105727
  • 例えば3分割する場合は…113427455640312821154458202477256070485

を指定すると良いでしょう。
均等に分割すべきか否か、どんなメリットがあるかは不明です。
有識者の方のコメントを期待します。。

桁数がバカでかいのでWindowsの電卓やExcelでは計算できません。
ココ辺りを活用してください。
桁数は42以上を指定で賄えるはずです。

分割イメージ

上記で3分割する場合の話が出ましたが、分割したシャードには親子関係があります。
また一度の分割では1シャードを2つのシャードに分割にすることのみ可能で、
一発で3分割するようなことはできません。
例)shardId-000000000000を1:2で分割し、分割した2の方をさらに分割

 shardId-000000000000
  ┣ shardId-000000000001      [*]
  ┗ shardId-000000000002
    ┣ shardId-000000000003  [*]
    ┗ shardId-000000000004  [*]

※[*]マークのシャードがOPENシャードです。

# 分割してみた
aws kinesis describe-stream --stream-name MyStream
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream",
        "Shards": [
            {
                "ShardId": "shardId-000000000000",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "0"
                },
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564038576878350996542329459147026915659220410261569538",
                    "StartingSequenceNumber": "49564038576867200623943064147577467982341808408192090114"
                }
            },
            {
                "ShardId": "shardId-000000000001",
                "HashKeyRange": {
                    "EndingHashKey": "113427455640312821154458202477256070484",
                    "StartingHashKey": "0"
                },
                "ParentShardId": "shardId-000000000000",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564042224577792002398560785433370121162354099113426962"
                }
            },
            {
                "ShardId": "shardId-000000000002",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "113427455640312821154458202477256070485"
                },
                "ParentShardId": "shardId-000000000000",
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564042224611243120196356720144464772751719433901178914",
                    "StartingSequenceNumber": "49564042224600092747597091408574905839435002460619407394"
                }
            },
            {
                "ShardId": "shardId-000000000003",
                "HashKeyRange": {
                    "EndingHashKey": "226854911280625642308916404954512140969",
                    "StartingHashKey": "113427455640312821154458202477256070485"
                },
                "ParentShardId": "shardId-000000000002",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564042263514893119033028790554734225206400778978197554"
                }
            },
            {
                "ShardId": "shardId-000000000004",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "226854911280625642308916404954512140970"
                },
                "ParentShardId": "shardId-000000000002",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564042263537193864231559413696269943479049140484177986"
                }
            }
        ],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "ACTIVE"
    }
}

Shardの結合

基本構文

aws kinesis merge-shards --stream-name MyStream --shard-to-merge {ShardId1} --adjacent-shard-to-merge {ShardId2}

{ShardId1}
結合するシャードID1
{ShardId2}
結合するシャードID2

結合できるもの

シャードの分割を行なう際に指定したHashKeyを境に、StartingHashKeyとEndingHashKeyがセットされます。
結合できるシャードは、HashKeyが連番になるシャード群となります。
また指定するシャードの順番も、HashKeyがStart→Endと並ぶようにする必要があります。
このとき、親子関係や分割元は関係ありません

例)
結合できない:shardId-000000000001とshardId-000000000004
結合できる :shardId-000000000001とshardId-000000000003
       shardId-000000000003とshardId-000000000004
※当然CLOSEDシャードは指定できません。

# 結合してみた1:1と3から5を作成
aws kinesis merge-shards --stream-name MyStream --shard-to-merge shardId-000000000001 --adjacent-shard-to-merge shardId-000000000003
{
    "StreamDescription": {
        ~略~
        "Shards": [
            ~略~
            {
                "ShardId": "shardId-000000000001",
                "HashKeyRange": {
                    "EndingHashKey": "113427455640312821154458202477256070484",
                    "StartingHashKey": "0"
                },
                "ParentShardId": "shardId-000000000000",
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564042224588942374997826097002929054479099659697520658",
                    "StartingSequenceNumber": "49564042224577792002398560785433370121162354099113426962"
                }
            },
            ~略~
            {
                "ShardId": "shardId-000000000003",
                "HashKeyRange": {
                    "EndingHashKey": "226854911280625642308916404954512140969",
                    "StartingHashKey": "113427455640312821154458202477256070485"
                },
                "ParentShardId": "shardId-000000000002",
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564042263526043491632294102124293158523138849139327026",
                    "StartingSequenceNumber": "49564042263514893119033028790554734225206400778978197554"
                }
            },
            ~略~
            {
                "ShardId": "shardId-000000000005",
                "HashKeyRange": {
                    "EndingHashKey": "226854911280625642308916404954512140969",
                    "StartingHashKey": "0"
                },
                "ParentShardId": "shardId-000000000001",
                "AdjacentParentShardId": "shardId-000000000003",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564042411993254650849917666899546484499220273098129490"
                }
            }
        ],
        ~略~
    }
}
# 結合してみた2:5と4から6を作成(順番に注意)
aws kinesis merge-shards --stream-name MyStream --shard-to-merge shardId-000000000005 --adjacent-shard-to-merge shardId-000000000004
{
    "StreamDescription": {
        ~略~
        "Shards": [
            ~略~
            {
                "ShardId": "shardId-000000000004",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "226854911280625642308916404954512140970"
                },
                "ParentShardId": "shardId-000000000002",
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564042263548344236830824725265828876795820127274664002",
                    "StartingSequenceNumber": "49564042263537193864231559413696269943479049140484177986"
                }
            },
            {
                "ShardId": "shardId-000000000005",
                "HashKeyRange": {
                    "EndingHashKey": "226854911280625642308916404954512140969",
                    "StartingHashKey": "0"
                },
                "ParentShardId": "shardId-000000000001",
                "AdjacentParentShardId": "shardId-000000000003",
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564042412004405023449182978469105417815962672586293330",
                    "StartingSequenceNumber": "49564042411993254650849917666899546484499220273098129490"
                }
            },
            {
                "ShardId": "shardId-000000000006",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "0"
                },
                "ParentShardId": "shardId-000000000005",
                "AdjacentParentShardId": "shardId-000000000004",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564042582928466597587144046770827044348944133067374690"
                }
            }
        ],
        ~略~
    }
}

知りたかったこと!!

分割・結合したあとどうなるの?

 ここまでの手順で、以下のような親子関係で7シャードが存在する状態となります。

  shardId-000000000000
   ┣ shardId-000000000001 ━━┓
   ┗ shardId-000000000002   ┣ shardId-000000000005 ┓
     ┣ shardId-000000000003 ┛            ┣ shardId-000000000006
     ┗ shardId-000000000004 ━━━━━━━━━━━━━┛

 ポイントは、分割・結合したシャードはCLOSED状態となり、新たに作成されたシャードがOPEN状態になるということです。
 よってOPEN状態なのはshardId-000000000006のみ、それ以外はCLOSED状態となります。
 OPEN/CLOSEDの意味は公式から引用

  • OPEN: リシャーディングオペレーションの前、親シャードは OPEN 状態にあります。つまり、データレコードはシャードへの追加とシャードからの取得のいずれも可能です。
  • CLOSED: リシャーディングオペレーションの後、親シャードは CLOSED 状態に移行します。つまり、データレコードはシャードに追加されなくなります。このシャードに追加されることになっていたデータレコードは、子シャードに追加されるようになります。ただし、データレコードは引き続き、制限された時間内にシャードから取得できます。
  • 期限切れ: ストリーム保持期間の有効期限が切れたら、親シャードのすべてのデータレコードの期限も切れてアクセスできなくなります。この時点で、シャード自体は EXPIRED 状態に移行します。getStreamDescription().getShards を呼び出してストリーム内のシャードを列挙しても、返されるシャードのリストには 状態のシャードは含まれません。EXPIREDストリームの保持期間の詳細については、「データ保持期間の変更」を参照してください。

 AWSのコンソールでは以下のように表示されるハズ
image

料金はどこにかかるの?

 涙の数だけ強くなれるように、シャードの数だけ金がかかります。
 料金構成
 よっていたずらに分割結合を繰り返すとその分だけ費用がかさむので気を付けましょう。
 またCLOSEDのシャードにも料金がかかります

 CLOSEDシャードがEXPIREDになるのは、設定したデータレコードの保持期間が過ぎたタイミングです。
 言い切ってますが確証なし。Amazonに確認中。
 データレコードの保持期間はデフォルト24時間、最大168時間まで1時間単位で設定可能です。
 データ保持期間の変更

Amazon Kinesis stream は 24 時間レコードを保持し、最大値は 168 時間です。

その他

流れだけ分かったら、公式ドキュメントも熟読することをオススメします。
ストリームをリシャーディングする
大事なことがサラっと書かれていたりしますので。

Thanks for

本記事を作成するにあたり、以下の記事を参考にさせてもらいました。
AWS CLIを使って初めてAmazon Kinesisを使ってみた
Kinesisの雰囲気をつかむためにawscliで操作する
ありがとうございます!!

あとしまつ

# 削除
aws kinesis delete-stream --stream-name MyStream
# 削除中
aws kinesis describe-stream --stream-name MyStream
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream",
        "Shards": [],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "DELETING"
    }
}
# 削除後
aws kinesis describe-stream --stream-name MyStream
An error occurred (ResourceNotFoundException) when calling the DescribeStream operation: Stream MyStream under account {AccountId} not found.

誤りや補足、その他ありましたらコメントください。
それではゴキゲンなAWSライフを!

P.S
しかしこのコードブロックに設定すべき適切なシンタックスハイライト、なんだろうな…
いまいち美しくない…

2016/7/27 追記

最初からShard数が2とかだったらどうなんの?

って同僚に聞かれたので調べました。

結論から言えば、単純にStart/Endが連続したHashKeyを持つシャード0と1が作られるだけです。

Shard作成

C:\Users\Administrator>aws kinesis create-stream --stream-name MyStream2 --shard-count 2

C:\Users\Administrator>aws kinesis describe-stream --stream-name MyStream2
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream2",
        "Shards": [],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream2",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "CREATING"
    }
}
C:\Users\Administrator>aws kinesis describe-stream --stream-name MyStream2
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream2",
        "Shards": [
            {
                "ShardId": "shardId-000000000000",
                "HashKeyRange": {
                    "EndingHashKey": "170141183460469231731687303715884105727",
                    "StartingHashKey": "0"
                },
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222136977019153325816905058856343758519904923287554"
                }
            },
            {
                "ShardId": "shardId-000000000001",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "170141183460469231731687303715884105728"
                },
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222136999319898524347528200392062031168266429267986"
                }
            }
        ],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream2",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "ACTIVE"
    }
}

Shard分割

C:\Users\Administrator>aws kinesis split-shard --stream-name MyStream2 --shard-to-split shardId-000000000001 --new-starting-hash-key 25521177519070384
7597530955573826158591

C:\Users\Administrator>aws kinesis describe-stream --stream-name MyStream2
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream2",
        "Shards": [
            {
                "ShardId": "shardId-000000000000",
                "HashKeyRange": {
                    "EndingHashKey": "170141183460469231731687303715884105727",
                    "StartingHashKey": "0"
                },
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222136977019153325816905058856343758519904923287554"
                }
            },
            {
                "ShardId": "shardId-000000000001",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "170141183460469231731687303715884105728"
                },
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564222137010470271123612839769950995347893348609294354",
                    "StartingSequenceNumber": "49564222136999319898524347528200392062031168266429267986"
                }
            },
            {
                "ShardId": "shardId-000000000002",
                "HashKeyRange": {
                    "EndingHashKey": "255211775190703847597530955573826158590",
                    "StartingHashKey": "170141183460469231731687303715884105728"
                },
                "ParentShardId": "shardId-000000000001",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222218017927204786101401399656546562681216977338402"
                }
            },
            {
                "ShardId": "shardId-000000000003",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "255211775190703847597530955573826158591"
                },
                "ParentShardId": "shardId-000000000001",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222218040227949984632024541192264835329578483318834"
                }
            }
        ],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream2",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "ACTIVE"
    }
}

Shard結合

C:\Users\Administrator>aws kinesis merge-shards --stream-name MyStream2 --shard-to-merge shardId-000000000000 --adjacent-shard-to-merge shardId-000000
000002

C:\Users\Administrator>aws kinesis describe-stream --stream-name MyStream2
{
    "StreamDescription": {
        "RetentionPeriodHours": 24,
        "StreamName": "MyStream2",
        "Shards": [
            {
                "ShardId": "shardId-000000000000",
                "HashKeyRange": {
                    "EndingHashKey": "170141183460469231731687303715884105727",
                    "StartingHashKey": "0"
                },
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564222136988169525925082216628415277075252202648371202",
                    "StartingSequenceNumber": "49564222136977019153325816905058856343758519904923287554"
                }
            },
            {
                "ShardId": "shardId-000000000001",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "170141183460469231731687303715884105728"
                },
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564222137010470271123612839769950995347893348609294354",
                    "StartingSequenceNumber": "49564222136999319898524347528200392062031168266429267986"
                }
            },
            {
                "ShardId": "shardId-000000000002",
                "HashKeyRange": {
                    "EndingHashKey": "255211775190703847597530955573826158590",
                    "StartingHashKey": "170141183460469231731687303715884105728"
                },
                "ParentShardId": "shardId-000000000001",
                "SequenceNumberRange": {
                    "EndingSequenceNumber": "49564222218029077577385366712969215479879397915381202978",
                    "StartingSequenceNumber": "49564222218017927204786101401399656546562681216977338402"
                }
            },
            {
                "ShardId": "shardId-000000000003",
                "HashKeyRange": {
                    "EndingHashKey": "340282366920938463463374607431768211455",
                    "StartingHashKey": "255211775190703847597530955573826158591"
                },
                "ParentShardId": "shardId-000000000001",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222218040227949984632024541192264835329578483318834"
                }
            },
            {
                "ShardId": "shardId-000000000004",
                "HashKeyRange": {
                    "EndingHashKey": "255211775190703847597530955573826158590",
                    "StartingHashKey": "0"
                },
                "ParentShardId": "shardId-000000000000",
                "AdjacentParentShardId": "shardId-000000000002",
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49564222255527780628714609525462734681157232485581455426"
                }
            }
        ],
        "StreamARN": "arn:aws:kinesis:ap-northeast-1:{AccountId}:stream/MyStream2",
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "StreamStatus": "ACTIVE"
    }
}

あとしまつ

aws kinesis delete-stream --stream-name MyStream2