🔖

ひとりMongoDB University / M103まとめ

2021/03/03に公開

この記録は、アドベントカレンダー形式ではじめた、MongoDB Universityの学習コースの記録の続きになります!今回は、M103のコースのまとめ問題 / Final Examの回答を記載していきます。

ただいまのコース

2020年12月中旬から、休み休みですが取り組んでいます。
最後のShardingの章の演習課題の回答をアップします。(2/3に完了しました!)

コース完了までの時間は9.5時間程度、とありますが、わたしは休み休み、それから手元でサーバを上げたりしながら進めたのもあって、結果的にはギリギリの2ヶ月で完走しています。

Final Exam

Final: Question 1

Problem:

Which of the following are valid command line instructions to start a mongod? You may assume that all specified files already exist.
mongod起動のために適切なコマンドはどれ?(必要な設定ファイルは揃っているものとします)

Answer:


# --forkでバックグラウンドで起動の場合は、logpathを必ず指定する(標準出力じゃなくログへ)
mongod --logpath /var/log/mongo/mongod.log --dbpath /data/db --fork

# 設定ファイル指定の場合はこのように
mongod -f /etc/mongod.conf

Ref: Start mongod as a Daemon

  • デーモンモードでの起動の場合は、ログパス(ログの書き出し先)を指定すること
    • To run a mongod process as a daemon (i.e. fork), and write its output to a log file, use the --fork and --logpath options.

Final: Question 2

Problem:

以下のような設定ファイルがあった場合:

storage:
  dbPath: /data/db
systemLog:
  destination: file
  path: /var/log/mongod.log
net:
  bindIp: localhost,192.168.0.100
security:
  keyFile: /var/pki/keyfile
processManagement:
  fork: true

How many directories must MongoDB have access to? Disregard the path to the configuration file itself.
MongoDBのプロセスがアクセスする必要があるディレクトリの数はいくつ?(設定ファイルが配置されているディレクトリは数に含めないで)

Answer:

  • 3つ
    • /data/db/, /var/log/, それとキーファイルのある /var/pki/

Final: Question 3

Problem:

rs.status().members コマンドの結果が次のような場合:

※ rsコマンドなのでレプリケーションのステータスに関連する。

[
  {
    "_id": 0,
    "name": "localhost:27017",
    "health": 1,
    "state": 1,
    "stateStr": "PRIMARY",
    "uptime": 548,
    "optime": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDate": ISODate("2018-03-14T14:47:51Z"),
    "electionTime": Timestamp(1521038358, 2),
    "electionDate": ISODate("2018-03-14T14:39:18Z"),
    "configVersion": 2,
    "self": true
  },
  {
    "_id": 1,
    "name": "localhost:27018",
    "health": 1,
    "state": 2,
    "stateStr": "SECONDARY",
    "uptime": 289,
    "optime": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDurable": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDate": ISODate("2018-03-14T14:47:51Z"),
    "optimeDurableDate": ISODate("2018-03-14T14:47:51Z"),
    "lastHeartbeat": ISODate("2018-03-14T14:47:56.558Z"),
    "lastHeartbeatRecv": ISODate("2018-03-14T14:47:56.517Z"),
    "pingMs": NumberLong("0"),
    "syncingTo": "localhost:27022",
    "configVersion": 2
  },
  {
    "_id": 2,
    "name": "localhost:27019",
    "health": 1,
    "state": 2,
    "stateStr": "SECONDARY",
    "uptime": 289,
    "optime": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDurable": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDate": ISODate("2018-03-14T14:47:51Z"),
    "optimeDurableDate": ISODate("2018-03-14T14:47:51Z"),
    "lastHeartbeat": ISODate("2018-03-14T14:47:56.558Z"),
    "lastHeartbeatRecv": ISODate("2018-03-14T14:47:56.654Z"),
    "pingMs": NumberLong("0"),
    "syncingTo": "localhost:27022",
    "configVersion": 2
  },
  {
    "_id": 3,
    "name": "localhost:27020",
    "health": 1,
    "state": 2,
    "stateStr": "SECONDARY",
    "uptime": 289,
    "optime": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDurable": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDate": ISODate("2018-03-14T14:47:51Z"),
    "optimeDurableDate": ISODate("2018-03-14T14:47:51Z"),
    "lastHeartbeat": ISODate("2018-03-14T14:47:56.558Z"),
    "lastHeartbeatRecv": ISODate("2018-03-14T14:47:56.726Z"),
    "pingMs": NumberLong("0"),
    "syncingTo": "localhost:27022",
    "configVersion": 2
  },
  {
    "_id": 4,
    "name": "localhost:27021",
    "health": 0,
    "state": 8,
    "stateStr": "(not reachable/healthy)",
    "uptime": 0,
    "optime": {
      "ts": Timestamp(0, 0),
      "t": NumberLong("-1")
    },
    "optimeDurable": {
      "ts": Timestamp(0, 0),
      "t": NumberLong("-1")
    },
    "optimeDate": ISODate("1970-01-01T00:00:00Z"),
    "optimeDurableDate": ISODate("1970-01-01T00:00:00Z"),
    "lastHeartbeat": ISODate("2018-03-14T14:47:56.656Z"),
    "lastHeartbeatRecv": ISODate("2018-03-14T14:47:12.668Z"),
    "pingMs": NumberLong("0"),
    "lastHeartbeatMessage": "Connection refused",
    "configVersion": -1
  },
  {
    "_id": 5,
    "name": "localhost:27022",
    "health": 1,
    "state": 2,
    "stateStr": "SECONDARY",
    "uptime": 289,
    "optime": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDurable": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDate": ISODate("2018-03-14T14:47:51Z"),
    "optimeDurableDate": ISODate("2018-03-14T14:47:51Z"),
    "lastHeartbeat": ISODate("2018-03-14T14:47:56.558Z"),
    "lastHeartbeatRecv": ISODate("2018-03-14T14:47:55.974Z"),
    "pingMs": NumberLong("0"),
    "syncingTo": "localhost:27017",
    "configVersion": 2
  },
  {
    "_id": 6,
    "name": "localhost:27023",
    "health": 1,
    "state": 2,
    "stateStr": "SECONDARY",
    "uptime": 289,
    "optime": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDurable": {
      "ts": Timestamp(1521038871, 1),
      "t": NumberLong("1")
    },
    "optimeDate": ISODate("2018-03-14T14:47:51Z"),
    "optimeDurableDate": ISODate("2018-03-14T14:47:51Z"),
    "lastHeartbeat": ISODate("2018-03-14T14:47:56.558Z"),
    "lastHeartbeatRecv": ISODate("2018-03-14T14:47:56.801Z"),
    "pingMs": NumberLong("0"),
    "syncingTo": "localhost:27022",
    "configVersion": 2
  }
]

At this moment, how many replica set members are eligible to become primary in the event of the current Primary crashing or stepping down?
現在のプライマリがクラッシュしたり、状況により降格した場合、プライマリに昇格可能なレプリカセットのメンバー数はいくつ?

Answer:

  • 5つ
    • "_id": 4 のメンバーが利用不能になっている
    • 出力されたノードは全部で7つ
    • プライマリを除外すると6つで、そのうち1つが利用不可のため

Final: Question 4

Problem:

次のようなレプリカセットの設定があった場合:

conf = {
  "_id": "replset",
  "version": 1,
  "protocolVersion": 1,
  "members": [
    {
      "_id": 0,
      "host": "192.168.103.100:27017",
      "priority": 2,
      "votes": 1
    },
    {
      "_id": 0,
      "host": "192.168.103.100:27018",
      "priority": 1,
      "votes": 1
    },
    {
      "_id": 2,
      "host": "192.168.103.100:27018",
      "priority": 1,
      "votes": 1
    }
  ]
}

What errors are present in the above replica set configuration?
上記の設定でどんなエラーがありますか?

Answer:

まちがっているものを選択(その理由も添える):

  • "_id": 0 のエントリが2つ存在するのがNG
  • "host": "192.168.103.100:27018" が別々のidに対して重複して存在するのがNG

上記の設定でも正しいのは以下:

  • レプリカセットのメンバーが合計で3つ(奇数であることが前提)
  • レプリカセットのプライオイティには0は設定できない

Final: Question 5

Problem:

次のようなレプリカセットの設定があった場合:

conf = {
  "_id": "replset",
  "version": 1,
  "protocolVersion": 1,
  "members": [
    {
      "_id": 0,
      "host": "localhost:27017",
      "priority": 1,
      "votes": 1
    },
    {
      "_id": 1,
      "host": "localhost:27018",
      "priority": 1,
      "votes": 1
    },
    {
      "_id": 2,
      "host": "localhost:27019",
      "priority": 1,
      "votes": 1
    },
    {
      "_id": 3,
      "host": "localhost:27020",
      "priority": 0,
      "votes": 0,
      "slaveDelay": 3600
    }
  ]
}

What is the most likely role served by the node with "_id": 3?
"_id": 3 のノードのロールはどんなものが適切?

Answer:

  • It serves as a "hot" backup of data in case of accidental data loss on the other members, like a DBA accidentally dropping the database.
    • ホットバックアップとして稼働するノードになる
    • priorityは0で、プライマリには昇格の対象ではない
    • slaveとしてのデータの同期は1時間の遅延があるので、プライマリとその他遅延のないセカンダリがクラッシュしてデータが飛んでしまっても、この id: 3 のノードのデータは即時にはロストしないので

Final: Question 6

Problem:

次のようなシャードキーの設定があった場合:

{ "country": 1, "_id": 1 }

Which of the following queries will be routed (targeted)? Remember that queries may be routed to more than one shard.
このシャードキーで効果的にカバーできるクエリはどれ?

Answer:


// _idは暗黙のうちに利用される、かつ上記のシャードキー順になっているのでOK
db.customers.find({"country": "Norway", "_id": 54})

// _idは暗黙のうちに利用される、かつ上記のシャードキーの通りにcountryがprefixとして利用されるのでOK
db.customers.find({"country": { $gte: "Portugal", $lte: "Spain" }})

// シャードキーの指定通りのprefixでのクエリなのでOK
db.customers.find({"_id": 914, "country": "Sweden"})

// シャードキーで指定されたcountryが使われていないので、このクエリは全てのシャードのクラスタに対して問合せをしに行く形になる
db.customers.find({"_id": 455})

Ref.

コース完走

途中間違えてしまい、何回かリトライして終了でした!

次はAggregationではなく、こちらのコース(2時間程度)をやってみます!

Discussion