前提
例えば、コレクションA
のドキュメントにnumber
というユニークな連番を保持するフィールドが必要だとする。
条件として、MongoDBはReplicaSetで構成されていて、複数のアプリケーションサーバーから参照されている状態とし、write concernとフィールドのuniq設定は使えないものとする。また、ナンバリングしたデータは直ぐには必要のないデーターとする。
上記の場合、アプリケーションサーバー側でnumber
フィールドのmax numberを取得し、そのアプリケーションのプログラム上でnumber
をインクリメントして最新の最大number
として保存すると、アプリケーションサーバー側が同じmax number
を掴む可能性があるので、ユニーク値での連番が作れない可能性がでてくる。
それでも、発番をしたい場合どうすべきかを2パターン、MongoDBを使ってどうするかということが課題としてあったので考えてみた。
パターン1 ジョブキューを使う
- 構成例
項目 | 説明 |
---|---|
App Server | Python Tornado冗長化構成 |
Job Server | RQ numberingキューを 1つのジョブワーカーに設定 |
Queue DB Server | Redis (AWS ElastiCascheを利用) |
Backend DB Sever | MongoDB (ReplicaSet構成) |
"""
APP Servers(Python Tornado)
↓ ジョブをnumberingキューに追加
Redis Servers
↑↓ numberingキューからジョブを取得して実行
rq worker
↓ DBをアップデート
MongoDB
"""
作業
- 既にジョブキューサーバーがあれば、キューを1つのジョブワーカーに設定
- アプリケーションサーバー側でジョブを作成しenqueueする
特徴
- キューがあれば都度実行
課題
- データーは保持されるが、ワーカー1台だと、それがspof
- 処理が増えた場合、スケールアップの対応しかできない
- ジョブキューサーバーが対応してる言語に依存するので、汎用性は低い
パータン2 メッセージキューを使う
- 構成例
項目 | 説明 |
---|---|
App Server | Python Tornado冗長化構成 |
Message Queueu | AWS SQS |
Batch Server | EC2 Instance上で1プロセスのみ実行 |
Backend DB Sever | MongoDB (ReplicaSet構成) |
"""
APP Servers(Python Tornado)
↓ キュー情報を追加
AWS SQS
↑↓ キュー情報を取得してバッチプログラムで処理
Batch Server
↓ DBをアップデート
MongoDB
"""
作業
- バッチで動かすためのプログラムを書く
- アプリケーション側にenqueue処理を追加
特徴
- プログラム言語の依存は低い
課題
- データーは保持されるが、バッチがこけると処理が止まるという問題
- スケールアップの対応しかできない
まとめ
結構制約が多い中どうするか、numberingやめて_idを使えばいいじゃんとか妥協案はあるのですが、どうしてもナバリングしたい。
上記の様に考えてみるとやはりドキュメントのnumberingを一貫性を保ちながら処理していくことは結構大変。
ただ、非同期に処理をすることでなんとなくできそうだということもわかった。
あと、規模によっては、課題にある問題でnumberingがうまく動かなかった場合の復活の呪文プログラムも別途用意しておけば、実運用的には問題ないということもなんとなくわかった。
__一貫性を保った処理をしたい場合(ナンバリングしたデータは直ぐには必要のないデーターというのが前提だが)ジョブキューかメッセージキューを使う__とそれなりに対応できるかもしれない。
他に良いアイディアがあれば、教えてもらいたい。