mongodbのObjectIdの生成規則
MongoDBのマイグレーションとかしてたら,MongoDBのObjectIdって本当にユニークだっけ?っていう疑問がわいた.
確かいろいろな要素を使って,ユニークになるようにできてたよなぁ...と思って,ちゃんと調べてみた.
とりあえず公式のObjectIdの説明.ObjectId - MongoDB Manual 2.4.9
からできているらしい.
↑がんばって書いた.
実験!
同じマシンで生成してみる.
以下の2つのObjectIdは同じマシン上で生成したObjectId.
52fcf106 0af12b af9e 8d5bba 52fcf108 0af12b af9e 8d5bbb
確かに最初のUnix時間は2秒ずれていることがわかる.
マシンIDは同じ.
プロセスIDも同じ.
カウンタは1だけ上がっていることがわかる.
違うマシンで生成してみる.
今度は別のマシンで生成してみる.
確かにマシンIDとプロセスIDが上のObjectIdとは違っている!
52fcebd1 9a5c4e a066 dbfa12
ちなみに,このObjectIdのUnix時間部分
52fcebd1(16進数) → 1392307153(10進数) → 2014/2/14 01:00:10
ちゃんとUnix時間になっていることがわかる.
マシンIDの仕組み
なんとなくユニークになるっぽいっていうのはわかった.
しかし,やはり疑問に思うのは,マシンIDって何だよ!って所だと思う.
Google Group-mongodb-user ›How to get machine id
で,このメーリングリストの投稿によると,マシンIDの生成はクライアント依存らしい.だけど,だいたいのクライアントではhostnameで決めてるらしい.
ということでpymongoの実装部分をみてみた.
マシンIDの生成にはhostname
を使っている...マシンIDに関して言えばユニークじゃないんだね.
もっとユニークなものを使ってマシンIDは生成されると思ってた...
だって,同じhostname
持ってるマシンあるよ.ubuntu
とかさ.
以下の2つはhostname
が同じ別のマシンでpymongoを使って生成したObejectId
確かにマシンIDは同じだ.
52fcf47b 1d41c8 2e90 e33611 52fcf461 1d41c8 75fe aff3e3
ただし,純正のmongoクライアントはhostname
でマシンIDを生成している訳では無いようで,マシンIDは異なるものになっていた.
ObjectIdは本当にユニークなのか?
ObjectIdの構成要素となっている4つの要素
Unix時間
マシンID
プロセスID
カウンタ
はそれぞれは十分重複する可能性があることがわかった.
しかし,これらが組み合わさるとユニークだと言える.
同一のmongoクライアントのプロセスではUnix時間とカウンタがあるので重複することは不可能.
同一マシン上ではmongoクライアントのプロセスIDが異なるので不可能.
別マシン上ではマシンIDが異なるので不可能(hostnameが同じならば可能性がある).
重複するIDを生成するためには以下の条件が必要になる.
同じ時刻の1秒間で,
同じhostnameを持つマシンで,
同じプロセスIDを持つmongoクライアントのプロセスを起動し,
乱数を調整してカウンタをあわせる.
普通に使っている分にはユニークですね.
普通に使いましょう.