Generating unique id numbers in Azure
-
Upload
takekazu-omi -
Category
Technology
-
view
2.466 -
download
5
description
Transcript of Generating unique id numbers in Azure
Generating unique ID numbers
in Microsoft Azure
kyrt Takekazu Omi
@takekazuomi
2014/3/29 1.0.1
Generating unique ID numbers
in Microsoft Azureスケーラブルな ID 生成手法の比較と、 twitter snowflake に見る工夫
2014/2/26 kyrt @takekazuomi 2
Agenda
• Challenge• スケーラブルなサービスとスケーラブルな採番
• twitter snowflake• スケーラブルな分散採番サービスの例
• Cloud Design Patterns• 応用例
kyrt @takekazuomi 32014/2/26
Challengeスケーラブルなサービスには、スケーラブルな採番が必須課題と背景的な話「またの名を Challenge を課題と訳さないで」
2014/2/26 kyrt @takekazuomi 4
ID 生成の要件
1. ユニークである重複が無い。これは ID をキーにしたいので当然ですね。
2. 時系列で増えていく(または減っていく)ID が生成される度に増加していくのは連番での重要な性質の一つ
3. 秒間の発行数採番を一箇所で行わずに分散してするとスケールする
4. 連続性連続した欠落の無い番号の生成
kyrt @takekazuomi 52014/2/26
ID 生成のパターン
1. SQL Database の自動連番を使う• スケールしない、耐障害性を考慮すると複数台必要
2. ID Provider が完全に独立して存在する• GUID 等、 128bit 16 byte
3. 擬似 ID Provider が、擬似 ID を生成し、 UNIQUE 性は別システムで担保される
4. ID Provider の Network Service を使う• Azure Cache, memcached, redis の increment 等
5. ID Provider の Cluster Service が実装されていて Cluster 内で合意をとって ID を生成する• snowflake
kyrt @takekazuomi 6
最初の2つ
• SQL Database の利用• 秒間の発番数、同時接続数に問題なければ、従来どおり利用可能• 上記の問題があるなら、複数の DB を使う (sharding) という方法も
ある• しかし、仕組みとしてはちょっと重い。コストも高い。• 秒間 100 程度まで
• GUID の利用• クライアントで完結するので、速くてスケールするしかし• 128bit あって長い( 16 byte)• 時系列で並ばない→ 時間由来のデータを prefix にすることで解決
kyrt @takekazuomi 7
時系列のキーの例
.Net なら、 Tikcs などを使う
こんな感じvar id =
string.Format("{0:D19}{1:N}",DateTime.UtcNow.Ticks, Guid.NewGuid());
var reverseId =
string.Format("{0:D19}{1:N}“,long.MaxValue-DateTime.UtcNow.Ticks, Guid.NewGuid());
結果0635317467093215594d1931d619d7041c69ececd37383ca4ae85880545697615502266d18953688dc4fbdb84da60f4d8e25c8
しかし長い・・・・・ 19+32 で 51 文字。(工夫の余地はあるけど)kyrt @takekazuomi 8
擬似 ID Provider パターン
• Client で擬似的に ID を生成して、 UNIQUE 性は、永続化レイヤーで担保• retry の発生頻度にパフォー
マンスが依存• 性能が永続化レイヤーに依存• スケールのためには永続化レ
イヤーの分散が必要• SQL Database < Storage
Table ( 分散の容易度 )
kyrt @takekazuomi 9
SQL Database (Windows Azure)
Storage Table
or
④ retry
Client 永続化レイヤー
① 擬似 ID で Insert
② 重複無しで成功
③ 重複有りで失敗
Cache などの Network Service を利用
• RBD の自動連番より小さなレイテンシー (1-2ms)• ID は時系列で増える• 耐障害性に課題
• HA 構成、永続化オプションを考慮
• 工夫• 起動時の時間+ incremental
number• 障害後にかぶらないように
kyrt @takekazuomi 10
Client Cache
ID を取得
Windows Azure Cache
memcached
or
redis
or
課題整理
1. latency (レイテンシー)HA のために、 Node 間通信、永続化に時間がかかる。 retry が発生すると時間がかかる
2. reliability (信頼性)採番系が一箇所なのは、 UNIQUE の担保には有利だが、障害に弱くなる。→分散すれば Ok
3. scalability (スケーラビリティ)分散が必要。 ID 生成が分散して Node 間通信が少なければ、スケーラビリティが上がる
4. data size (データサイズ)data size を大きくして冗長性を増せば、 retry の頻度は下がる
kyrt @takekazuomi 11
特性の比較
kyrt @takekazuomi 12
latency reliability scalability data size
SQL 自動連番 ◯ × × ◯
GUID 等 ◯ ◯ ◯ ×
Pseudo ID and Retry △※ 1 ◯ ◯ △
Cache ◯ × △ ◯
Snowflake ◯ ◯ ◯ ◯
※ 1 Data Size を小さくすると、衝突が起きやすくなるのでレイテンシーが上がる
ここまでのまとめ
• 永続化ストレージ• latency (↓)、 reliability (↑)、 scalability (↓)、 data size (↑)• scalability 改善には、パーティショニングが必要 → パーテーションを跨い
だ UNIQUE 性に制限、 data size (↓)
• On Memory• latency (↑)、 reliability (↓)、 scalability (↓)、 data size (↓)• reliability 改善
• 複数 Node で HA 構成にすれば良い。しかし、更新の度に、 Node 間で通信して合意をとると latency が悪化
• scalability 改善• シングル Node だと Node の性能上限=スケールの上限になってしまうので、複数
Node 構成にしたい。しかし、
kyrt @takekazuomi 13
↑ :良↓ :悪
こんなのがあったら
•GUID のように速く•SQL の自動採番のように並んで•簡単に使える•そんなに長くない (longぐらいで入ると嬉しい)
kyrt @takekazuomi 14
twitter snowflakehttps://github.com/twitter/snowflake/
kyrt @takekazuomi 15
snowflake の短い説明
• snowflake は、 Twitter 社が作成した、 UNIQUE な ID 生成のネットワークサービス。いくつかの簡単な保証で高いスケーラビリティを実現
• Twitter 社が、 MySQL から Cassandra に移行するにあたって、 Cassandra には シーケンシャルな id 生成の仕組みが無かったことから作成• 参考: Twitter IDs, JSON and Snowflake
https://dev.twitter.com/docs/twitter-ids-json-and-snowflake• ソースは https://github.com/twitter/snowflake/ に公開• ライセンス、 Apache License, Version 2.0
kyrt @takekazuomi 162014/2/26
基本的なアイディア
• Clock Skew (クロックスキュー)に上手く対応することで、オンメモリの計算だけで UNIQ な ID を生成する
• 永続化レイヤーの支援無しに UNIQ な ID が生成できる、 ID 生成はオンメモリなので速い( 10k ids per second per process Snowflake https://github.com/twitter/snowflake/ )というのが特徴
• GUID v1 と似ているが、半分のデータ量 64bit(long) で、おおよそ時系列で増えていく「 (Roughly) Time Ordered 」
kyrt @takekazuomi 17
データ構造
• snowflake では、 64bit を上記のように分割して使います• time が時間由来の数字でミリ秒単位• machine id は、 datacenter id と、 worker id で構成されていて、
Cluster 内の Node固有の値• sequence number は、同一時間の連番
kyrt @takekazuomi 18
ポイント
• 時間由来のデータが先頭 41bit なので発番の時間順に並びます• ms で 41bit だと (2^41)*(10^-3)/60/60/24/365 で約 69年
•各インスタンスは、 クラスター内で UNIQUE な、 machine id を持ちます• machine id が重複しない限りは ID は重複しない
• 同時間内の発番では、 sequence number がインクリメントされます• ms 内の発番は、 2^12 = 4096 まで
採番情報は on memory のみで処理kyrt @takekazuomi 19
コード上の工夫
• なかなか興味深かったので、 IdWorker.scala を C# で写経https://gist.github.com/takekazuomi/9571376
kyrt @takekazuomi 20
time skew対策
• 最後に発番してから timestamp が戻っていないか確認 L63• 巻き戻っていればエラーで帰る(呼び出し側が再試行する)
kyrt @takekazuomi 21
time 41bit の有効利用
•開始時間を採番の開始時間と合わせて bit を有効利用• TwEpoch は、 2010/11/04 。 2010/11/01 + 69年
kyrt @takekazuomi 22
sequence
• 同一 timestamp なら、 _sequence をインクリメントして採番 `L72 <https://gist.github.com/takekazuomi/9571376#file-idworker-cs-L72>`_• timestamp が進んでいれば、 _sequence = 0 で採番 `L82
<https://gist.github.com/takekazuomi/9571376#file-idworker-cs-L82>`_• 同一 timestamp 内で、 _sequence がオーバーフローした場
合は、 timestamp が変わるまで待つ `L75 <https://gist.github.com/takekazuomi/9571376#file-idworker-cs-L75>`_
kyrt @takekazuomi 23
起動時にWorker Id の重複を確認
構成
• snowflake の Worker は複数の Node で構成• Node の起動時に Worker Id
の重複を zookeeper を使って担保
• GUID では、 MAC Address 48bit が、 machine Id相当
kyrt @takekazuomi 24
Client
snowflake cluster
ID 要求
zookeeper cluster
machine id を重複させない仕組
• snowflake では、 machine id の下位 5bit の Worker Id をzookeeper で管理しています• 起動時に Worker Id で、 Ephemeral Nodes を作成
kyrt @takekazuomi 25
/workerIdZkPath
/
/0 /1 /2 /n
worker id の ephemeral node
1. 同じ Node 名では1つのみ2. session が切れると node は消える
kyrt @takekazuomi 26
Micorosoft Azure でどうするか
• Azure Blob のリースを使うとほぼ同じことができます• Worker Id の path の lease が取れば、重複なしで起動 Ok• インスタンスが生きてる間は、 Lease を更新• 参考: Cloud Design Patterns
• patterns & practices• Leader Election Pattern 、 BlobDistributedMutex
/workerIdZkPath
/
/0 /2 /n/1
Blob Lease でBlobDistributedMutex 利用
まとめ
• snowflake は、 on memory で時間情報を元に高速に ID を生成する• ID の一部には machine id が含まれていて、 node の起動
時に zookeeper を使って重複を確認する• 起動後は、 node-zookeeper 間の通信は ephemeral nodes
の keep alive のみ• 時間の巻き戻り対策がされている( time service対策)• zookeeper の ephemeral nodes 相当の機能は Azure Blob
で実装できる
kyrt @takekazuomi 27
Appendix
2014/2/26 kyrt @takekazuomi 28
リファレンス• Twitter IDs, JSON and Snowflake
• https://dev.twitter.com/docs/twitter-ids-json-and-snowflake
• snowflake source code• https://github.com/twitter/snowflake/
• Cloud Design Patterns / patterns & practices• Leader Election Pattern http://msdn.microsoft.com/en-us/library/dn568104.aspx• BlobDistributedMutex Code http://aka.ms/cloud-design-patterns-sample
• Apache ZooKeeper• http://zookeeper.apache.org/• http://zookeeper.apache.org/doc/r3.2.1/zookeeperProgrammers.html#Ephemeral+Nodes
• Twitter の snowflake について(お勧め)• http://www.slideshare.net/moaikids/20130901-snowflake
• 全ての情報は 2014/3/29 時点のものです。2014/2/12 kyrt @takekazuomi 29