MongoDB ~ 从入门到入坑。

MongoDB~从入门到入坑。


文章目录


相关概念。

业务应用场景。

传统的关系型数据库(eg. MySQL),在数据操作的“三高”需求以及应对 Web 2.0 的网站需求前,显得力不从心。

  • 三高。
  • high performance。对数据库高并发读写的需求。
  • high storage。对海量数据的高效率存储和访问的需求。
  • high scalability & high availability。对数据库的高可扩展的高可用的需求。
  • 具体应用场景。
  • 社交场景。用 MongoDB 存储用户信息,以及用户发表的朋及圈信息,通过地理位置索引实现附近的人、地点等功能。
  • 游戏场景。使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方使查询、高效率存储和访问。
  • 物流场景。使用 MongoDB 存储订单信息,订单状态在运输过程中会不断更新,以 MongoDB 内嵌的形式来存储,一次查询就能将订单所有的变更读取出来。
  • 物联网场景。使用 MongoDB 存储接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
  • 视频直播。使用 MongoDB 存储用户信息,点赞互动信息等。

在这些应用场景中,数据操作方面的共同特点是。

数据量大。
读写操作频繁。
价值较低的数据,对事务要求不高。

何时选用。

  • 应用不需要事务及复杂的 join 支持。
  • 新应用,需求会变,数据模型无法确认,想快速迭代开发。
  • 应用需要 2000 ~ 3000 以上的读写 QPS。
  • 应用需要 TB 甚至 PB 级数据存储。
  • 应用发展迅速,需要能快速水平发展。
  • 应用要求存储的数据不丢失。
  • 应用需要 99.999% 的高可用。
  • 应用需要大量的地理位置查询、文本查询。


MongoDB。

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 json 的 bson 格式,因此可以存储比较复杂的数据类型。Mongo 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

最像关系型数据库的非关系型数据库。

体系结构。

在这里插入图片描述

SQL 术语MongoDB 术语解释 / 说明
databasedatabase数据库
tablecollection数据库表 / 集合
rowdocument数据记录行 / 文档
columnfield数据字段
indexindex索引
table joins表连接,MongoDB 不支持嵌入文档
primary keyprimary key主键。MongoDB 自动将 _id 字段设置为主键。


数据模型。
数据类型描述eg.
String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。{“x”: “foobar”}
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double双精度浮点值。用于存储浮点值。
Min/Max keys将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Arrays用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object用于内嵌文档。
Null用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。{“X”: ObjectId()}
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。{“x”: function() { /* … */ }}
Regular expression 正则表达式类型。用于存储正则表达式。{“x”: /foobar/i}


单机部署。

Windows。
  • 下载 zip 包。

https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-4.0.17.zip

版本。
x.y.z。
y ——> 奇数 ——> development release。eg. 4.3.6。
y ——> 偶数 ——> 稳定版。
z ——> 修正版。数字越大越好。

  • 解压。

  • 手动建立一个目录用于存放数据文件。eg. 在解压目录中\ data\db

命令行参数方式启动服务。

\bin 目录中打开命令提示符。

mongod --dbpath=..\data\db

可以将 bin 目录设置到环境变量的 path 中。

mongod ——> 启动服务。
mongo ——> 客户端连接服务。

默认端口:27017。



配置文件方式启动服务。

在解压目录下新建 config 文件夹,新建 mongod.conf 配置文件。

内容参考:https://docs.mongodb.com/manual/reference/configuration-options/。

storage:
  # The directory where the mongod instance stores its data. Default value is "\data\db" on windows.
  dbPath: G:\lyfGeek\mongodb-win32-x86_64-2008plus-ssl-4.0.17\data\db

Default Configuration File

  • On Linux, a default /etc/mongod.conf configuration file is included when using a package manager to install MongoDB.
  • On Windows, a default /bin/mongod.cfg configuration file is included during the installation.
  • On macOS, a default /usr/local/etc/mongod.conf configuration file is included when installing from MongoDB’s official Homebrew tap.
  • 启动。

mongod -f ..\config\mongod.conf

mongod --config ..\config\mongod.conf



Shell 连接。(mongo 命令)。

mongo

mongo --host=127.0.0.1 --port=27017

Microsoft Windows [版本 10.0.18362.449]
(c) 2019 Microsoft Corporation。保留所有权利。

G:\lyfGeek\mongodb-win32-x86_64-2008plus-ssl-4.0.17\bin>mongo
MongoDB shell version v4.0.17
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("8773fd2d-f16f-4eca-81ab-bd11a4f8867b") }
MongoDB server version: 4.0.17
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user
Server has startup warnings:
2020-04-10T13:58:59.329+0800 I CONTROL  [initandlisten]
2020-04-10T13:58:59.329+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-04-10T13:58:59.331+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2020-04-10T13:58:59.331+0800 I CONTROL  [initandlisten]
2020-04-10T13:58:59.331+0800 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2020-04-10T13:58:59.332+0800 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server.
2020-04-10T13:58:59.332+0800 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP
2020-04-10T13:58:59.332+0800 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2020-04-10T13:58:59.332+0800 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2020-04-10T13:58:59.333+0800 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2020-04-10T13:58:59.333+0800 I CONTROL  [initandlisten]
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).

The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.

To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---

>
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB


MongoDB Compass

The easiest way to explore and manipulate your MongoDB data
The GUI for MongoDB.

https://downloads.mongodb.com/compass/mongodb-compass-1.20.5-win32-x64.zip

绿色版,解压直接使用。



Linux。

https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.17.tgz

使用 scp 传输至 Linux 服务器。
geek@ubuntu:~$ scp mongodb-linux-x86_64-4.0.17.tgz root@192.168.142.135:/root/geek/tools_my
root@192.168.142.135's password: 
mongodb-linux-x86_64-4.0.17.tgz               100%   81MB 104.5MB/s   00:00    


配置。

https://www.mongodb.com/docs/v4.0/administration/configuration/#base-config

[root@192 mongodb-linux-x86_64-4.0.17]# mkdir -p /usr/local/mongodb
[root@192 tools_my]# tar -zxvf mongodb-linux-x86_64-4.0.17.tgz -C /usr/local/mongodb/
mongodb-linux-x86_64-4.0.17/THIRD-PARTY-NOTICES.gotools
mongodb-linux-x86_64-4.0.17/README
mongodb-linux-x86_64-4.0.17/THIRD-PARTY-NOTICES
mongodb-linux-x86_64-4.0.17/MPL-2
mongodb-linux-x86_64-4.0.17/LICENSE-Community.txt
mongodb-linux-x86_64-4.0.17/bin/mongodump
mongodb-linux-x86_64-4.0.17/bin/mongorestore
mongodb-linux-x86_64-4.0.17/bin/mongoexport
mongodb-linux-x86_64-4.0.17/bin/mongoimport
mongodb-linux-x86_64-4.0.17/bin/mongostat
mongodb-linux-x86_64-4.0.17/bin/mongotop
mongodb-linux-x86_64-4.0.17/bin/bsondump
mongodb-linux-x86_64-4.0.17/bin/mongofiles
mongodb-linux-x86_64-4.0.17/bin/mongoreplay
mongodb-linux-x86_64-4.0.17/bin/mongod
mongodb-linux-x86_64-4.0.17/bin/mongos
mongodb-linux-x86_64-4.0.17/bin/mongo
mongodb-linux-x86_64-4.0.17/bin/install_compass
[root@192 tools_my]# cd /usr/local/mongodb/
[root@192 mongodb]# ls
mongodb-linux-x86_64-4.0.17
[root@192 mongodb]# cd mongodb-linux-x86_64-4.0.17/
[root@192 mongodb-linux-x86_64-4.0.17]# ls
bin  LICENSE-Community.txt  MPL-2  README  THIRD-PARTY-NOTICES  THIRD-PARTY-NOTICES.gotools
# 存储数据目录。
[root@192 mongodb]# mkdir -p single/data/db
# 存储日志目录。
[root@192 mongodb]# mkdir -p single/log
[root@192 mongodb]# mkdir -p single/data/db
[root@192 mongodb]# mkdir -p single/log
[root@192 mongodb]# vim single/mongod.conf
systemLog:
   path: /usr/local/mongodb/single/log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /usr/local/mongodb/single/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   #pidFilePath: <string>
   #timeZoneInfo: <string>
net:
   port: 27017
   #port: <int>

   # 服务实例绑定的 IP。默认是 localhost。
   bindIp: localhost,192.168.142.161



启动。
[root@192 bin]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /usr/local/mongodb/single/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 34286
ERROR: child process failed, exited with error number 1

如果报这个错误,大概率是配置的问题。

path: /usr/local/mongodb/single/log

路径要指定到文件。

path: /usr/local/mongodb/single/log/mongod.log

[root@192 bin]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /usr/local/mongodb/single/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 34291
child process started successfully, parent exiting



关闭。

通过 mongo 客户端中的 shutdownServer 命令关闭服务。

// 客户端登录服务。这里通过 localhost 登录。如果需要远程登录,必须先登录认证。
mongo --port 27017
// 切换到 admin 库。
use admin
// 关闭服务。
db.shutdownServer()

[root@192 bin]# ./mongo
MongoDB shell version v4.0.17
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("7f7f569d-4fd7-4f75-9b99-85d7162395e3") }
MongoDB server version: 4.0.17
Server has startup warnings: 
2020-04-06T22:07:20.349+0800 I CONTROL  [initandlisten] 
2020-04-06T22:07:20.349+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-04-06T22:07:20.349+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2020-04-06T22:07:20.349+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2020-04-06T22:07:20.349+0800 I CONTROL  [initandlisten] 
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] 
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] 
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2020-04-06T22:07:20.350+0800 I CONTROL  [initandlisten] 
> 



基本常用命令。

数据库操作。
show databases; or show dbs;
> show databases
admin   0.000GB
config  0.000GB
local   0.000GB
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB


use 数据库名。

如果数据库不存在则自动创建。

数据库名:

  • 不能是空字符串(“”)。
  • 不得有 ``(空格)、.$/\、和 \0(空字符)。
  • 应全部小写。
  • 最多 64 字节。

数据库保留名。

  • admin:从权限角度来看,这是 “root” 数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行。eg. 列出所有数据库 or 关闭服务器。
  • local:这个数据库永远不会被复制,可以用来存储限于本地单台服务器的任意集合。
  • config:当 Mongo 用于分片设置时,config 数据库在内部使用,用于保存分片的相关信息。
> use articledb
switched to db articledb
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

在这里插入图片描述



数据库的删除。

db.dropDatabase()



集合操作。

集合,类似关系型数据库中的表。

可以显式的创建,也可以隐式的创建。

集合的显式创建。(了解)。

db.createColeection(-要创建的集合名称-)

  • 查看当前库中的集合。

show collections

show tables



删除。
> db.createCollection("my")
{ "ok" : 1 }
> show tables
my
> show collections
my

> db.my.drop()
true



文档基本 CRUD。

文档的数据结构和 JSON 基本一样。

所有存储在集合中的数据都是 BSON 格式。

文档的插入。
  • 单个文档的插入。

insert() 或 save()。

db.collection.insert(
	<document or array of document>
	{
		writeConcernL <document>,
		ordered: <boolean>
	}	
)
ParameterTypeDescription
documentdocument or array要插入到集合中的文档或文档数组。(bson 格式)。
writeConcerndocumentOptional. A document expressing the write concern. Omit to use the default write concern. Do not explicitly set the write concern for the operation if run in a transaction. To use write concern with transactions, see Transactions and Write Concern.
orderedbooleanOptional. A boolean specifying whether the mongod instance should perform an ordered or unordered operation execution. Defaults to true.可选的。一个布尔值,指定 mongod 实例应执行有序操作还是无序操作执行。 版本 2.6- 默认为 true。如果为真,按顺序插入数组中的文档,如果文档中出现错误,MongoDB 将返回而不处理数组中的其余文档。如果为假,无序插入,如果文档中出现错误,MongoDB 将继续处理数组中的主文档。See Execution of Operations

db.comment.insert({“articleId”: “100000”, “content”: “今天天气好”, “userId”: “1001”, “nickName”: “Geek”, “createdTime”: new Date(), “likeNum”: NumberInt(10), “state”: null})

WriteResult({ “nInserted” : 1 })

  • comment 集合如果不存在,会隐式创建。
  • mongo 中的数字,默认情况下是 double 类型。如果要存整型,必须使用函数 NumberInt(整型数字)。
  • 插入当前日期:new Date()。
  • 插入的数据没有指定 _id,会自动生成主键值。
  • 如果某字段没值,可以赋值为 null,或不写该字段。
  • 批量插入。
db.collection.insertMany (
	[<document 1>, <document 2>, ...]
	{
		writeConcernL <document>,
		ordered: <boolean>
	}
)
> db.comment.insertMany([
... {"_id": "1", "articleId": "1000001", "content": "我们不应该把时间浪费在手机上,健康很重要,一杯温水幸福你我他。", "userId": "1002", "nickName": "相忘于江湖。", "createdTime": new Date("2020-04-13T17:29:16.521Z"), "likeNum": NumberInt(166), "state": "1"},
... {"_id": "2", "articleId": "1000001", "content": "我夏天空腹喝凉开水,冬天喝温开水。", "userId": "1002", "nickName": "相忘于江湖。", "createdTime": new Date(), "likeNum": NumberInt(200), "state": "1"},
... {"_id": "3", "articleId": "1000001", "content": "我一直喝凉开水,冬天夏天都一样。", "userId": "1002", "nickName": "Geek", "createdTime": new Date(), "likeNum": NumberInt(300), "state": "1"},
... {"_id": "4", "articleId": "1000001", "content": "专家说空腹不能吃饭,影响健康。。", "userId": "1002", "nickName": " 相忘于江湖。", "createdTime": new Date("2020-04-13T17:29:16.521Z"), "likeNum": NumberInt(400), "state": "1"},
... {"_id": "5", "articleId": "1000001", "content": "研究表明,刚烧开的水千万不能喝,因为烫。", "userId": "1002", "nickName": "Geek。", "createdTime": new Date("2020-04-13T17:29:16.521Z"), "likeNum": NumberInt(56), "state": "1"}
... ]);
{
        "acknowledged" : true,
        "insertedIds" : [
                "1",
                "2",
                "3",
                "4",
                "5"
        ]
}
>


文档插入使用 try … catch …
try {
db.comment.insertMany([
... {"_id": "1", "articleId": "1000001", "content": "我们不应该把时间浪费在手机上,健康很重要,一杯温水幸福你我他。", "userId": "1002", "nickName": "相忘于江湖。", "createdTime": new Date("2020-04-13T17:29:16.521Z"), "likeNum": NumberInt(166), "state": "1"},
... {"_id": "2", "articleId": "1000001", "content": "我夏天空腹喝凉开水,冬天喝温开水。", "userId": "1002", "nickName": "相忘于江湖。", "createdTime": new Date(), "likeNum": NumberInt(200), "state": "1"},
... {"_id": "3", "articleId": "1000001", "content": "我一直喝凉开水,冬天夏天都一样。", "userId": "1002", "nickName": "Geek", "createdTime": new Date(), "likeNum": NumberInt(300), "state": "1"},
... {"_id": "4", "articleId": "1000001", "content": "专家说空腹不能吃饭,影响健康。。", "userId": "1002", "nickName": " 相忘于江湖。", "createdTime": new Date("2020-04-13T17:29:16.521Z"), "likeNum": NumberInt(400), "state": "1"},
... {"_id": "5", "articleId": "1000001", "content": "研究表明,刚烧开的水千万不能喝,因为烫。", "userId": "1002", "nickName": "Geek。", "createdTime": new Date("2020-04-13T17:29:16.521Z"), "likeNum": NumberInt(56), "state": "1"}
... ]);
} catch (e) {
	print(e);
}
BulkWriteError({
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 11000,
                        "errmsg" : "E11000 duplicate key error collection: test.comment index: _id_ dup key: { : \"1\" }",
                        "op" : {
                                "_id" : "1",
                                "articleId" : "1000001",
                                "content" : "我们不应该把时间浪费在手机上,健康很重要,一杯温水幸福你我他。",
                                "userId" : "1002",
                                "nickName" : "相忘于江湖。",
                                "createdTime" : ISODate("2020-04-13T17:29:16.521Z"),
                                "likeNum" : NumberInt(166),
                                "state" : "1"
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 0,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})



文档的基本查询。
  • 查询所有。

如果我们要查询集合的所有文档。

db.comment.find()

db.comment.find({})

> db.comment.find({articleId: "1000001"})
> db.comment.findOne({articleId: "1000001"})


投影查询。

默认显示 _id

1 ——> 显示。
0 ——> 不显示。

> db.comment.find({articleId: "1000001"}, {articleId: 1})
{ "_id" : "1", "articleId" : "1000001" }
{ "_id" : "2", "articleId" : "1000001" }
{ "_id" : "3", "articleId" : "1000001" }
{ "_id" : "4", "articleId" : "1000001" }
{ "_id" : "5", "articleId" : "1000001" }
> db.comment.find({articleId: "1000001"}, {articleId: 1, _id: 0})
{ "articleId" : "1000001" }
{ "articleId" : "1000001" }
{ "articleId" : "1000001" }
{ "articleId" : "1000001" }
{ "articleId" : "1000001" }


文档的更新。
db.collection.update(query, update, options)
// 或
db.collection.update(
	<query>,
	<update>,
	{
		upsert: <boolean>,
		multi: <boolean>,
		writeConcern: <document>,
		collation: <document>,
		arrayFilters: [ <filterdocument 1>, ... ], 
		hint: <document | string>  // Available starting in MongoDB 4.2
	}
)


- 覆盖修改。
> db.comment.update({_id: "1"}, {likeNum: NumberInt(1001)})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

执行后,这条文档除了 likeNum 字段,其他字段都不见了。

{ "_id" : "1", "likeNum" : 1001 }


- 局部修改。

修改器 $set。

db.comment.update({_id: "2"}, {$set: {likeNum: NumberInt(889)}})


- 批量修改。

如果有相同条件的,MongoDB 默认只修改第一条数据。

修改所有符合条件的数据。{multi: true}

db.comment.update({userId: “1003”}, {$set:{nickName: “Geek”}}, {multi: true})



- 列值的增长~$inc。

db.comment.update({_id: “3”}, {$inc: {likeNum: NumberInt(1)}})
WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })



删除文档。

db.集合名称.remove(条件)

db.comment.remove({_id: “1”})

  • 删除全部。慎用。

db.comment.remove({})



文档分页查询。
  • 统计查询。

db.collection.count(query, options)

参数。

ParameterTypeDescription
querydocument查询选择条件。
optionsdocument可选。用于修改计数的额外选项。

eg.

  • 统计所有记录数。

db.comment.count()
5

  • 按条件统计。

db.comment.count({userId: “1002”})
4



  • 分页列表查询。

db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

skip()。——> 参数表示跳过前 n 个数据不要。默认为 0。

db.comment.find().limit(3).skip(2)

分页查询。

每页 2 个。第二页开始,跳过前两条数据,接着显示第 3 和第 4 条数据。

// 第一页。
db.comment.find().skip(0).limit(2)
// 第二页。
db.comment.find().skip(2).limit(2)
// 第三页。
db.comment.find().skip(4).limit(2)



  • 排序查询~sort()。

sort() 参数。

1 ——> 升序。
-1 ——> 降序。

db.comment.find().sort({userId: -1, likeNum: 1})



文档的更多查询。
正则查询。

db.collection.find({field: /正则表达式/})

db.comment.find({content: /开水/})
db.comment.find({content: /^专家/})



比较查询。

< ——> $gt
<= ——> $gte
> ——> $lt
>= ——> $lte
!= ——> $ne



包含查询~$in:


条件连接查询。

$and: [{}, {}, {}]
$or: [{}, {}, {}]



索引~index。

在这里插入图片描述
MongoDB 索引~B-Tree。

MySQL 索引~B+Tree。

单字段索引~Single Field Index。

MongoDB 支持在文档的单个字段上创建用户定义的升序 / 降序索引,称为单字段索引~Single Field Index。

对于单个字段的索引的排序操作,索引键的排序顺序(升序或降序)并不重要,因为 MongoDB 可以在任何方向上遍历索引。



复合索引~Compound Index。

MongoDB 还支持多个字段的用户定义索引,即复合索引~Compound Index。

复合索引中列出的字段顺序具有重要意义。eg. 如果复合索引由 {userId: 1, score: -1} 组成,则索引首先按 userId 正序排序,然后在每个 userId 的值内,再按 score 倒序排序。



其他索引。
地理空间索引~Geospatial Index。

为了支持对地理空间坐标数据的有效查询,MongoDB 提供了两种特殊的索引。

  • 返回结果时使用平面几何的二维索引。
  • 返回结果时使用球面几何的二维球面索引。


文本索引~Text Indexes。

MongoDB 图加工了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(eg. “the”,“a”,“or”),而将集合中的词作为词干,只存储词根。



哈希索引~Hashed Indexes。

为了支持基于散列的分片,MongoDB 提供了散列索引类型,ta 对字段的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。



索引的管理操作。
索引的查看。

db.collection.getIndexes()

> db.comment.getIndexes()
[
        {
                "v" : 2,  // 索引引擎版本号。
                "key" : {  // 索引字段。
                        "_id" : 1  // 1 升序。
                },
                "name" : "_id_", // 索引名称。(一般是 字段 - “_”)。
                "ns" : "test.comment"  // namespace。
        }
]
>


索引的创建。

db.collection.createIndex(keys, options)

ParameterTypeDescription
keysdocument包含字段和值对的文档,其中字段是索引键,值描述该字段的索引类型。对于字段上的升序索引,请指定值 1;对于降序索引,请指定值 -1。
optionsdocument可选。包含一组控制索引创建的选项的文档。
> db.comment.createIndex({userId: 1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.comment.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.comment"
        },
        {
                "v" : 2,
                "key" : {
                        "userId" : 1
                },
                "name" : "userId_1",
                "ns" : "test.comment"
        }
]
> db.comment.createIndex({userId: 1, nickName: -1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}
> db.comment.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.comment"
        },
        {
                "v" : 2,
                "key" : {
                        "userId" : 1
                },
                "name" : "userId_1",
                "ns" : "test.comment"
        },
        {
                "v" : 2,
                "key" : {
                        "userId" : 1,
                        "nickName" : -1
                },
                "name" : "userId_1_nickName_-1",
                "ns" : "test.comment"
        }
]
>


索引的移除。
  • 指定索引。

db.collection.dropIndex(index)

参数~index。

String or document。

指定要删除的索引。可以通过索引名称或索引规范文档指定索引。若要删除文本索引,请指定索引名称。

eg.

> db.comment.dropIndex({userId: 1})
{ "nIndexesWas" : 3, "ok" : 1 }
  • 全部索引。

db.collection.dropIndexes()

// _id 字段的索引是无法删除的,只能删除非 _id 字段的索引。



索引的使用。
执行计划。

分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plain)来查看查询的情况,eg. 查询耗费时间、是否基于索引查询等。

db.collection.find(query, options).explain(options)

> db.comment.find({userId: 1002}).explain()
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "test.comment",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "userId" : {
                                "$eq" : 1002
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",  // 索引扫描。
                                "keyPattern" : {
                                        "userId" : 1,
                                        "nickName" : -1
                                },
                                "indexName" : "userId_1_nickName_-1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "userId" : [ ],
                                        "nickName" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "userId" : [
                                                "[1002.0, 1002.0]"
                                        ],
                                        "nickName" : [
                                                "[MaxKey, MinKey]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "192.168.142.135",
                "port" : 27017,
                "version" : "4.0.17",
                "gitVersion" : "0bc918c73390f6e4d6349660e4cd233f5900b69a"
        },
        "ok" : 1
}
>


涵盖的查询~Covered Queries。

当查询条件和查询的投影仅包含索引字段时,MongoDB 直接从索引返回结果,而不扫描任何文档或将文档带入内存。这些覆盖的查询可以非常有效,

https://docs.mongodb.com/manual/core/query-optimization/index.html#covered-query

> db.comment.find({userId: "1002"}, {userId: 1, _id: 0})
{ "userId" : "1002" }
{ "userId" : "1002" }
{ "userId" : "1002" }
{ "userId" : "1002" }


文章评论~mongodb-driver。

mongodb-driver 是 mongo 官方推出的 Java 连接 MongoDB 的驱动包。

http://mongodb.github.io/mongo-java-driver/

<dependencies>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver</artifactId>
        <version>3.11.2</version>
    </dependency>
</dependencies>


文章评论~SpringDataMongoDB。

  • SpringBoot 整合。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.geek</groupId>
    <artifactId>mongodb_article</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

  • application.yml
spring:
  data:
    mongodb:
      host: 192.168.142.135
      database: articledb
      port: 27017
      # 也可以使用 url 连接。
#      uri: mongodb://192.168.142.135:27017/articledb
  • 启动类。
package com.geek.article;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author geek
 */
@SpringBootApplication
public class ArticleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ArticleApplication.class, args);
    }

}

2020-04-15 17:29:39.872  INFO 14064 --- [8.142.135:27017] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:1, serverValue:901}] to 192.168.142.135:27017
  • pojo。
package com.geek.article.po;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * 文章评论实体类。
 * // 把 Java 类声明为 mongodb 的文档,可以通过 collection 参数指定这个类对应的文档。
 * // 如果没有 @Document,该 bean save 到 mongo 的 comment collection。
 * // 如果添加 @Document,则 save 到 comment collection。
 * // collection 可以省略。默认使用类名小写映射集合。
 * // @CompoundIndex(def = "{'userId': 1, 'nickName': -1}")// 复合索引。// 最好用 Mongo 命令行建立。
 *
 * @author geek
 */
@Document(collection = "comment")
@Data
public class Comment implements Serializable {

    /**
     * 主键标识。该属性的值会自动对应 mongodb 的主键字段 “_id”,如果该属性名就叫 “id”,则该注解可以省略。
     */
    @Id
    private String id;
    /**
     * 吐槽内容。
     * // @Field("content")
     * 该属性对应 MongoDB 的字段名。如果一致,则可以不写。
     */
    @Field("content")
    private String content;
    /**
     * 发布日期。
     */
    private Date publishTime;
    /**
     * 发布人 id。
     * // @Indexed
     * 单字段索引。
     */
    @Indexed
    private String userId;
    /**
     * 昵称。
     */
    private String nickName;
    /**
     * 评论的日期时间。
     */
    private LocalDateTime createdTime;
    /**
     * 点赞数。
     */
    private Integer likeNum;
    /**
     * 回复数。
     */
    private Integer replyNum;
    /**
     * 状态。
     */
    private String state;
    /**
     * 上级 id。
     */
    private String parentId;
    /**
     * 文章 id。
     */
    private String articleId;

}

  • Repository。
package com.geek.article.dao;

import com.geek.article.po.Comment;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface CommentRepository extends MongoRepository<Comment, String> {
}

  • service。
package com.geek.article.service;

import com.geek.article.dao.CommentRepository;
import com.geek.article.po.Comment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author geek
 */
@Service
public class CommentService {

    /**
     * 动态代理生成 SimpleMongoRepository 对象。
     */
    @Autowired
    private CommentRepository commentRepository;

    /**
     * 注入 MongoTemplate。
     */
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 点赞数 + 1。
     *
     * @param id
     */
    public void updateCommentLikeNum(String id) {
        // 查询对象。
        Query query = Query.query(Criteria.where("_id").is(id));
        // 更新对象。
        Update update = new Update();
        // 局部更新。——> $set。
//        update.set(key, value)
        // 递增 $inc。
        update.inc("likeNum", 1);

//        this.mongoTemplate.updateFirst(query, update, "comment");。
        this.mongoTemplate.updateFirst(query, update, Comment.class);
    }

    // criterion
    //n. (评判或作决定的)标准,准则,原则

    /**
     * 点赞。效率低。包含查询。
     *
     * @param id
     */
    public void updateCommentThumbUpToIncrementingOld(String id) {
        Comment comment = this.commentRepository.findById(id);
        comment.setLikeNum(comment.getLikeNum() + 1);
        this.commentRepository.save(comment);
    }

    /**
     * 分页查询。
     *
     * @param parentId
     * @param page
     * @param size
     * @return
     */
    public Page<Comment> findCommentByParentId(String parentId, int page, int size) {
        PageRequest pageRequest = new PageRequest(page - 1, size);
        Page<Comment> commentPage = this.commentRepository.findByParentId(parentId, pageRequest);
        System.out.println(commentPage.getTotalElements());
        return commentPage;
    }

    /**
     * 保存一个评论。
     *
     * @param comment
     */
    public void saveComment(Comment comment) {
        // 如果需要自定义主键,可以在这里指定。如果不指定,MongoDB 自动自成。
        // 设置一些值。
        // 调用 dao。
        this.commentRepository.save(comment);
    }

    /**
     * 更新评论。
     *
     * @param comment
     */
    public void updateComment(Comment comment) {
        this.commentRepository.save(comment);
    }

    /**
     * 删除评论。
     *
     * @param commentId
     */
    public void deleteCommentById(String commentId) {
        this.commentRepository.delete(commentId);
    }

    /**
     * 查询所有。
     *
     * @return
     */
    public List<Comment> findCommentList() {
        return this.commentRepository.findAll();
    }

    /**
     * 根据 id 查询评论。
     *
     * @param commentId
     * @return
     */
    public Comment findCommentById(String commentId) {
        return this.commentRepository.findOne(commentId);
    }

}



根据上级 id 查询文章评论的分页列表。
  • CommentRepository 新增方法定义。
package com.geek.article.dao;

import com.geek.article.po.Comment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface CommentRepository extends MongoRepository<Comment, String> {

    // 根据父 id 查询子评论的分页列表。
    Page<Comment> findByParentId(String parentId, Pageable pageable);
}

  • CommentService 新增方法定义。
    public Page<Comment> findCommentByParentId(String parentId, int page, int size) {
        PageRequest pageRequest = new PageRequest(page - 1, size);
        Page<Comment> commentPage = commentRepository.findByParentId(parentId, pageRequest);
        System.out.println(commentPage.getTotalElements());
        return commentPage;
    }
  • 测试方法。
    @Test
    public void findCommentByParentId() {

        Page<Comment> page = commentService.findCommentByParentId("3", 1, 2);
        System.out.println(page.getTotalElements());
        System.out.println(page.getTotalPages());
        System.out.println(page.getContent());
    }


MongoTemplate 实现评论点赞。

    /**
     * 点赞。效率低。包含查询。
     *
     * @param id
     */
    public void updateCommentThumbupToIncrementiongOld(String id) {
        Comment comment = commentRepository.findById(id);
        comment.setLikeNum(comment.getLikeNum() - 1);
        commentRepository.save(comment);
    }

  • 使用 MongoTemplate。
    // 注入 MongoTemplate。
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 点赞数 - 1。
     *
     * @param id
     */
    public void updateCommentLikeNum(String id) {
        // 查询对象。
        Query query = Query.query(Criteria.where("_id").is(id));
        // 更新对象。
        Update update = new Update();
        // 局部更新。——> $set。
//        update.set(key, value)
        // 递增 $inc。
        update.inc("likeNum", 1);
//        update.inc("likeNum", 1);

//        mongoTemplate.updateFirst(query, update, "comment");
        mongoTemplate.updateFirst(query, update, Comment.class);
    }

    // criterion
    //n. (评判或作决定的)标准,准则,原则

  • 测试类。
    @Test
    public void updateCommentLikeNum() {
        commentService.updateCommentLikeNum("1");
    }


MongoDB 集群和安全。

副本集~Replica Sets。

A replica set in MongoDB is a group of mongod processes that maintain the same data set. Replica sets provide redundancy and high availability, and are the basis for all production deployments. This section introduces replication in MongoDB as well as the components and architecture of replica sets. The section also provides tutorials for common tasks related to replica sets.

MongoDB 中的副本集是一组维护相同数据集的 mongod 进程。 副本集提供冗余和高可用性,并且是所有生产部署的基础。

副本集群类似于有自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本。并且当主库宕掉时在不需要用户干预的情况下自动切换其他备份服务器做主库。而且还能利用副本服务器做只读服务器,实现读写分离,提高负载。



主从复制的副本集区别。

副本集没有固定的主节点。

副本集。

整个集群会选出一个“”主节点,当其挂掉后,又在剩下的从节点中选中其他节点为“主节点”。副本集总有一个活跃点(主 primary)和一个或多个备份节点(从 secondary)。



副本集的两种类型、三个角色。
  • 两种类型。
  • 主节点(Primary)类型。
    数据操作的主要连接点,可读写。
  • 次要(辅助、从)(Secondary)类型。
    数据冗余备份节点,可以读或选举。
  • 三种角色。
  • 主要成员(Primary)。
    主要接受所有写操作。就是主节点。
  • 副本成员(Replicate)。
    从主机诶单通过复制操作以维护相同的数据集,即备份数据,不可写数据,但可以读操作(需要配置)。是默认的一种节点类型。
  • 仲裁者(Arbiter)。
    不保留任何数据的副本,只具有投票选举作用。当然也可以将仲裁服务器维护为副本集的一部分,即副本成员也可以是仲裁者。也是 一种从节点类型。


副本集的创建。

在这里插入图片描述
一主一副一仲裁。

  • 建立存放数据和日志的目录。
[root@192 ~]# mkdir -p /mongodb/replica_sets/myrs_27018/log
[root@192 ~]# mkdir -p /mongodb/replica_sets/myrs_27018/data/db

  • 新建或修改配置文件。

[root@192 ~]# vim /mongodb/replica_sets/myrs_27017/mongod.conf

systemLog:
   path: /mongodb/replica_sets/myrs_27017/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/replica_sets/myrs_27017/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/replica_sets/myrs_27017/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27017
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myrs
  • 启动节点服务。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 43791
child process started successfully, parent exiting



  • 副本。

  • 建立存放数据和日志的目录。

[root@192 ~]# mkdir -p /mongodb/replica_sets/myrs_27017/log
[root@192 ~]# mkdir -p /mongodb/replica_sets/myrs_27017/data/db

  • 新建或修改配置文件。

[root@192 ~]# vim /mongodb/replica_sets/myrs_27018/mongod.conf

systemLog:
   path: /mongodb/replica_sets/myrs_27018/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/replica_sets/myrs_27018/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/replica_sets/myrs_27018/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27018
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myrs
  • 启动节点服务。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 43863
child process started successfully, parent exiting



  • 仲裁节点。

  • 建立存放数据和日志的目录。

[root@192 ~]# mkdir -p /mongodb/replica_sets/myrs_27019/log
[root@192 ~]# mkdir -p /mongodb/replica_sets/myrs_27019/data/db

  • 新建或修改配置文件。

[root@192 ~]# vim /mongodb/replica_sets/myrs_27019/mongod.conf

systemLog:
   path: /mongodb/replica_sets/myrs_27019/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/replica_sets/myrs_27019/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/replica_sets/myrs_27019/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27019
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myrs
  • 启动节点服务。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 43904
child process started successfully, parent exiting

[root@192 ~]# ps -ef | grep mongo
root      43791      1  0 18:30 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf
root      43863      1  0 18:37 ?        00:00:01 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf
root      43904      1  1 18:41 ?        00:00:00 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf
root      43936  43579  0 18:41 pts/0    00:00:00 grep --color=auto mongo



初始化配置副本集和主节点。

使用客户端命令连接任意一个节点。尽量连接主节点(27017)。

[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host=192.168.142.135 --port=27017

show dbs 不能使用。

要初始化副本集。

> show dbs
2020-04-08T18:46:39.292+0800 E QUERY    [js] Error: listDatabases failed:{
	"operationTime" : Timestamp(0, 0),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(0, 0),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:139:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1

> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.142.135:27017",
	"ok" : 1,
	"operationTime" : Timestamp(1586342952, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586342952, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myrs:SECONDARY> (再按一下回车)。
myrs:PRIMARY> 
myrs:PRIMARY> 

配置。

myrs:PRIMARY> rs.conf()
{
	"_id" : "myrs",
	"version" : 1,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.142.135:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatIntervalMillis" : 2000,
		"heartbeatTimeoutSecs" : 10,
		"electionTimeoutMillis" : 10000,
		"catchUpTimeoutMillis" : -1,
		"catchUpTakeoverDelayMillis" : 30000,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		},
		"replicaSetId" : ObjectId("5e8dac28efd72b6247c35400")
	}
}



添加副本从节点。

rs.add(host, arbiterOnly)

arbiterOnly 可选。仅在 <host> 为字符串时适用。如果为 true,则添加的主机是仲裁者。

myrs:PRIMARY> rs.add("192.168.142.135:27018")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586343360, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586343360, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}



添加仲裁从节点。
myrs:PRIMARY> rs.addArb("192.168.142.135:27019")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586343442, 2),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586343442, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

查看状态。
myrs:PRIMARY> rs.status()
{
	"set" : "myrs",
	"date" : ISODate("2020-04-08T10:58:49.099Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncingTo" : "",
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1586343522, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1586343522, 1),
			"t" : NumberLong(1)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1586343522, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1586343522, 1),
			"t" : NumberLong(1)
		}
	},
	"lastStableCheckpointTimestamp" : Timestamp(1586343482, 1),
	"electionCandidateMetrics" : {
		"lastElectionReason" : "electionTimeout",
		"lastElectionDate" : ISODate("2020-04-08T10:49:12.300Z"),
		"electionTerm" : NumberLong(1),
		"lastCommittedOpTimeAtElection" : {
			"ts" : Timestamp(0, 0),
			"t" : NumberLong(-1)
		},
		"lastSeenOpTimeAtElection" : {
			"ts" : Timestamp(1586342952, 1),
			"t" : NumberLong(-1)
		},
		"numVotesNeeded" : 1,
		"priorityAtElection" : 1,
		"electionTimeoutMillis" : NumberLong(10000),
		"newTermStartDate" : ISODate("2020-04-08T10:49:12.301Z"),
		"wMajorityWriteAvailabilityDate" : ISODate("2020-04-08T10:49:12.311Z")
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.142.135:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 1684,
			"optime" : {
				"ts" : Timestamp(1586343522, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-04-08T10:58:42Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1586342952, 2),
			"electionDate" : ISODate("2020-04-08T10:49:12Z"),
			"configVersion" : 3,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 1,
			"name" : "192.168.142.135:27018",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 169,
			"optime" : {
				"ts" : Timestamp(1586343522, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1586343522, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-04-08T10:58:42Z"),
			"optimeDurableDate" : ISODate("2020-04-08T10:58:42Z"),
			"lastHeartbeat" : ISODate("2020-04-08T10:58:49.010Z"),
			"lastHeartbeatRecv" : ISODate("2020-04-08T10:58:49.046Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "192.168.142.135:27017",
			"syncSourceHost" : "192.168.142.135:27017",
			"syncSourceId" : 0,
			"infoMessage" : "",
			"configVersion" : 3
		},
		{
			"_id" : 2,
			"name" : "192.168.142.135:27019",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 86,
			"lastHeartbeat" : ISODate("2020-04-08T10:58:49.010Z"),
			"lastHeartbeatRecv" : ISODate("2020-04-08T10:58:49.009Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 3
		}
	],
	"ok" : 1,
	"operationTime" : Timestamp(1586343522, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586343522, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myrs:PRIMARY> 

副本集数据读写操作。
myrs:PRIMARY> db.comment.insert({"articleId": "100000", "content": "今天天气好", "userId": "1001", "nickName": "Geek", "createdTime": new Date(), "likeNum": NumberInt(10), "state": null});
WriteResult({ "nInserted" : 1 })

myrs:PRIMARY> db.comment.find()
{ "_id" : ObjectId("5e8dafb94baa24ce385776da"), "articleId" : "100000", "content" : "今天天气好", "userId" : "1001", "nickName" : "Geek", "createdTime" : ISODate("2020-04-08T11:04:25.948Z"), "likeNum" : 10, "state" : null }
  • 登录从节点 27018。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27018

“errmsg” : “not master and slaveOk=false”,

myrs:SECONDARY> show dbs;
2020-04-08T19:09:23.653+0800 E QUERY    [js] Error: listDatabases failed:{
	"operationTime" : Timestamp(1586344162, 1),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586344162, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:139:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1

  • 确认自己为从节点。
myrs:SECONDARY> rs.slaveOk()
myrs:SECONDARY> show dbs;
admin      0.000GB
articledb  0.000GB
config     0.000GB
local      0.000GB

rs.slaveOk(false)



仲裁者节点副本集。

[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27019

myrs:ARBITER> show dbs;
2020-04-08T19:14:37.884+0800 E QUERY    [js] Error: listDatabases failed:{
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:139:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1
myrs:ARBITER> 

myrs:ARBITER> rs.slaveOk()
myrs:ARBITER> show dbs;
local  0.000GB



主节点的选举原则。

MongoDB 在副本集中,会自动进行主节点的选举,主节点选举的触发条件。

  • 主节点故障。
  • 主节点网络不可达(默认心跳信息为 10 秒)。
  • 人工干预(rs.stepDown(600))。
  • 票数最高,且获得了“大多数”成员的投票支持的节点获胜。
    “大多数” ——> 假设赋值集中投票成员数量为 N, 则大多数为 N / 2 - 1。eg. 3 个成员投票,则大多数的值为 2。当复制集中存活成员数量不足大多数时,整个复制集将无法选举出 Primary,复制集将无法提供写服务,处于只读状态。
  • 若票数相同,且都获得了“大多数”成员的投票支持的,数据新的节点获胜。
    数据的新旧是通过操作日志 oplog 来对比的。

在获得票数的时候,优先级(priority)参数影响重大。

可以通过设置优先级(priority)来设置额外票数。优先级即权重,取值为 0 ~ 1000,相当于课额外增加 0 ~ 1000 的票数。优先级的值越大,就越可能获得多数成员的投票数(votes)。指定较高的值可使成员更有资格成为主要成员,更低的值可使成员更不符合条件。

默认情况下,优先级的值是 1。

myrs:ARBITER> rs.conf();
{
	"_id" : "myrs",
	"version" : 3,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.142.135:27017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "192.168.142.135:27018",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "192.168.142.135:27019",
			"arbiterOnly" : true,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		}
	],
	"settings" : {
		"chainingAllowed" : true,
		"heartbeatIntervalMillis" : 2000,
		"heartbeatTimeoutSecs" : 10,
		"electionTimeoutMillis" : 10000,
		"catchUpTimeoutMillis" : -1,
		"catchUpTakeoverDelayMillis" : 30000,
		"getLastErrorModes" : {
			
		},
		"getLastErrorDefaults" : {
			"w" : 1,
			"wtimeout" : 0
		},
		"replicaSetId" : ObjectId("5e8dac28efd72b6247c35400")
	}
}
myrs:ARBITER> 



故障测试。
  • 副本节点宕机,再次启动,会自动同步数据。

  • 主节点宕机 27017。

[root@192 ~]# ps -ef | grep mongo
root      43791      1  0 18:30 ?        00:00:43 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27017/mongod.conf
root      43863      1  0 18:37 ?        00:00:43 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27018/mongod.conf
root      43904      1  0 18:41 ?        00:00:31 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/replica_sets/myrs_27019/mongod.conf
root      43945  43579  0 18:46 pts/0    00:00:00 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host=192.168.142.135 --port=27017
root      44185  44165  0 19:08 pts/1    00:00:00 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27018
root      45024  44231  0 22:00 pts/2    00:00:00 grep --color=auto mongo
[root@192 ~]# kill -9 43791

副本节点 27018 变为主节点。

myrs:SECONDARY> 
myrs:PRIMARY> 
  • 主节点和仲裁节点都挂。

先关掉仲裁节点 27019,再关掉主节点 27018。

登陆 27017,仍然是从节点,副本集中没有主节点。此时副本集是只读状态,无法写入。

因为 27017 的票数是 1,没有大于等于 2。

如果只加入 27019 仲裁节点成员,则主节点一定是 27017。仲裁成员不参与选举,但参与投票。
如果只加入 27018 节点,发生选举。因为 27017 和 27018 都是两票,按照谁数据新谁当主节点。

  • 仲裁节点和从节点故障。

先关掉仲裁节点 27019,再关掉现在的主节点 27018。

10 秒后,27017 主节点自动降级为副本节点。(服务降级)。

副本集不可写数据。已经故障了。



Compass 连接副本集。

如果使用云服务器需要修改配置中的主节点 ip。

var config = rs.config();
config.members[0].host = "192.168.142.135:27017";
rs.reconfig(config);

Compass 填写 Replica Set Name。

在这里插入图片描述
在这里插入图片描述



SpringDataMongoDB 连接副本集。

spring:
data:
mongodb:
uri: mongodb://192.168.142.135:27017, 192.168.142.135:27018, 192.168.142.135:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs



分片集群~Sharded Cluster。

分片(sharding)是一种跨多台机器分布数据的方法,MongoDB 使用分片来支持具有非常大的数据集和高吞吐量操作的部署。
换句话说:分片(sharding)是指将数据拆分,将其分散在不同的机器上的过程。有时也用分区(partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存更多的数据,处理更多的负载。
貝有大型数据集或高吞吐量应用程序的数库系统可以挑战单个服务器的容量。例如,高查询率会耗尽服务器的 CPU 容量。工作集大小大于系统的 RAM 会强调磁盘驱动的 I / O 容量。

有两种解决系统增长的方法:垂直扩展和水平扩展。

垂直扩展以为着增加单个服务器的容量。eg. 使用更强大的 CPU,添加更多 RAM 或增加存储空间量。可用技术的局限性可能会限制单个机器对于给定工作负载而言足够强大。此外,基于云的提供商基于可用的硬件配置具有硬性上限。结果,垂直缩放有实际的最大值。
 ~
水平扩展意味着划分系统数据集并加载多个服务器,添加其他服务器以根据需要增加容量。虽然单个机器的总体速度或容量可能不高,但每台机器处理整个工作负载的子集,可能会提供比单个高速大容量服务器更高的效率。扩展部署容量只需要添加额外的服务器,这可能比单个机器的高端硬件的总体成本更低。权衡使基础架构和部署维护的复杂性增加。
~
MongoDB 支持通过分片进行水平扩展。



分片集群包含的组件。
  • 分片(存储):每个分片包含分片数据的子集。每个分片都可以部署为副本集。
  • mongos(路由):mongos 充当查询路由器,在客户端应用程序的分片集群之间提供接口。
  • config servers(“调度”的配置):配置服务器存储集群的元数据和配置设置。从 MongoDB 3.4 开始,必须将配置服务器部署为副本集(CSRS)。

在这里插入图片描述



分片集群架构。

在这里插入图片描述



分片(存储)节点副本集第一套。
[root@192 ~]# 
mkdir -p /mongodb/shard_cluster/myshardrs01_27018/log \
& mkdir -p /mongodb/shard_cluster/myshardrs01_27018/data/db \
& mkdir -p /mongodb/shard_cluster/myshardrs01_27118/log \
& mkdir -p /mongodb/shard_cluster/myshardrs01_27118/data/db \
& mkdir -p /mongodb/shard_cluster/myshardrs01_27218/log \
& mkdir -p /mongodb/shard_cluster/myshardrs01_27218/data/db

[root@192 ~]# vim /mongodb/shard_cluster/myshardrs01_27018/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myshardrs01_27018/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myshardrs01_27018/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myshardrs01_27018/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27018
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myshardrs01
sharding:
   # 分片角色。
   clusterRole: shardsvr
ValueDescription
configsvrStart this instance as a config server. The instance starts on port 27019 by default.
shardsvrStart this instance as a shard. The instance starts on port 27018 by default.
[root@192 ~]# vim /mongodb/shard_cluster/myshardrs01_27118/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myshardrs01_27118/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myshardrs01_27118/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myshardrs01_27118/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27118
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myshardrs01
sharding:
   # 分片角色。
   clusterRole: shardsvr
[root@192 ~]# vim /mongodb/shard_cluster/myshardrs01_27218/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myshardrs01_27218/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myshardrs01_27218/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myshardrs01_27218/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27218
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myshardrs01
sharding:
   # 分片角色。
   clusterRole: shardsvr
  • 启动第一套副本集:一主一副本一仲裁。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27018/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46012
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27118/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46041
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27218/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46070
child process started successfully, parent exiting



分片(存储)节点副本集第二套。
[root@192 ~]# 
mkdir -p /mongodb/shard_cluster/myshardrs02_27318/log \
& mkdir -p /mongodb/shard_cluster/myshardrs02_27318/data/db \
& mkdir -p /mongodb/shard_cluster/myshardrs02_27418/log \
& mkdir -p /mongodb/shard_cluster/myshardrs02_27418/data/db \
& mkdir -p /mongodb/shard_cluster/myshardrs02_27518/log \
& mkdir -p /mongodb/shard_cluster/myshardrs02_27518/data/db

[root@192 ~]# vim /mongodb/shard_cluster/myshardrs02_27318/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myshardrs02_27318/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myshardrs02_27318/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myshardrs02_27318/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27318
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myshardrs02
sharding:
   # 分片角色。
   clusterRole: shardsvr
ValueDescription
configsvrStart this instance as a config server. The instance starts on port 27019 by default.
shardsvrStart this instance as a shard. The instance starts on port 27018 by default.
[root@192 ~]# vim /mongodb/shard_cluster/myshardrs02_27418/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myshardrs02_27418/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myshardrs02_27418/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myshardrs02_27418/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27418
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myshardrs02
sharding:
   # 分片角色。
   clusterRole: shardsvr
[root@192 ~]# vim /mongodb/shard_cluster/myshardrs02_27518/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myshardrs02_27518/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myshardrs02_27518/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myshardrs02_27518/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27518
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myshardrs02
sharding:
   # 分片角色。
   clusterRole: shardsvr
  • 启动第二套副本集:一主一副本一仲裁。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27318/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46149
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27418/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46178
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27518/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46207
child process started successfully, parent exiting

[root@192 ~]# ps -ef | grep mongo
root      46012      1  0 23:33 ?        00:00:10 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27018/mongod.conf
root      46041      1  0 23:34 ?        00:00:10 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27118/mongod.conf
root      46070      1  0 23:34 ?        00:00:10 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27218/mongod.conf
root      46149      1  1 23:51 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27318/mongod.conf
root      46178      1  1 23:51 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27418/mongod.conf
root      46207      1  1 23:51 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27518/mongod.conf
root      46237  45910  0 23:55 pts/3    00:00:00 grep --color=auto mongo



创建配置副本集节点。
[root@192 ~]# 
mkdir -p /mongodb/shard_cluster/myconfigrs_27019/log \
& mkdir -p /mongodb/shard_cluster/myconfigrs_27019/data/db \
& mkdir -p /mongodb/shard_cluster/myconfigrs_27119/log \
& mkdir -p /mongodb/shard_cluster/myconfigrs_27119/data/db \
& mkdir -p /mongodb/shard_cluster/myconfigrs_27219/log \
& mkdir -p /mongodb/shard_cluster/myconfigrs_27219/data/db

[root@192 ~]# vim /mongodb/shard_cluster/myconfigrs_27019/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myconfigrs_27019/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myconfigrs_27019/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myconfigrs_27019/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27019
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myconfigrs
sharding:
   # 分片角色。
   clusterRole: configsvr
ValueDescription
configsvrStart this instance as a config server. The instance starts on port 27019 by default.
shardsvrStart this instance as a shard. The instance starts on port 27018 by default.
[root@192 ~]# vim /mongodb/shard_cluster/myconfigrs_27119/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myconfigrs_27119/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myconfigrs_27119/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myconfigrs_27119/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27119
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myconfigrs
sharding:
   # 分片角色。
   clusterRole: configsvr
[root@192 ~]# vim /mongodb/shard_cluster/myconfigrs_27219/mongod.conf
systemLog:
   path: /mongodb/shard_cluster/myconfigrs_27219/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
storage:
   # mongod 实例存储其数据的目录。storage.dbPath 设置仅适用于 mongod。
   dbPath: /mongodb/shard_cluster/myconfigrs_27219/data/db
   #indexBuildRetry: <boolean>
   journal:
      # 持久性日至以确保数据文件保持有效和可恢复。
      enabled: true
      # commitIntervalMs: <num>
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/myconfigrs_27219/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27219
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
replication:
   # 副本集的名称。
   replSetName: myconfigrs
sharding:
   # 分片角色。
   clusterRole: configsvr
  • 启动第二套副本集:一主一副本一仲裁。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myconfigrs_27019/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46291
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myconfigrs_27119/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46328
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myconfigrs_27219/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46364
child process started successfully, parent exiting

[root@192 ~]# ps -ef | grep mongo
root      46012      1  0 Apr08 ?        00:00:15 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27018/mongod.conf
root      46041      1  0 Apr08 ?        00:00:15 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27118/mongod.conf
root      46070      1  0 Apr08 ?        00:00:15 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs01_27218/mongod.conf
root      46149      1  0 Apr08 ?        00:00:08 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27318/mongod.conf
root      46178      1  0 Apr08 ?        00:00:08 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27418/mongod.conf
root      46207      1  0 Apr08 ?        00:00:07 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myshardrs02_27518/mongod.conf
root      46291      1  2 00:08 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myconfigrs_27019/mongod.conf
root      46328      1  2 00:08 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myconfigrs_27119/mongod.conf
root      46364      1  2 00:08 ?        00:00:02 /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /mongodb/shard_cluster/myconfigrs_27219/mongod.conf
root      46399  45910  0 00:10 pts/3    00:00:00 grep --color=auto mongo



初始化~第一套副本集。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27018
> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.142.135:27018",
	"ok" : 1,
	"operationTime" : Timestamp(1586362370, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362370, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myshardrs01:SECONDARY> 
myshardrs01:PRIMARY> 

> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.142.135:27018",
	"ok" : 1,
	"operationTime" : Timestamp(1586362370, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362370, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myshardrs01:SECONDARY> 
myshardrs01:PRIMARY> rs.add("192.168.142.135:27118")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586362463, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362463, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myshardrs01:PRIMARY> rs.addArb("192.168.142.135:27218")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586362476, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362476, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}



初始化~第二套副本集。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27318
> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.142.135:27318",
	"ok" : 1,
	"operationTime" : Timestamp(1586362634, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362634, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myshardrs02:SECONDARY> 
myshardrs02:PRIMARY> 

> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.142.135:27318",
	"ok" : 1,
	"operationTime" : Timestamp(1586362634, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362634, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myshardrs02:SECONDARY> 
myshardrs02:PRIMARY> rs.add("192.168.142.135:27418")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586362692, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362692, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myshardrs02:PRIMARY> rs.addArb("192.168.142.135:27518")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586362924, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586362924, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}



初始化~配置节点。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27019
> rs.initiate()
{
	"info2" : "no configuration specified. Using a default configuration for the set",
	"me" : "192.168.142.135:27019",
	"ok" : 1,
	"operationTime" : Timestamp(1586363477, 1),
	"$gleStats" : {
		"lastOpTime" : Timestamp(1586363477, 1),
		"electionId" : ObjectId("000000000000000000000000")
	},
	"lastCommittedOpTime" : Timestamp(0, 0),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586363477, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myconfigrs:OTHER> 
myconfigrs:PRIMARY> rs.add("192.168.142.135:27119")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586363569, 1),
	"$gleStats" : {
		"lastOpTime" : {
			"ts" : Timestamp(1586363569, 1),
			"t" : NumberLong(1)
		},
		"electionId" : ObjectId("7fffffff0000000000000001")
	},
	"lastCommittedOpTime" : Timestamp(1586363567, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586363569, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myconfigrs:PRIMARY> rs.add("192.168.142.135:27219")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586363574, 1),
	"$gleStats" : {
		"lastOpTime" : {
			"ts" : Timestamp(1586363574, 1),
			"t" : NumberLong(1)
		},
		"electionId" : ObjectId("7fffffff0000000000000001")
	},
	"lastCommittedOpTime" : Timestamp(1586363569, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586363574, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
myconfigrs:PRIMARY> 



路由节点 mongos Router 的创建和操作。
  • 准备存放数据和日志的目录。(这里不需要 data 目录)。

[root@192 ~]# mkdir -p /mongodb/shard_cluster/mymongos_27017/log

  • mymongos_27017 节点。

配置文件。

[root@192 ~]# vim /mongodb/shard_cluster/mymongos_27017/mongos.conf
systemLog:
   path: /mongodb/shard_cluster/mymongos_27017/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/mymongos_27017/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27017
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
#replication:
#   # 副本集的名称。
#   replSetName: myconfigrs
sharding:
   # 指定配置节点副本集。
   configDB: myconfigrs/192.168.142.135:27019,192.168.142.135:27119,192.168.142.135:27219
  • 启动 mongos。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongos -f /mongodb/shard_cluster/mymongos_27017/mongos.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 46982
child process started successfully, parent exiting

  • 客户端登录 mongos。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --host 192.168.142.135 --port 27017
mongos> show dbs;
admin   0.000GB
config  0.000GB

不能写数据。



在路由节点上进行分片配置操作。

sh.addShard(“IP:port”)

  • 将第一套分片副本集加入。
mongos> sh.addShard("myshardrs01/192.168.142.135:27018,192.168.142.135:27118,192.168.142.135:27218")
{
	"shardAdded" : "myshardrs01",
	"ok" : 1,
	"operationTime" : Timestamp(1586365831, 8),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586365831, 8),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

  • 将第二套分片副本集加入。
mongos> sh.addShard("myshardrs02/192.168.142.135:27318,192.168.142.135:27418,192.168.142.135:27518")
{
	"shardAdded" : "myshardrs02",
	"ok" : 1,
	"operationTime" : Timestamp(1586366782, 5),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586366782, 5),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
  	"_id" : 1,
  	"minCompatibleVersion" : 5,
  	"currentVersion" : 6,
  	"clusterId" : ObjectId("5e8dfc556fd5c454adec608a")
  }
  shards:
        {  "_id" : "myshardrs01",  "host" : "myshardrs01/192.168.142.135:27018,192.168.142.135:27118",  "state" : 1 }
        {  "_id" : "myshardrs02",  "host" : "myshardrs02/192.168.142.135:27318,192.168.142.135:27418",  "state" : 1 }
  active mongoses:
        "4.0.17" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	1
                        { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : myshardrs01 Timestamp(1, 0) 

mongos> 



开启分片功能。

sh.enableSharding(“库名”)
sh.shardCollection(“库名.集合名”: {“key”: 1})

在 mongos 上的 articledb 数据库配置 sharding。

mongos> sh.enableSharding("articledb")
{
	"ok" : 1,
	"operationTime" : Timestamp(1586367142, 7),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586367142, 7),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
  • 集合分片。

sh.shardCollection(namespace, key, unique)

ParameterTypeDescription
namespaceString要(分片)共享的目标集合的命名空间。格式:<database>.<collection>
keydocument用作分片键的索引规范文档。shard 键决定 MongoDB 如何在 shard 之间分发文档。除非集合为空,否则索引必须在 shard collection 命令之前存在。如果集合为空,则 MongoDB 在对集合进行分片之前创建索引,前提是支持分片键的索引不存在。简单的说:由包含字段和该字段的索引遍历方向的文档组成。
uniqueboolean当值为 true 情况下,片键字段上会限制为确保是唯一索引。哈希策略片键不支持唯一索引。默认是 false。


分片规则。
- 哈希策略。

对于基于哈希的分片,MongoDB 计算一个字段的哈希值,并用这个哈希值来创建数据块。
在使用基于哈希分片的系统中,拥有“相近”片键的文档很可能不会存储在同一个

使用 nickName 作为片键。根据其值的哈希值进行数据分片。

mongos> sh.shardCollection("articledb.comment", {"nickName": "hashed"})
{
	"collectionsharded" : "articledb.comment",
	"collectionUUID" : UUID("d9c19cb9-32d3-4b2a-ad49-2ea9624efe3a"),
	"ok" : 1,
	"operationTime" : Timestamp(1586370005, 28),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586370005, 28),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

查看分片状态。

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
  	"_id" : 1,
  	"minCompatibleVersion" : 5,
  	"currentVersion" : 6,
  	"clusterId" : ObjectId("5e8dfc556fd5c454adec608a")
  }
  shards:
        {  "_id" : "myshardrs01",  "host" : "myshardrs01/192.168.142.135:27018,192.168.142.135:27118",  "state" : 1 }
        {  "_id" : "myshardrs02",  "host" : "myshardrs02/192.168.142.135:27318,192.168.142.135:27418",  "state" : 1 }
  active mongoses:
        "4.0.17" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "articledb",  "primary" : "myshardrs02",  "partitioned" : true,  "version" : {  "uuid" : UUID("db0eb3a4-c050-4bac-bbd1-3461e79ef0eb"),  "lastMod" : 1 } }
                articledb.comment
                        shard key: { "nickName" : "hashed" }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	2
                                myshardrs02	2
                        { "nickName" : { "$minKey" : 1 } } -->> { "nickName" : NumberLong("-4611686018427387902") } on : myshardrs01 Timestamp(1, 0) 
                        { "nickName" : NumberLong("-4611686018427387902") } -->> { "nickName" : NumberLong(0) } on : myshardrs01 Timestamp(1, 1) 
                        { "nickName" : NumberLong(0) } -->> { "nickName" : NumberLong("4611686018427387902") } on : myshardrs02 Timestamp(1, 2) 
                        { "nickName" : NumberLong("4611686018427387902") } -->> { "nickName" : { "$maxKey" : 1 } } on : myshardrs02 Timestamp(1, 3) 
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	1
                        { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : myshardrs01 Timestamp(1, 0) 

mongos> 



- 范围策略。

对于基于范围的分片,MongoDB 按照片键的范围吧数据分成不同比分。假设有一个数字的片键,想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点,MongoDB 把这条直线划分为更短的不重叠的片段,并称之为数据块,每个数据块包含了片键在一定范围内的数据。
在使用片键作范围划分的系统中,拥有“相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中。

使用 age 作为片键。按照点赞数的值进行分片。

mongos> sh.shardCollection("articledb.author", {"age": 1})
{
	"collectionsharded" : "articledb.author",
	"collectionUUID" : UUID("98c390ab-7cc6-4c53-bdda-ed5441b186c7"),
	"ok" : 1,
	"operationTime" : Timestamp(1586370617, 12),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1586370617, 12),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

查看分片状态。

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
  	"_id" : 1,
  	"minCompatibleVersion" : 5,
  	"currentVersion" : 6,
  	"clusterId" : ObjectId("5e8dfc556fd5c454adec608a")
  }
  shards:
        {  "_id" : "myshardrs01",  "host" : "myshardrs01/192.168.142.135:27018,192.168.142.135:27118",  "state" : 1 }
        {  "_id" : "myshardrs02",  "host" : "myshardrs02/192.168.142.135:27318,192.168.142.135:27418",  "state" : 1 }
  active mongoses:
        "4.0.17" : 1
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "articledb",  "primary" : "myshardrs02",  "partitioned" : true,  "version" : {  "uuid" : UUID("db0eb3a4-c050-4bac-bbd1-3461e79ef0eb"),  "lastMod" : 1 } }
                articledb.author
                        shard key: { "age" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs02	1
                        { "age" : { "$minKey" : 1 } } -->> { "age" : { "$maxKey" : 1 } } on : myshardrs02 Timestamp(1, 0) 
                articledb.comment
                        shard key: { "nickName" : "hashed" }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	2
                                myshardrs02	2
                        { "nickName" : { "$minKey" : 1 } } -->> { "nickName" : NumberLong("-4611686018427387902") } on : myshardrs01 Timestamp(1, 0) 
                        { "nickName" : NumberLong("-4611686018427387902") } -->> { "nickName" : NumberLong(0) } on : myshardrs01 Timestamp(1, 1) 
                        { "nickName" : NumberLong(0) } -->> { "nickName" : NumberLong("4611686018427387902") } on : myshardrs02 Timestamp(1, 2) 
                        { "nickName" : NumberLong("4611686018427387902") } -->> { "nickName" : { "$maxKey" : 1 } } on : myshardrs02 Timestamp(1, 3) 
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                myshardrs01	1
                        { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : myshardrs01 Timestamp(1, 0) 

mongos> 



测试。
mongos> db
articledb
mongos> for(var i = 1; i <= 1000; i++) {db.comment.insert({_id: i - "", nickName: "geek" - i})}
WriteResult({ "nInserted" : 1 })
mongos> db.comment.count()
1000
mongos> 
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --port 27318
myshardrs02:PRIMARY> use articledb
switched to db articledb
myshardrs02:PRIMARY> db.comment.count()
508
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo --port 27018
myshardrs01:PRIMARY> db.comment.count()
492


再添加一个路由节点。

[root@192 ~]# mkdir -p /mongodb/shard_cluster/mymongos_27117/log

  • mymongos_27117 节点。

配置文件。

[root@192 ~]# vim /mongodb/shard_cluster/mymongos_27117/mongos.conf
systemLog:
   path: /mongodb/shard_cluster/mymongos_27117/log/mongod.log
   # 当 mangos 或 mongod 实例重新启动后,mongos 或 mongod 会将新条目附加到现有日志文件的末尾。
   logAppend: true
   # mongoDB 发送所有日志输出的目标为文件。
   destination: file
processManagement:
   # 启用在后台运行 mongos 或 mongod 进程的守护进程模式。
   fork: true
   # 指定用于保存 mongos 或 mongod 进程的进程 id 文件位置。其中 mongos 或 mongod 将写入其 pid。
   pidFilePath: /mongodb/shard_cluster/mymongos_27117/log/mongod.pid
   #timeZoneInfo: <string>
net:
   port: 27117
   #port: <int>

   # 服务实例绑定所有 IP,有副作用。副本集初始化的时候,节点名字会自动设置为本地域名,而不是 ip。
   # bindIpAll: true
   # 服务实例绑定的 IP。默认是 localhost
   bindIp: localhost,192.168.142.135
#replication:
#   # 副本集的名称。
#   replSetName: myconfigrs
sharding:
   # 指定配置节点副本集。
   configDB: myconfigrs/192.168.142.135:27019,192.168.142.135:27119,192.168.142.135:27219
  • 启动 mongos。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongos -f /mongodb/shard_cluster/mymongos_27117/mongos.conf
about to fork child process, waiting until server is ready for connections.
forked process: 47944
child process started successfully, parent exiting



SpringData 连接。
spring:
  data:
    mongodb:
      uri: mongodb://192.168.142.135:27017,192.168.142.135:27117/articledb
#      uri: mongodb://192.168.142.135:27017, 192.168.142.135:27018, 192.168.142.135:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
      #      host: 192.168.142.135
      #      database: test
      #      port: 27017
      # 也可以使用 url 连接。
#      uri: mongodb://192.168.142.135:27017/articledb


安全认证。

默认情况下,MongoDB 实例启动运行时是没有启用用户访问权限控制的,也就是说,在实体本机服务器上都可以随意连接到实例进行各种操作,MongoDB 不会对连接客户端进行用户验证,这是非常危险的。

——》

  • 使用新的端口,默认的 27017 端口一旦知道了 ip 就能连接上,不安全。
  • 设置 MongoDB 的网络环境,最好将 MongoDB 部署到公司服务器内网,这样外网是访问不到的。公司内部访问使用 vpn 等。
  • 开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。

在 MongoDB 实例启动使用选项 --auth 或在启动配置文件中添加选项 auth=true

  • 启用访问控制。

MongoDB 使用的是基于角色的访问控制(Role-Based Access Control, RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。

  • 角色。

在 MongoDB 中通过角色对用户授予相应数据库资源的操作权限,每个角色中的权限可以显式指定,也可以通过继承其他角色的权限,或者两者都存在的权限。

  • 权限。

权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。

  • 资源(resource):数据库、集合、部分集合和集群。
  • 操作(action):对资源进行增删改查操作。

在角色定义时可以包含一个或多个已存在的角色,新创建的角色会继承包含的角色所有权限。在同一个数据库中,新创建的角色可以继承其他角色的权限,在 admin 数据库中创建的角色可以继承在其他任意数据库中角色的权限。

角色权限
read@Database User Roles。可以读取指定数据库中任何数据。
readWrite@Database User Roles。可以读写指定数据库中任何数据,包括创建、重命名、删除集合。
dbAdmin@Database Administration Roles。可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息执行检查等操作。
userAdmin@Database Administration Roles。可以在指定数据库创建和修改用户。
clusterAdmin@Cluster Administration Roles。可以对整个集群或数据库系统进行管理操作。
clusterManager@Cluster Administration Roles。
clusterMonitor@Cluster Administration Roles。
hostManager@Cluster Administration Roles。
backup@Backup and Restoration Roles。备份 MongoDB 数据最小权限。
restore@Backup and Restoration Roles。从备份文件中还原恢复 MongoDB 数据(除了 system.profile 集合)的权限。
readAnyDatabase@All-Database Roles。可以读取所有数据库中任何数据(除了数据库 config 和 local 之外)。
readWriteAnyDatabase@All-Database Roles。可以读写所有数据库中任何数据(除了数据库 config 和 local 之外)。
userAdminAnyDatabase@All-Database Roles。可以在指定数据库创建和修改用户(除了数据库 config 和 local 之外)。
dbAdminAnyDatabase@All-Database Roles。可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统计信息执行检查等操作(除了数据库 config 和 local 之外)。
root@Superuser Roles。超级账号,超级权限。
__system@Internal Role。


单实例环境。

(未开启副本集或分片的 MongoDB 实例)。

关闭所有 mongo 服务。启动单机 mongo 服务。

[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /usr/local/mongodb/single/mongod.conf 
about to fork child process, waiting until server is ready for connections.
forked process: 48915
child process started successfully, parent exiting
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo
  • 创建超级管理员。
> use admin
switched to db admin
> db.createUser({user: "myroot", pwd: "123.", roles: [{"role": "root", "db": "admin"}]})
> Successfully added user: {
	"user" : "myroot",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
> // 或
> db.createUser({user: "myroot", pwd: "123456", roles: ["root"]})
> // 创建专门用来管理 admin 库的账号 myadmin,只用来作为用户权限管理。
> db.createUser({user: "myadmin", pwd: "123.", roles: [{role: "userAdminAnyDatabase", db: "admin"}]})
> Successfully added user: {
	"user" : "myadmin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	]
}

  • 查看用户。
> db.system.users.find()
{ "_id" : "admin.myroot", "userId" : UUID("af174892-632b-4416-abc0-3a9732929c2f"), "user" : "myroot", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "2R4lboAm1sHoP3Rl2zgOzg==", "storedKey" : "j8uiwe83E2rCNY7W3w9cL/+refw=", "serverKey" : "RHMdkzI905HIGcL4zjHfor0Ppok=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "Z2emksaCDd1RKKBA3BqetpyUXwNVJNolpgNprA==", "storedKey" : "Q1iXz7VBP3ymwiAkUryyHk5T3Y5LVaqAWFURBCyGFMY=", "serverKey" : "p2uvP9CTSwz74YHF3zK2U/Jh76ISB8HJ32JAktdiEbY=" } }, "roles" : [ { "role" : "root", "db" : "admin" } ] }
{ "_id" : "admin.myadmin", "userId" : UUID("111fa55b-3535-4791-b4eb-c87a811a5c7d"), "user" : "myadmin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "0rOcKsp/0H9mxjTsuIdung==", "storedKey" : "jBJr/c+fTrDgCL1m9SozJjMSoyE=", "serverKey" : "ueSuBtjw0+nAYdnOdcMz0/Q198g=" }, "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "9bluIul/FGsebI1UIZQYd7G0ls3Vy1dn+U+3Ww==", "storedKey" : "4y9BYYaop581ebkQmJ2IAtwb8phvIee+sgAwNwI3ZaM=", "serverKey" : "ad5c8ewk8BwqKD9X93vXgJoouGi88Hwb2z1FDJYUr4E=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }
  • 删除用户。
db.dropUser("myadmin")
  • 修改密码。
db.changeUserPassword("myroot", "123.")
  • 认证测试。
> db.auth("myroot", "2")
Error: Authentication failed.
0
> db.auth("myroot", "123.")
1


创建普通用户。
> db.createUser({user: "geek", pwd: "123.", roles: [{role: "readWrite", db: "articledb"}]})
Successfully added user: {
	"user" : "geek",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "articledb"
		}
	]
}
> db.createUser({user: "geek", pwd: "123.", role: ["readWrite"]})



开启认证。
  • 参数方式。
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /usr/local/mongodb/single/mongod.conf --auth
  • 配置文件。

/usr/local/mongodb/single/mongod.conf

security:
   # 开启授权认证。
   authorization: enabled
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongod -f /usr/local/mongodb/single/mongod.conf
[root@192 ~]# /usr/local/mongodb/mongodb-linux-x86_64-4.0.17/bin/mongo
> show dbs
> 
> show collections
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
> 

  • 登录。
> db.auth("myroot", "123.")
Error: Authentication failed.
0
> use admin
switched to db admin
> db.auth("myroot", "123.")
1


SpringData。
spring:
  data:
    mongodb:
      #      host: 192.168.142.135
      #      database: test
      #      port: 27017
      uri: mongodb://geek:123.@192.168.142.135:27017/articledb


副本集安全认证。


分片集安全认证。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyfGeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值