More Related Content More from Takahiro Inoue (20) Mongo sharding3. 発表の目的 Mongo Shardingへの理解を深めてほしい 1. Mongo Shardingの特徴を知ってほしい 2. なかなか知り得ない機能詳細や意外な振る舞いがあることを知って欲しい 3. 使用上における問題点をきちんと把握しておいて欲しい 4. Mongo Shardingを試すきっかけになって欲しい 5. アジェンダ 1. Mongo Shardingの3つのコンセプトを紹介 -> 概要の理解 2. Mongo Shardingの機能・振る舞いを4つのキーワードから紹介 -> 個々の機能の深い理解 6. 最終的に言いたいこと Shard Key の設定は非常に重要、慎重に Shard の偏りを極力減らす事は重要 Shard Key によって偏り具合が大きく異なる Sharding環境におけるクエリは振る舞いが怪しい部分があるので要注意(重複問題) 正しい count() が行われない unique のはずのキーが重複して存在 9. Mongo Sharding Concept MongoDBの掲げる3つのコンセプト 「Make the cluster “invisible”」 「Make the cluster always available for reads and writes」 「Let the cluster grow easily」 10. Mongo Sharding Concept 1 Make the cluster “invisible” 全ての接続をmongosサーバーが仲介することによってクライアントはクラスタ全体の情報を意識することなく扱える クライアントはShardingしていない状況と同じようにクエリを発行し、結果を得ることができるより高速に) 11. Mongo Sharding Concept 2 Make the cluster always available for reads and writes Auto-Failover でMongoDBのダウン時間を減らせ、常にデータにアクセスできる状態 データの自動分割や Auto-balancing によって常に安定した状態を保ち続けられる 12. Mongo Sharding Concept 3 Let the cluster grow easily Shardの追加・撤退が容易にできる 新しいShardの追加に対して自動的にデータの移行・均一化が図れる(Migration, Auto-Balancing) 14. Mongo Shardingを理解するための4つのキーワード Shard Key: コレクションを分割する際のキー Balancing, Migration: Shard 間のデータの均等な分散を維持する仕組み mongos, config, mongod: Shardingを構成する3種類のサーバー Shardingクエリ: Sharding環境におけるクエリの振舞と問題点 16. Shard Key:概略 データの分割は何らかのキーに従って行う それを Shard Key と呼ぶ Shard Key は Collection 内のどれか1つのキーから選択 各 Shard 内のデータは Chunk と呼ばれるデータ単位で分割・移動・削除などが行われる Shard 間の偏りとは、Chunkの数が一部に偏る事 Shard が偏るのはよろしくない 17. Chunk に関して Chunkは、特定のコレクションの連続した範囲のデータ集合 データがどの Chunk に属するかは、Shard Key の値によって決まる Chunk はデータサイズが200MB(デフォルト)を超えると自動で等分割が行われる 分割されるごとにShard 内の Chunk 数が増加 Shard Key は型の混在が可能。MongoDBは全ての型を通して順序が決まっている 22. Chunk に関する注意点 各々の Chunk の持つ範囲は絶対に重複しない。1つのデータに対してただ1つの Chunk が対応。範囲は [ a, b ) で、左を含み右を含まない Shard Key は変更できない。やり直したい場合は対象の Collection を削除してから ShardKeyの値を持たないドキュメントは保存できない。ただし null は可能 24. Auto-balancing, Migration Auto-balancing ある特定の Shard に Chunkが集中した場合、自動で他の Shard への移行(=Migration) トリガーは Shard 内における最大 Chunk 数と最小 Chunk 数の差が10以上になったとき デフォルトで最大 200MB/Chunk なのでデータサイズの差が2GB以上になったとき 最大 Shard からランダムに5つの Chunk が選ばれ、最小 Shard への Migration が行われる 27. Shard Key 選択の重要性 Migration は極力起こらないように つまり Shard 間に Chunk の偏りがない Shard 間に偏り少なくなる Shard Key を選択 一度選択したShardKeyは変更できないので慎重に 28. Shard Key: 悪い例① Low-Cardinality Shard Key 「密度」の低い Shard Key 主にカテゴリデータなどの”離散”データ 例:大陸名 (-∞, America], (America, Asia], (Asia, Australia],… 理由: Chunk の分割ができない N 個のカテゴリ数なら N 個の Chunk しかできない N 個以上の Shard サーバーは意味がない 29. Shard Key: 悪い例② Ascending Shard Key Shard Key の値が増えていくのみのデータ Time, ObjectId, Incremental Unique Id 例: [-∞, +∞ ) -> [ -∞, 12945 ), [12945, +∞ ) -> [ -∞, 12945 ), [12945, 12948 ), [ 12948, +∞ ) 理由: ( $CurrentMax, +∞ ] の Chunk だけがひたすら分割 明らかに Shard 間で不均一がおこる 30. ShardKey: 悪い例③ Random Shard Key Shard Key の値が Random に決まる場合 例:MD5 hash 理由: Chunk は均等分散するが非常に大きな範囲を持った Chunk が存在する可能性 その Chunk の Migration はRAMを圧迫する Random Shard Key に対する Index も非効率 31. Shard Key: 良い例 Coarsely Ascending Key + Search Key 緩く増加していくキー + 検索でよく使われるキー 例:アクセス解析 { month:1, user: 1} ( (“2011-04”,”doryokujin”), (“2011-04”, “gohan”) ), ( (“2011-04”,”gohan”), (“2011-04”, “taberu”) ),… 理由: 左のキーは一定期間固定で、右のキーはほぼ均等に分布してくれる 時間がたつと左のキーの値が増え、元の(解析対象としない、古い)値の Chunk は分割されなくなり、 Migration が起こりにくくなる 32. 良い Shard Key のイメージ 長い時間が経って Shard の偏りが起き始める頃に、片方のキーが増加して Shard をリフレッシュしてくれる shard2 shard3 shard4 shard5 shard6 shard1 name 2011/04 2011/05 month 34. Shardingを構成するサーバー群 Cluster Shard Servers (Data) config Servers (Shard Configration) shard3 shard1 shard2 [ a, f ) [ k, n) [ o, t ) Chunk [ f, k ) [ n, o ) [ t, } ) mongos Servers (Routers) 39. configサーバーの役割 shards, mongos process, sysadminに関するメタ情報を保持 複数起動可能。ただしテスト環境は1つ、本番環境でも3つで十分(3で最適化) 独自のプロトコルで同期を行う。手動でReplicationの設定をしてはいけない [ ダウン ]:Shardの設定変更が不可能になる。読み書きは継続 40. config Collection > use config switched to db config > show collections changelog# 過去の Migration に関する詳細なログ chunks # 全てのChunk の情報 collections # Shardingしている全ての Collection の情報 databases # 全DBに関してShardingの有無などの情報 lockpings locks mongos# mongosに関する情報 settings # chunkSizeの設定情報、balancer機能の切替 shards # Shard に関する情報 system.indexes version > db.settings.update({"_id" : "balancer"}, {"$set" : {"stopped" : true }}, true) 43. Shard Key を用いての find() targeted db.adminCommand({"shardCollection" : ”mongo.users", key : {”name" : 1}} shard3 shard1 [ a, f ) [ o, t ) {“name”: “inoue” } [ f, k ) [ t, } ) mongos {“name”: “tanaka” } 指定された Shard Key (“name” key)を含む Chunkの あるShard にのみクエリの発行・データの取得を行う shard2 db.shardCollection.find({“shardKey”: “xxx”}) [ k, n) [ n, o ) 44. Non Shard Key を用いての find() global shard1 db.adminCommand({"shardCollection" : ”mongo.users", key : {”name" : 1}} [ a, f ) [ f, k ) mongos {“pref”: “Tokyo” } mongosは Shard Key 以外 (“pref” key)の情報を 知り得ないので全ての Shard にアクセスする。 ただしインデックスを利用できる。 shard3 shard2 [ o, t ) db.shardCollection.find({“nonShardKey”: “xxx”}) [ k, n) [ t, } ) [ n, o ) 45. Shard Key を用いての single-update() targeted db.adminCommand({"shardCollection" : ”mongo.users", key : {”name" : 1}} shard3 shard1 [ a, f ) [ o, t ) update {“name”: “inoue” } [ f, k ) [ t, } ) mongos {“name”: “tanaka” } 指定されたshard key(“name” key)を含むchunkのある shardにのみクエリの送出・データの取得を行う shard2 db.shardCollection.update({“shardKey”: “x”},{$set{key:value}}) [ k, n) [ n, o ) update 46. Non Shard Key を用いての sort() global shard1内でsort shard1 [ a, f ) shard1,2,3の結果 を merge sort [ f, k ) shard2内でsort {“pref”: “Tokyo” } mongos sort() が呼ばれた場合は、各 Shard における 検索結果のドキュメント集合に対してsortを行い、 さらにmongosが全Shard で merge sort shard3内でsort shard3 shard2 [ o, t ) db.shardCollection.find().sort({“nonShardKey”: 1}) [ k, n) [ t, } ) [ n, o ) 47. Non Shard Key を用いての count() global shard1内でcount shard1 [ a, f ) shard1,2,3の 結果で count [ f, k ) shard2内でcount {“pref”: “Tokyo” } mongos count() が呼ばれた場合は、各 Shard における 検索結果のドキュメント集合に対して count を 行い、さらにmongosが全 Shard の結果で total shard3内でcount shard3 shard2 [ o, t ) db.shardCollection.count ({“nonShardKey”: 1}) [ k, n) [ t, } ) [ n, o ) 48. Non Shard Key を用いての mapreduce() global mapreduce shard1 [ a, f ) shard1,2,3の結果 で ”re”-reduce [ f, k ) mapreduce mongos emit( “pref”: 1 ) mapreduce() が呼ばれた場合は、各 Shard における 検索結果のドキュメント集合に対してmapreduceを 行い、さらにmongosが全 Shard の結果で reduce shard3 mapreduce shard2 [ o, t ) [ k, n) db.runCommand ({mapreduce: shardedCollection,…}) [ t, } ) [ n, o ) 49. { x : 1 } Shard Key と仮定。 targetedでは Shard へのアクセスは最小限 globalは、システム内の(ほぼ)すべての Shard にアクセス 50. Shard Key を使用しない場合に問題のあるクエリ Sharding環境で Shard Key を使用しないクエリは、必ずしも正しく実行されるとは限らない 「Chunk Migration 中の count()」 「同時書き込み発生時の single-update()」 「同時書き込み発生時の unique index」 「tmp_collectionが削除されないmapreduce()」 51. Chunk Migration 中の count() Chunk Migration 中は処理が完了するまで、移動元・移動先に同じ Chunk が存在する 完全にコピーが完了し、configサーバーが更新されて完了となる その間に count() コマンドが実行された場合、この Chunk のデータは重複してカウントしてしまう可能性がある。 結果:真値より大きくなる 52. Chunk Migration 中の count() shard2 shard2 shard1 shard2 shard1 shard1 X X count X mongos count X 重複カウント X 移行中… X 54. 同時書き込み発生時のunique Index {"_id" : ObjectId("4d2a2f7c56d1bb09196fe7d0"), ”name" : ”doryokujin", "email" : “doryokujin@example.com” } shard 1 shard2 shard3 X update mongos {"_id" : ObjectId("4d2a2e9f74de15b8306fe7d0"), ”name" : ”doryokujin", "email" : ”inoue@example.com" update Y mongos shardKey={“email”:1} とは別に unique Index={“name”:1} である Key で の update が同時に行われた場合、unique キーなのに重複する可能性がある Z 58. Mongo Shardingを理解するための4つのキーワード Shard Key: コレクションを分割する際のキー Balancing, Migration: Shard 間のデータの均等な分散を維持する仕組み mongos, config, mongod: Shardingを構成する3種類のサーバー Shardingクエリ: Sharding環境におけるクエリの振舞と問題点 59. 最終的に言いたいこと Shard Key の設定は非常に重要、慎重に Shard の偏りを極力減らす事は重要 Shard Key によって偏り具合が大きく異なる Sharding環境におけるクエリは振る舞いが怪しい部分があるので要注意 正しいcount()が行われない uniqueのはずのキーが重複して存在