Mongodb 运维讲解 - Go语言中文社区

Mongodb 运维讲解


一、介绍

Mongodb 是 NoSql ,属于文档存储,同类型的文档存储还有ES

Mongodb 是介于关系型数据库和非关系性数据库之间,故有强大的关系型数据库功能 ( 查询功能、强一致性、二级索引)  和关系性数据库 ( 灵活模式、扩展性、性能 ) 

Mongodb 与 Redis 区别:没有固定的行列组织数据结构

表   叫做   集合        数据行 叫做  文档    

Mongodb 存档就是文档 ,一个文档就是一个 json,相当于 mysql 的一行中数据

二、部署Mongodb

官网:Download MongoDB Community Server | MongoDB

1、查看操作系统内核版本

# 操作系统内核版本
uname -a
# 操作系统发行版本
cat /etc/redhat-release

2、下载 mongodb_4.0.28

​[root@db1 opt]# yun install -y wget
[root@db1 ~]# cd /opt/src
[root@db1 src]# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.28.tgz

3、解压目录

# -C 指定解压目录
[root@db1 src]# tar -zxvf mongodb-linux-x86_64-rhel70-4.0.28.tgz -C /opt/

# 修改名字
[root@db1 src]# cd /opt
[root@db1 opt]# mv mongodb-linux-x86_64-rhel70-4.0.28/ mongodb-4.0.28

# 软连接
[root@db1 opt]# ln -s mongodb-4.0.28/ mongodb

4、mongodb主要使用的就是bin目录的二进制文件,加载到环境变量中

[root@db1 mongodb]# ll /opt/mongodb/
drwxr-xr-x 2 root root    70 10月 24 11:32 bin
-rw-r--r-- 1 root root 30608 9月  29 19:18 LICENSE-Community.txt
-rw-r--r-- 1 root root 16726 9月  29 19:18 MPL-2
-rw-r--r-- 1 root root  1977 9月  29 19:18 README
-rw-r--r-- 1 root root 77913 9月  29 19:18 THIRD-PARTY-NOTICES

[root@db1 mongodb]# ll /opt/mongodb/bin/
-rwxr-xr-x 1 root root     15205 9月  29 19:18 install_compass
-rwxr-xr-x 1 root root  58599688 9月  29 20:05 mongo
-rwxr-xr-x 1 root root 110063096 9月  29 20:04 mongod
-rwxr-xr-x 1 root root  76724856 9月  29 20:05 mongos

5、配置环境变量

[root@db1 mongodb]# echo "export PATH=\$PATH:/opt/mongodb/bin/" >> /etc/profile 

# 使配置文件生效
[root@db1 mongodb]# source /etc/profile

6、创建 data 目录

[root@db1 opt]# mkdir -p /opt/mongodb/{conf,log,data}

7、启动mongodb ,验证是否能启动 

[root@db1 conf]# mongod --dbpath /opt/mongodb/data/ --logpath /opt/mongodb/logs/mongodb.log --logappend --port 27017 --fork

注:可以添加-bind_ip 0.0.0.0 选项,让所有的用户访问mongodb,可以不加

[root@db1 conf]# ps -ef |grep mongodb
root      2830     1  0 14:19 ?        00:00:03 mongod --dbpath /opt/mongodb/data/ --logpath /opt/mongodb/logs/mongodb.log --logappend --port 27017 --bind_ip 0.0.0.0 --fork
root      3180  2075  0 14:25 pts/2    00:00:00 grep --color=auto mongodb

[root@db1 conf]# ll /opt/mongodb/data/  # 第一次启动生成的初始化文件
总用量 272
-rw------- 1 root root 20480 10月 24 14:19 collection-0--3238775234172203344.wt
-rw------- 1 root root 36864 10月 24 14:20 collection-2--3238775234172203344.wt
-rw------- 1 root root  4096 10月 24 14:07 collection-4--3238775234172203344.wt
drwx------ 2 root root   197 10月 24 14:26 diagnostic.data
-rw------- 1 root root 20480 10月 24 14:19 index-1--3238775234172203344.wt
-rw------- 1 root root 36864 10月 24 14:20 index-3--3238775234172203344.wt
-rw------- 1 root root  4096 10月 24 14:07 index-5--3238775234172203344.wt
-rw------- 1 root root  4096 10月 24 14:20 index-6--3238775234172203344.wt
drwx------ 2 root root   110 10月 24 14:19 journal
-rw------- 1 root root 20480 10月 24 14:19 _mdb_catalog.wt
-rw------- 1 root root     5 10月 24 14:19 mongod.lock
-rw------- 1 root root 36864 10月 24 14:21 sizeStorer.wt
-rw------- 1 root root   114 10月 24 14:06 storage.bson
-rw------- 1 root root    50 10月 24 14:06 WiredTiger
-rw------- 1 root root  4096 10月 24 14:19 WiredTigerHS.wt
-rw------- 1 root root    21 10月 24 14:06 WiredTiger.lock
-rw------- 1 root root  1467 10月 24 14:26 WiredTiger.turtle
-rw------- 1 root root 69632 10月 24 14:26 WiredTiger.wt
[root@db1 conf]# ll /opt/mongodb/logs/
总用量 192
-rw------- 1 root root 90288 10月 24 14:26 mongodb.log
[root@db1 conf]# 

8、配置文件

--系统日志有关
systemLog: 
 destination: file                       --定义日志
 path: "/var/log/mongo/mongod.log"       --日志位置
 quiet: true                             --安静输出
 logAppend: true                         --日志以追加模式记录

--数据存储有关
storage:                                 --定义数据存储
 journal:                                --是不是开启redo
  enabled             
 dbPath: "/var/lib/mongo"                --数据位置
 directoryPerDB: true                    --设置每个数据库将被保存在一个单独的目录
 indexBuildRetry: false                  --在一个索引创建失败后启动mongod,可以使用storage.indexBuildRetry or --noIndexBuildRetry跳过索引创建来启动
 preallocDataFiles: true
 nsSize: 16                              --设置数据库.ns文件大小(MB)

--进程控制
processManagement:                                         
 fork: true                                    --后台守护进程
 pidFilePath: "/var/run/mongodb/mongod.pid"    --pid文件位置,默认不指定在/data目录下

--网络有关的
net: 
 bindIp: 192.168.11.52                    --监听端口,如果不配置这行就是监听0.0.0.0
 port: 27017                              --端口号,默认不配置端口号,是27017
 http:
  enabled: true
  RESTInterfaceEnabled: false 

--安全认证有关,比mysql更加的安全,有认证库
security:
 keyFile: "/var/lib/mongo/mongodb-keyfile"
 clusterAuthMode: "keyFile"
 authorization: "disabled"               --是否打开用户名密码验证


--集群相关的
replication:
 oplogSizeMB: 50
 replSetName: "repl_test"
 secondaryIndexPrefetch: "all"

[root@db1 conf]# cat /opt/mongodb/conf/mongod.cfg   # 先简单配置

storage:
  dbPath: /opt/mongodb/data/
  journal:
    enabled: true
 
systemLog:
  destination: file
  logAppend: true
  path:  /opt/mongodb/log/mongodb.log
 
processManagement: 
  fork: true
 
net:
  bindIp: 192.168.86.5,127.0.0.1
  port: 27017

9、关闭之前启动的mongodb,添加systemcd 管理,并使用自定义配置文件进行启动

# 关闭mongodb
[root@db1 conf]# mongod -f /opt/mongodb/conf/mongod.cfg --shutdown
killing process with pid: 3755

# 启动 mongodb
[root@db1 mongodb]# cat /etc/systemd/system/mongod.service
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
 
[Service]
Type=forking
User=root
Group=root
ExecStart=/opt/mongodb/bin/mongod --config /opt/mongodb/conf/mongo.conf
ExecReload=/bin/kill -s HUP
ExecStop=/opt/mongodb/bin/mongod --config /opt/mongodb/conf/mongo.conf --shutdown
PrivateTmp=true

[root@db1 mongodb]# systemctl daemon-reload
[root@db1 mongodb]# systemctl start mongod.service

10、登陆mongo

[root@db1 mongodb]# mongo
MongoDB shell version v4.0.28
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("a1d7a2ab-ac77-47d6-bf1c-23e469d9ad2a") }
MongoDB server version: 4.0.28
Server has startup warnings: 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2022-10-24T15:42:34.696+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()
---

> 
[root@db1 data]# ll
总用量 188
drwx------ 4 root root    37 10月 25 06:12 admin
drwx------ 4 root root    37 10月 25 06:12 config
drwx------ 2 root root   216 10月 25 09:13 diagnostic.data
drwx------ 4 root root    37 10月 25 08:47 jerry
drwx------ 2 root root   110 10月 25 09:06 journal   #日志
drwx------ 4 root root    37 10月 25 05:54 local
-rw------- 1 root root 36864 10月 25 09:13 _mdb_catalog.wt
-rw------- 1 root root     0 10月 25 09:13 mongod.lock
-rw------- 1 root root 36864 10月 25 09:13 sizeStorer.wt
-rw------- 1 root root   114 10月 25 05:54 storage.bson
-rw------- 1 root root    45 10月 25 05:54 WiredTiger
-rw------- 1 root root  4096 10月 25 09:13 WiredTigerLAS.wt
-rw------- 1 root root    21 10月 25 05:54 WiredTiger.lock
-rw------- 1 root root  1073 10月 25 09:13 WiredTiger.turtle
-rw------- 1 root root 98304 10月 25 09:13 WiredTiger.wt  # .wt使用WiredTiger存储引擎存储的

三、命令集合

1、增删改查(库、集合、文档)

只有show databases(show dbs)、 use 库、show tables(show collections; 跟 mysl 一样,其他的都不一样
输入mongo后,提示的信息说的是没有验证之类的,好在mongodb只允许本地登陆

[root@db1 mongodb]# mongo
MongoDB shell version v4.0.28
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("a1d7a2ab-ac77-47d6-bf1c-23e469d9ad2a") }
MongoDB server version: 4.0.28
Server has startup warnings: 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] 
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2022-10-24T15:42:34.696+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2022-10-24T15:42:34.696+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 databases;
admin   0.000GB
config  0.000GB
local   0.000GB
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
> use admin
switched to db admin
> show tables;
system.version
> 

这三个库是mongodb相关的系统库,不能删除,不能修改

admin   0.000GB  # 系统相关的
config  0.000GB  # 配置相关的
local   0.000GB  # 日志相关的

db 命令,代表你在哪个库下,每次第一次登陆,会进入一个临时库 test 库

> db
test

如何指定库登陆

[root@db1 mongodb]# mongo admin

> db
admin

[root@db1 mongodb]# mongo admin1   # 库不存在直接创建

> db
admin1

创建数据库直接use,如果不存在则创建,存在则切换到

> use dev
switched to db dev
> db
dev

集合(表)中插入数据,给 jerry 表插入一条文档(数据行)

> db.jerry.insert({name:"hello"})
WriteResult({ "nInserted" : 1 })
> 

只要数据库中存在表,则 数据库会自动保存

> show databases;
admin   0.000GB
config  0.000GB
dev     0.000GB
local   0.000GB
> use abc
switched to db abc
> show databases;
admin   0.000GB
config  0.000GB
dev     0.000GB
local   0.000GB
> 

查集合中的文档 db.集合.find()

> use dev
switched to db dev
> show collections;
jerry
> db.jerry.find()
{ "_id" : ObjectId("635647932670e9afdaddee05"), "name" : "hello" }
> db.jerry.insert({name:"world"})
WriteResult({ "nInserted" : 1 })
> db.jerry.find()
{ "_id" : ObjectId("635647932670e9afdaddee05"), "name" : "hello" }
{ "_id" : ObjectId("6356495d2670e9afdaddee06"), "name" : "world" }
> 

help() 函数,帮助文档

> db.help()

table 命令补全

> db.
Display all 103 possibilities? (y or n)
db.adminCommand(                   db.fsyncUnlock(                    db.grantPrivilegesToRole(          db.revokePrivilegesFromRole(
db.aggregate(                      db.getCollection(                  db.grantRolesToRole(               db.revokeRolesFromRole(
db.auth(                           db.getCollectionInfos(             db.grantRolesToUser(               db.revokeRolesFromUser(
db.changeUserPassword(             db.getCollectionNames(             db.group(                          db.runCommand(
db.cloneCollection(                db.getFreeMonitoringStatus(        db.groupcmd(                       

createCollection 创建集合

> db.createCollection("zxy")
{ "ok" : 1 }
> show tables;
zxy
> db.zxy.find()
> 

修改表名 renameCollection

> db.zxy.renameCollection("biao1")
{ "ok" : 1 }

删除表

> show tables;
zxy
> db.zxy.drop()
true

查看版本

> db.version()
4.0.28
> 
[root@db1 ~]# mongo -version
MongoDB shell version v4.0.28
git version: af1a9dc12adcfa83cc19571cb3faba26eeddac92
OpenSSL version: OpenSSL 1.0.1e-fips 11 Feb 2013
allocator: tcmalloc
modules: none
build environment:
    distmod: rhel70
    distarch: x86_64
    target_arch: x86_64

库状态,可以看库占用空间大小

> show databases;
admin   0.000GB
config  0.000GB
dev     0.000GB
local   0.000GB
> use admin
> db.stats()
{
	"db" : "admin",
	"collections" : 1,
	"views" : 0,
	"objects" : 1,
	"avgObjSize" : 59,
	"dataSize" : 59,
	"storageSize" : 16384,
	"numExtents" : 0,
	"indexes" : 1,
	"indexSize" : 16384,
	"fsUsedSize" : 10771628032,
	"fsTotalSize" : 40778076160,
	"ok" : 1
}

 显示连接的地址

> db.getMongo()
connection to 127.0.0.1:27017
> 

删除库  use 库  db.dropDatabase()

> use dev
switched to db dev
> show tables;
jerry
> db.dropDatabase()
{ "dropped" : "dev", "ok" : 1 }
> db
dev
> show databases;
admin   0.000GB
config  0.000GB
local   0.000GB
> 

集合操作 db.getCollectionNames()

> use app
switched to db app
> db.createCollection('a')
{ "ok" : 1 }
> db.createCollection('b')
{ "ok" : 1 }
> show collections
a
b
> db.getCollectionNames()
[ "a", "b" ]

pretty() 以 json 格式显示

> db.test.find({"age" : "10", "gender" : "nan"})
{ "_id" : ObjectId("6356d3e931c488f67f74bd3b"), "id" : "102", "name" : "lisi", "age" : "10", "gender" : "nan" }
{ "_id" : ObjectId("6356d43d31c488f67f74bd3c"), "id" : "102", "name" : "liu", "age" : "10", "gender" : "nan" }
> db.test.find({"age" : "10", "gender" : "nan"}).pretty()
{
	"_id" : ObjectId("6356d3e931c488f67f74bd3b"),
	"id" : "102",
	"name" : "lisi",
	"age" : "10",
	"gender" : "nan"
}
{
	"_id" : ObjectId("6356d43d31c488f67f74bd3c"),
	"id" : "102",
	"name" : "liu",
	"age" : "10",
	"gender" : "nan"
}
> 

删除记录  # 注意删除表中所有数据,会很慢,所以建议删除表,在创建一个空表

> db.test.find()
{ "_id" : ObjectId("6356d25a31c488f67f74bd37"), "name" : "zhang" }
{ "_id" : ObjectId("6356d2c031c488f67f74bd38"), "id" : "101", "name" : "liu", "age" : "10" }
{ "_id" : ObjectId("6356d2ff31c488f67f74bd39"), "name" : "zhang", "age" : "23" }
{ "_id" : ObjectId("6356d3b831c488f67f74bd3a"), "id" : "102", "name" : "lisi", "age" : "10" }
{ "_id" : ObjectId("6356d3e931c488f67f74bd3b"), "id" : "102", "name" : "lisi", "age" : "10", "gender" : "nan" }
{ "_id" : ObjectId("6356d43d31c488f67f74bd3c"), "id" : "102", "name" : "liu", "age" : "10", "gender" : "nan" }


# 删除指定的文档(数据行)
> db.test.remove({"age" : "10", "gender" : "nan"})
WriteResult({ "nRemoved" : 2 })
> db.test.find()
{ "_id" : ObjectId("6356d25a31c488f67f74bd37"), "name" : "zhang" }
{ "_id" : ObjectId("6356d2c031c488f67f74bd38"), "id" : "101", "name" : "liu", "age" : "10" }
{ "_id" : ObjectId("6356d2ff31c488f67f74bd39"), "name" : "zhang", "age" : "23" }
{ "_id" : ObjectId("6356d3b831c488f67f74bd3a"), "id" : "102", "name" : "lisi", "age" : "10" }

# 删除表中所有数据
> db.test.remove({})
WriteResult({ "nRemoved" : 4 })
> db.test.find()
> 

去掉集合中,某列重复值后,都存在什么, 查询语句,不影响原值

> db.jihe.find()
{ "_id" : ObjectId("6356da33e3f8ef3a107dc651"), "id" : "101", "name" : "lisi", "age" : "10", "gender" : "nan" }
{ "_id" : ObjectId("6356da42e3f8ef3a107dc652"), "id" : "102", "name" : "zhang", "age" : "12", "gender" : "nan" }
{ "_id" : ObjectId("6356da4fe3f8ef3a107dc653"), "id" : "103", "name" : "wang", "age" : "10", "gender" : "nan" }
{ "_id" : ObjectId("6356db851a1cdc1597160e25"), "id" : "104", "name" : "lisi", "age" : "12", "gender" : "nan" }

> db.jihe.distinct("age")   # age去重后,只有10 和 12
[ "10", "12" ]
> db.jihe.distinct("name")  # name去重后,只有lisi 和 wang 和 zhang
[ "lisi", "wang", "zhang" ]
> 

2、增删改使用

 1、给一个新的文档插入数据

> use jerry
switched to db jerry
> db.test.insert({name:"zhang"})
WriteResult({ "nInserted" : 1 })
> db.test.insert({id:"101",name:"liu",age:"10",gender:"nan"})
WriteResult({ "nInserted" : 1 })
> db.test.insert({id:"102",name:"liu",age:"10",gender:"nan"})
WriteResult({ "nInserted" : 1 })

2、指定查询

> db.test.find({"age" : "10", "gender" : "nan"})
{ "_id" : ObjectId("6356d3e931c488f67f74bd3b"), "id" : "102", "name" : "lisi", "age" : "10", "gender" : "nan" }
{ "_id" : ObjectId("6356d43d31c488f67f74bd3c"), "id" : "102", "name" : "liu", "age" : "10", "gender" : "nan" }
> 

3、批量插入数据,mongodb支持for循环 (压力测试)

> for(i=0;i<10;i++){db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new
... Date()})}
WriteResult({ "nInserted" : 1 })
> db.log.find()
{ "_id" : ObjectId("6356d64f31c488f67f74bd3d"), "uid" : 0, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.748Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd3e"), "uid" : 1, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.764Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd3f"), "uid" : 2, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.764Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd40"), "uid" : 3, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.765Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd41"), "uid" : 4, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.765Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd42"), "uid" : 5, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.765Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd43"), "uid" : 6, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.765Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd44"), "uid" : 7, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.766Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd45"), "uid" : 8, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.766Z") }
{ "_id" : ObjectId("6356d64f31c488f67f74bd46"), "uid" : 9, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:15:43.766Z") }
> 

4、会自动分页,每页20条,超过提示Type "it" for more,输入it下一页。 使用DBQuery.shellBatchSize= 修改多扫条一页 (修改后真对已经存在、以后创建的) 

{ "_id" : ObjectId("6356d6a531c488f67f74bd57"), "uid" : 16, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:17:09.635Z") }
{ "_id" : ObjectId("6356d6a531c488f67f74bd58"), "uid" : 17, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:17:09.635Z") }
{ "_id" : ObjectId("6356d6a531c488f67f74bd59"), "uid" : 18, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:17:09.635Z") }
{ "_id" : ObjectId("6356d6a531c488f67f74bd5a"), "uid" : 19, "name" : "mongodb", "age" : 6, "date" : ISODate("2022-10-24T18:17:09.636Z") }
Type "it" for more
> 

> DBQuery.shellBatchSize=30;

3、复制集有关

复制集有关(replication set)  rs  比 mysql 主从复制高级太多,比MHA还好用,保证了集群的所有节点的一致性,不会出现不一致问题,有延时,隐藏、投票等等。

分片集群(sharding custer)  sh  自动分片,分布式集群

> rs.
rs.add(                            rs.constructor                     rs.printReplicationInfo(           rs.slaveOk(
rs.addArb(                         rs.debug                           rs.printSecondaryReplicationInfo(  rs.status(
rs.apply(                          rs.freeze(                         rs.printSlaveReplicationInfo(      rs.stepDown(
rs.bind(                           rs.hasOwnProperty(                 rs.propertyIsEnumerable(           rs.syncFrom(
rs.call(                           rs.hello(                          rs.prototype                       rs.toLocaleString(
rs.compareOpTimes(                 rs.help(                           rs.reconfig(                       rs.toString(
rs.conf(                           rs.initiate(                       rs.remove(                         rs.valueOf(
rs.config(                         rs.isMaster(                       rs.secondaryOk(
> sh.
sh.addShard(               sh.disableBalancing(       sh.getShouldAutoSplit(     sh.removeShardTag(         sh.toLocaleString(
sh.addShardTag(            sh.enableAutoSplit(        sh.hasOwnProperty(         sh.removeTagRange(         sh.toString(
sh.addShardToZone(         sh.enableBalancing(        sh.help(                   sh.setBalancerState(       sh.updateZoneKeyRange(
sh.addTagRange(            sh.enableSharding(         sh.isBalancerRunning(      sh.shardCollection(        sh.valueOf(
sh.apply(                  sh.getActiveMigrations(    sh.moveChunk(              sh.splitAt(                sh.waitForPingChange(
sh.bind(                   sh.getBalancerState(       sh.propertyIsEnumerable(   sh.splitFind(
sh.call(                   sh.getBalancerWindow(      sh.prototype               sh.startBalancer(
sh.constructor             sh.getRecentFailedRounds(  sh.removeRangeFromZone(    sh.status(
sh.disableAutoSplit(       sh.getRecentMigrations(    sh.removeShardFromZone(    sh.stopBalancer(
> sh.

4、集合存储信息

1、数据压缩比,对比 mysql 高很多
2、注意,命令查看会有延迟,执行totalSize()后,在插入数据,在执行totalSize(),在一小段时间内大小不变

– 查看集合存储信息
app> db.log.stats()
app> db.log.dataSize() //集合中数据的原始大小
app> db.log.totalIndexSize() //集合中索引数据的原始大小

# ***** 集合大小(索引+数据压缩存储之后的大小)单位字节 ,
# 将来数据量比较大的业务,需要关注存储空间占用
app> db.log.totalSize()

app> db.log.storageSize() //集合中数据压缩存储的大小

四、用户管理(运维重要)

1、介绍

mysql:用户、密码、对应的有哪些权限(增删改查)、访问IP限制

mongodb : 
1、用户、密码
2、权限( 类似Linux权限定义,Linux是rwx,mongodb 使用角色管理,定义可读可写rw,只读 r-,还有一种 root 权限,把一堆可能性的命令打包成一个角色,进行给用户授权,mysql 8.0 已经存在,比如给 insert 、update 打包给 名字叫 jerry 的角色,然后账户1 和  jerry 的角色绑定,然后账户2 和  jerry 的角色绑定 )、
3、验证库,登录时,必须明确指定验证库才能登录,相当于再一次加了一道锁,账户密码对了,不一定能的登录,还的看验证库。要求你是管理员,执行(mongo -u 用户名 -p 密码 admin)进入admin库。你是开发,执行(mongo -u 用户名 -p 密码 dev)进入dev库,增加了安全的能力。

注意:
验证库,建立用户时use到的库,在使用用户时,要加上验证库才能登陆。
对于管理员用户,必须在admin下创建.

1. 建用户时,use到的库,就是此用户的验证库Linu
2. 登录时,必须明确指定验证库才能登录
3. 通常,管理员用的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库
4. 如果直接登录到数据库,不进行use,默认的验证库是test,不是我们生产建议的
5、mongodb 在 3.4 版本之前,可以不加验证进行远程登录,在之后的版本,不加验证只能在本地

查看帮助文档

[root@db1 ~]# mongo -help

Authentication Options:
  -u [ --username ] arg               username for authentication
  -p [ --password ] arg               password for authentication
  --authenticationDatabase arg        user source (defaults to dbname)  # 验证库
  --authenticationMechanism arg       authentication mechanism
  --gssapiServiceName arg (=mongodb)  Service name to use when authenticating 
                                      using GSSAPI/Kerberos
  --gssapiHostName arg                Remote host name to use for purpose of 
                                      GSSAPI/Kerberos authentication

1、use 到某一个库(db命令查看在那个库),建立用户密码,登录的时候,就必须指定这个库 ( 登录不加库名,默认 test 库 ),尽量不用test库,容易被破解
2、mongodb 会建立两种,第一种 admin 管理员用户库,第二种是谁使用哪个库,就指定哪个库

2、创建管理员用户

默认第一次安装后,配置文件没开验证,直接使用 mongo 回车后,登录的是管理员用户,需要借助此账户创建

[root@db1 ~]# mongo
> use admin
switched to db admin
> db
admin
> db.createUser(
{
    user: "jerry",
    pwd: "root123",
    roles: [ { role: "root", db: "admin" } ]
}
)
# 回车后
Successfully added user: {
	"user" : "root",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
> 

# 注意user: user: "root", 可以不给root名字,用户名字可以随意起,我们是将用户名字跟mongo服
务账号root做了绑定的,root服务账号才是真的root,这样能增加安全性
解释:
db.createUser(
{
    user: "<name>",               # 用户名
    pwd: "<cleartext password>",  # 密码
    roles: [ { role: "<role>", db: "<database>" }  ]   # 权限又叫角色,角色类型是<role>,如果是root就是超级管理员.<database> 可以管理的库
}
)

<role>角色类型:
root , readWrite, read(only read)

<database> 可以管理的库:
如果是admin库,所有的管理都需要经过admin库
# 验证用户
> db.auth('root','root123')   # 此命令不会保存历史记录,所有通过上下翻越找不到
1                             # 1代表sueecss
> db.auth('root','root1234')
Error: Authentication failed.
0
> 

3、开启验证功能

[root@db1 ~]# tail -n 2 /opt/mongodb/conf/mongo.conf  # 最后两行添加
security:
  authorization: enabled

[root@db1 ~]# systemctl restart mongod.service

验证

[root@db1 ~]# mongo   # 直接输入mongo,输入命令后会有问题
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("547a17bc-774e-4cc0-a504-29c1a5c25e7a") }
MongoDB server version: 4.0.28
> 
> show databases;
> db
test
> use admin
switched to db admin
> show tables;
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
警告:无法运行listCollections,试图通过解析connectionStatus来近似集合名称


[root@db1 ~]# mongo -uroot -proot123  # 此方式是可以进入,走的是本地的登录,增加验证后,可以直接使用
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("b69aa6c8-c5b4-4739-920c-9bb52202c36f") }
> show databases;
admin   0.000GB
app     0.000GB
config  0.000GB
jerry   0.000GB
local   0.000GB
> use admin
switched to db admin
> show tables;
system.users
system.version
> 

[root@db1 ~]# mongo -uroot -proot123 192.168.86.5  # 这种的意思是,使用mongo命令,去连接192.168.86.5的mongo,虽然都在本机,在不加库的时候不好使
MongoDB shell version v4.0.28
connecting to: mongodb://192.168.86.5:27017/test?gssapiServiceName=mongodb
2022-10-25T03:41:48.087+0800 E QUERY    [js] Error: Authentication failed. :
connect@src/mongo/shell/mongo.js:356:17
@(connect):2:6
exception: connect failed
[root@db1 ~]# 

[root@db1 ~]#  mongo -uroot -proot123 192.168.86.5/admin
> show databases;
admin   0.000GB
app     0.000GB
config  0.000GB
jerry   0.000GB
local   0.000GB
> 
# 注意,管理员用户必须是roles: [ { role: "root", db: "admin" } ],如下
> use admin
switched to db admin
> db
admin
> db.createUser(
{
    user: "jerry",
    pwd: "root123",
    roles: [ { role: "root", db: "jerry" } ]
}
)
或者
> use jerry
switched to db jerry
> db.createUser(
... {
...     user: "jerry",
...     pwd: "root123",
...     roles: [ { role: "root", db: "jerry" } ]
... }
... )

提示 Error: couldn't add user: No role named root@jerry 


# 另外如果没有use到admin账户下,只要roles: [ { role: "root", db: "admin" },发现也可以管理,但是登陆的时候,需要执行你use的那个库,应该是执行db.createUser后,会将信息存在这个库,有没有权限看roles

> use jerry
switched to db jerry
> db
jerry
> db.createUser(
{
    user: "jerry4",
    pwd: "root123",
    roles: [ { role: "root", db: "admin" } ]
}
)
Successfully added user: {
	"user" : "jerry4",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
> show tables;
> db
jerry
> exit
bye
[root@db1 ~]#  mongo -ujerry4 -proot123 192.168.86.5/jerry
> show databases;
admin   0.000GB
app     0.000GB
config  0.000GB
jerry   0.000GB
local   0.000GB
> use admin
switched to db admin
> show tables;
system.users
system.version
> 

4、创建库管理用户(了解)

只能对库单独的这个库做操作( 查询状态),不能对表做操作

mongo -uroot -proot123 192.168.86.5/admin

use app

db.createUser(
{
user: "app1",
pwd: "app1",
roles: [ { role: "dbAdmin", db: "app" } ]
}
)

db.auth('app1','app1')

登录测试
mongo -uapp1 -papp1 192.168.86.5/app
> db
app
> show databases;
app  0.000GB
> db.stats()
{
	"db" : "app",
	"collections" : 2,
	"views" : 0,
	"objects" : 0,
	"avgObjSize" : 0,
	"dataSize" : 0,
	"storageSize" : 8192,
	"numExtents" : 0,
	"indexes" : 2,
	"indexSize" : 8192,
	"fsUsedSize" : 10772742144,
	"fsTotalSize" : 40778076160,
	"ok" : 1
}> show tables;
a
b
> db.a.find()
Error: error: {
	"ok" : 0,
	"errmsg" : "not authorized on app to execute command { find: \"a\", filter: {}, lsid: { id: UUID(\"97710038-f3e3-4f36-acd1-8a6937298248\") }, $db: \"app\" }",
	"code" : 13,
	"codeName" : "Unauthorized"
}

5、创建用户多库权限、只读只写

创建一个对 app 库的可读可写,对 test 库的只能读

> use app
> show tables;
biao1
biao2

> use test
> show tables;
biao1
biao2

> db.createUser(
{
    user: "app3",
    pwd: "app3",
    roles: [ { role: "readWrite", db: "app" },{ role: "read", db: "test" } ]
}
)
Successfully added user: {
	"user" : "app3",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "app"
		},
		{
			"role" : "read",
			"db" : "test"
		}
	]
}
> 

验证

[root@db1 ~]# mongo -uapp3 -papp3 192.168.86.5/test # 为什么是test库,因为最后在test下创建的
> show databases;
app   0.000GB
test  0.000GB
> use app
switched to db app
> show tables;
biao1
biao2
> db.biao1.insert({"name":"nihao"})
WriteResult({ "nInserted" : 1 })
> db.biao1.find()
{ "_id" : ObjectId("6356fa7bcc4502724f1a083a"), "name" : "nihao" }

> use test
switched to db test
> show tables;
biao1
biao2
> db.biao1.insert({"name":"nihao"})
WriteCommandError({
	"ok" : 0,
	"errmsg" : "not authorized on test to execute command { insert: \"biao1\", ordered: true, lsid: { id: UUID(\"25c3e0c2-01c4-41f9-bfb6-11ca9892b9d7\") }, $db: \"test\" }",
	"code" : 13,
	"codeName" : "Unauthorized"
})
> db.biao1.find()
> 

6、查询mongo下的用户信息

[root@db1 ~]# mongo -uroot -proot123 192.168.86.5/admin
> db
admin
> db.system.users.find().pretty()
{
	"_id" : "admin.root",   # 验证库.权限
	"userId" : UUID("8f56275e-0c78-4465-851f-389685ced05d"),
	"user" : "root",    # 用户名
	"db" : "admin",     # 密码
	},
	"roles" : [         # 权限
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
{
	"_id" : "admin.jerry",
	"userId" : UUID("9ad43321-97c0-4782-b453-933f

7、删除用户

使用 root 身份登录, use 到验证库

# 先查有哪些用户

[root@db1 ~]# mongo -uroot -proot123 192.168.86.5/admin
> db
admin
> db.system.users.find().pretty()
{
	"_id" : "app.app1",
	"userId" : UUID("ac3dd3bc-f308-4b7d-a6b1-3dcb65636e90"),
	"user" : "app1",
	"db" : "app",
	"credentials" : {
		"SCRAM-SHA-1" : {
			"iterationCount" : 100

# 删除
[root@db1 ~]# mongo -uroot -proot123 192.168.86.5/admin
> use app
switched to db app
> db.dropUser("app1")
true
> 

五、复制集RS集群架构(运维重要)

1、介绍

对比的是 mysql8.0以下主从,复制集很重要,因为 MongoDB 没有单机运行的,都是集群,最简单的集群是RS(复制集),跟主从不一样,跟 mysql 8.0的 mgr 很像

普通复制集架构

1、基本构成是最低3台, 1主2从的结构,3节点

2、自带互相监控 (心跳检测) 投票机制(Raft(MongoDB),还有一种是  Paxos(mysql MGR 用的是变种))
如果发生主库宕机,复制集内部会进行投票选举,选择一个新的主库替代原有主库对外提供服务。同时复制集会自动通知客户端程序,

4、主库已经发生切换了,应用就会连接到新的主库。mongodb没有VIP,怎么解决应用透明到的问题,会自动告知应用程序,主节点已经切换了,连接我的新主节点

5、宕机节点在修复好之后,自动加入集群

3、保证多节点数值一致性

一主一从一个 Arbiter(心跳检测和投票)

1、为什么需要3个节点,因为2节点以防选举失败而脑裂
2、如果多节点一主多从,主给从复制数据压力也大
3、考虑主压力的问题,主只给一个从做复制,另一个不做,这样压力就小了,另一个只是作为他们两个节点之间的选举作用,毕竟有一个宕机后,还有另一台,期间运维人员不可能不去进行修复,修复好后,自动加入集群作为从,所以出现以下架构,另一台只是作为投票

4、Arbiter 可以选择配置较低的设备

2、搭建集群(四节点使用多实例)

端口:28017   28018   28019   28020 

多套目录:      

mkdir -p /mongodb/28017/conf /mongodb/28017/data /mongodb/28017/log
mkdir -p /mongodb/28018/conf /mongodb/28018/data /mongodb/28018/log
mkdir -p /mongodb/28019/conf /mongodb/28019/data /mongodb/28019/log
mkdir -p /mongodb/28020/conf /mongodb/28020/data /mongodb/28020/log

多套配置文件:  

/mongodb/28017/conf/mongod.conf
/mongodb/28018/conf/mongod.conf
/mongodb/28019/conf/mongod.conf
/mongodb/28020/conf/mongod.conf

配置文件内容:  

cat > /mongodb/28017/conf/mongod.conf <<EOF
systemLog:
  destination: file
  path: /mongodb/28017/log/mongodb.log
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28017/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
processManagement:
  fork: true
net:
  bindIp: 192.168.86.5,127.0.0.1
  port: 28017
replication:
  oplogSizeMB: 2048
  replSetName: my_repl
EOF
解释:

# 引擎选择,默认是 wiredTiger,和innodb一样,有事务行级锁、自动故障恢复等。4.0 完全实现和mysql 一样
  #engine: wiredTiger     
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1   # 缓冲区大小,  相当于innodb跟buffer pool功能一样,内存区域,所有数据跟索引的缓冲


# 复制集专用的配置选项      
replication:            
  oplogSizeMB: 2048  # mysql 通过 mysqlbinlog实现主从复制,mongnDB 叫做 oploglog,而且做到了比mysql 高效,表来存储日志,而不是 mysql 落盘在导入SQL层,
                     # 所以同步极其快。但是他是定容集合,也就是说表的大小是有限制的,最多可以使用2g,  如果不设置,最大不超过总磁盘的5%。既然跟二进制有关,一定跟备份恢复有关
  replSetName: my_repl   # 复制集名字,随便起,但是主、从的名字一定要一致,配置文件定义好了,在生成集群的时候,起的这个名字也是这个
cp  /mongodb/28017/conf/mongod.conf  /mongodb/28018/conf/
cp  /mongodb/28017/conf/mongod.conf  /mongodb/28019/conf/
cp  /mongodb/28017/conf/mongod.conf  /mongodb/28020/conf/

sed 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i
sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i
sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i

启动多个实例备用:  

mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf

查看: 

[root@db1 /]# ps -ef |grep mongo
root      2166     1  1 05:54 ?        00:00:00 mongod -f /mongodb/28017/conf/mongod.conf
root      2199     1  2 05:54 ?        00:00:00 mongod -f /mongodb/28018/conf/mongod.conf
root      2232     1  2 05:54 ?        00:00:00 mongod -f /mongodb/28019/conf/mongod.conf
root      2265     1  4 05:54 ?        00:00:01 mongod -f /mongodb/28020/conf/mongod.conf
root      2297  1170  0 05:55 pts/1    00:00:00 grep --color=auto mongo
[root@db1 /]# 

3、配置普通复制集(重要)

第一步先定义config ,随意找那台设备,但一般情况下,配置那个机器,后台选择也会选择此节点为主

[root@db1 /]# mongo --port 28017 admin
> db
admin
> config = {_id: 'my_repl', members: [
                          {_id: 0, host: '192.168.86.5:28017'},
                          {_id: 1, host: '192.168.86.5:28018'},
                          {_id: 2, host: '192.168.86.5:28019'}]
          }
提示:
{
	"_id" : "my_repl",
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.86.5:28017"
		},
		{
			"_id" : 1,
			"host" : "192.168.86.5:28018"
		},
		{
			"_id" : 2,
			"host" : "192.168.86.5:28019"
		}
	]
}

解释:
一个配置文件config 
给三个成员变量起一个集群名字my_repl

在启动复制集

> rs.initiate(config)
{ "ok" : 1 }
my_repl:SECONDARY> # SECONDARY 代表次级,因为刚刚启动三个节点在PK,过一段时间会选择出谁是主,一般都是那个机器配置,那个为主
my_repl:PRIMARY>   # PRIMARY表是主
[root@db1 /]# mongo --port 28018 admin
my_repl:SECONDARY> 

4、故障演示

挡掉主节点

[root@db1 /]# mongod -f /mongodb/28017/conf/mongod.conf --shutdown

[root@db1 ~]# mongo --port 28018 admin
my_repl:SECONDARY> 
my_repl:PRIMARY> 

[root@db1 ~]# mongo --port 28019 admin
my_repl:SECONDARY>

启动被关掉的主节点,自动作为从库

[root@db1 /]# mongod -f /mongodb/28017/conf/mongod.conf

[root@db1 /]# mongo --port 28017 admin
my_repl:SECONDARY> 

6、查看复制集状态

my_repl:PRIMARY> rs.status();
{
	"set" : "my_repl",    # rs集群名字
	"date" : ISODate("2022-10-24T22:22:30.364Z"),
    ...............

	"members" : [   # 节点信息
		{
			"_id" : 0,
			"name" : "192.168.86.5:28017",  # 节点1
			"health" : 1,   # 健康状态
			"state" : 2,
			"stateStr" : "SECONDARY", # 从库还会主库
			"uptime" : 121,
			"optime" : {              # 相当于gtid的号码
				"ts" : Timestamp(1666650148, 1),
				"t" : NumberLong(2)
			},
			
		{
			"_id" : 1,
			"name" : "192.168.86.5:28018",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 1679,

7、复制集的监控

rs.status();    //查看整体复制集状态
rs.isMaster(); // 查看当前是否是主节点
rs.conf();   //查看复制集配置信息


my_repl:PRIMARY> rs.isMaster()
{
	"hosts" : [
		"192.168.86.5:28017",
		"192.168.86.5:28018",
		"192.168.86.5:28019"
	],
	"setName" : "my_repl",
	"setVersion" : 1,
	"ismaster" : true,
	"secondary" : false,
	"primary" : "192.168.86.5:28018",  主节点是谁
    "me" : "192.168.86.5:28018",  我是谁

my_repl:PRIMARY> rs.conf()
{
	"_id" : "my_repl",
	"version" : 1,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.86.5:28017",
			"arbiterOnly" : false, 代表是不是arbiter

8、添加删除节点

rs.remove("ip:port"); // 删除一个节点       在主上操作
rs.add("ip:port"); // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点

9、配置一主一从一 Arbiter(重要)

一个节点是无法同时在两个复制集以上存在的,mongodb 是不支持级联的。也没有多主的功能。不能参数多节点的复制。mysql 是支持的,比如节点可以作为另一个节点的从,可以作为其他节点的主。

9.1、从头搭建

1、取消刚刚搭建的 28017  28018  28019 主从关系
2、搭建过程跟普通复制集一样,区别是在config中其中一个节点声明Arbiter

mongo -port 28017 admin

config = {_id: 'my_repl', members: [
                          {_id: 0, host: '192.168.86.5:28017'},
                          {_id: 1, host: '192.168.86.5:28018'},
                          {_id: 2, host: '192.168.86.5:28019',"arbiterOnly":true}]
          }                
rs.initiate(config)

9.2 、将刚刚搭建的普通复制集,转成一主一从一Arbiter

思路:将想要添加Arbiter节点的从集群中删除,重新在添加为Arbiter

my_repl:PRIMARY> rs.remove("192.168.86.5:28019")
{
	"ok" : 1,   # 代表成功 
	"operationTime" : Timestamp(1666651545, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1666651545, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

my_repl:PRIMARY> rs.addArb("192.168.86.5:28019")
{
	"ok" : 1,
	"operationTime" : Timestamp(1666651620, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1666651620, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}


my_repl:PRIMARY> rs.conf()
		{
			"_id" : 2,
			"host" : "192.168.86.5:28019",
			"arbiterOnly" : true,  # 代表是arbiter

10、常见问题

主从复制后,从数据库默认不能读不能插入

1、主从复制后,从数据库默认不能读不能插入,必须需要执行rs.slaveOk(),此时当前的从数据库才能可读可写,其他从节点还是不能读不能插入,在主节点执行rs.slaveOk()也不会让从节点能读能写

my_repl:PRIMARY> use jerry
switched to db jerry
my_repl:PRIMARY> db.t1.insert({"id":101,"name":"nihao"})
WriteResult({ "nInserted" : 1 })
my_repl:PRIMARY> rs.conf()


my_repl:SECONDARY> show databases;
2022-10-25T08:48:15.220+0800 E QUERY    [js] Error: listDatabases failed:{
	"operationTime" : Timestamp(1666658878, 2),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1666658878, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:151:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1

my_repl:SECONDARY> rs.slaveOk()
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.

my_repl:SECONDARY> show databases;
admin   0.000GB
config  0.000GB
jerry   0.000GB
local   0.000GB
my_repl:SECONDARY> show databases;

2、当重启数据库后,或者删除子节点,重新加入,继续变成默认不能读不能写

3、如果就行能读

要想不用每次输入该命令,可以修改如下文件
[root@db1 ~]# find / -name .mongorc.js
/root/.mongorc.js
/home/mongod/.mongorc.js

在文件里面添加一行:rs.slaveOk();
一般这个文件都是空的,直接加上去。保存退出。之后退出mongo在进去就可以了.
[root@db1 ~]# cat /root/.mongorc.js 
rs.slaveOk();

重启mongodb

六、特殊从节点-延时从库

延时从库(slaveDelay):
mysql 有过滤、半同步、延时同步节点,mongodb也有延时从库
架构:一主、一从、一Arbiter、一个延时从库,解决逻辑损坏
mysql 是通过SQL线程实现的,mongodb也是。

隐藏节点概念:
隐藏节点中有 hidden:true  概念(不进行读写操作,业务上看不见他),priority : 0 概念(不参与选举、投票、权重是0),隐藏节点 搭配 延时从库,实现了延时从库加到集群中,不需要参与选举、投票等,只是为了做数据备份

1、环境

架构:28017 28018 为主从    28019 为 Arbiter   28020 为隐藏节点的延时从库

my_repl:PRIMARY> rs.conf()
{
	"_id" : "my_repl",
	"version" : 4,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "192.168.86.5:28017",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 1,
			"host" : "192.168.86.5:28018",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 2,
			"host" : "192.168.86.5:28019",
			"arbiterOnly" : true,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 0,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1
		},
		{
			"_id" : 3,
			"host" : "192.168.86.5:28020",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,               # hidden
			"priority" : 1,                 # priority
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),   # 延时从库
			"votes" : 1
		}
}
my_repl:PRIMARY> 

2、参数配置介绍

启动

cfg=rs.conf()                  # rs.conf()打印的信息,定义到cfg变量
cfg.members[2].priority=0      # 不进行选主功能,独立
cfg.members[2].hidden=true     # 藏起来不参与业务
cfg.members[2].slaveDelay=120  # 延时多久
rs.reconfig(cfg)               # 配置生效

取消

cfg=rs.conf() 
cfg.members[2].priority=1
cfg.members[2].hidden=false
cfg.members[2].slaveDelay=0
rs.reconfig(cfg) 

3、修改对应的参数,启动延时从库

# 注意,将192.168.86.5:28020加入到延时从库中,他的下标是03
my_repl:PRIMARY> rs.conf()      
		},
		{
			"_id" : 3,
			"host" : "192.168.86.5:28020",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : false,
			"priority" : 1,
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(0),
			"votes" : 1

my_repl:PRIMARY> cfg=rs.conf()
my_repl:PRIMARY> cfg.members[3].priority=0
0
my_repl:PRIMARY> cfg.members[3].hidden=true
true
my_repl:PRIMARY> cfg.members[3].slaveDelay=120
120
my_repl:PRIMARY> rs.reconfig(cfg)

my_repl:PRIMARY> rs.conf()
{
			"_id" : 3,
			"host" : "192.168.86.5:28020",
			"arbiterOnly" : false,
			"buildIndexes" : true,
			"hidden" : true,    # 从 false 变成 true
			"priority" : 0,     # 从 1 变成 0
			"tags" : {
				
			},
			"slaveDelay" : NumberLong(120), # 从 0 变成 120
			"votes" : 1

七、集群分片

1、介绍

分布式集群架构图,根据颜色,分为三大部分

蓝色部分Mongos,也称之为 router ,在 mysql 架构中,相当于Mycat角色(访问Mycat,Mycat 通过规则决定到底给那个库或者那个表,分库分表),所以所有的连接需要通过Mongos,由Mongos决定给谁,是给 Shard 1 还是 Shard 2。可以随意扩容多个节点

但本身 Mongos 是一个无状态的,没有脑子,他也不清楚来了给谁,甚至不知道后端有多少个节点。所以需要Config Servers来进行配合使用,可以说 Config Servers是 Mongos 秘书,一个插入数据,到达Mongos,Mongos 会问 Config Servers 有几个节点,应该怎么发。所以整个集群都在Config Servers,这个统一配置文件中。Mycat 使用 zookpeer 作为统一存储配置信息(比如路由规则)

绿色的就是分片,一个分片中包含一套主从,所以架构中既有高可用(每个shard中有复制集)、又有分布式分片功能(多个shard),每个Shard中的复制集可以存在Arbiter

思考:架构中什么最重要,Shard 数据最为重要,毕竟是数据。其次是 Config Servers 是配置的中心。所以 Mongodb 也是考虑到了此问题,故一般每个Shard 要做(replica set)复制集,Config Servers也要做复制集。一套复制集也必须要最低有三个节点(防止脑裂),而且不能存在Arbiter,必须独立的主跟从节点

2、规划

shard 节点:

sh1:38021-23    (1主两从,其中一个节点为arbiter,复制集名字sh1)
sh2:38024-26    (1主两从,其中一个节点为arbiter,复制集名字sh2)

configService节点:

38018-20    (1主两从,不支持Arbiter

mongos节点:

38017

生产最低规划:  物理机做多实例

3、环境搭建

搭建两组分片节点

目录创建:
mkdir -p /mongodb/38021/conf  /mongodb/38021/log  /mongodb/38021/data
mkdir -p /mongodb/38022/conf  /mongodb/38022/log  /mongodb/38022/data
mkdir -p /mongodb/38023/conf  /mongodb/38023/log  /mongodb/38023/data
mkdir -p /mongodb/38024/conf  /mongodb/38024/log  /mongodb/38024/data
mkdir -p /mongodb/38025/conf  /mongodb/38025/log  /mongodb/38025/data
mkdir -p /mongodb/38026/conf  /mongodb/38026/log  /mongodb/38026/data


修改配置文件:

sh1:

cat > /mongodb/38021/conf/mongodb.conf<<EOF 
systemLog:
  destination: file
  path: /mongodb/38021/log/mongodb.log   
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/38021/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  bindIp: 192.168.86.5,127.0.0.1
  port: 38021
replication:
  oplogSizeMB: 2048
  replSetName: sh1  # 复制集名字,自定义
sharding:           # sharding相关的
  clusterRole: shardsvr   # 在sharding集群中角色是shardsvr,固定不变的,必须个名字
processManagement: 
  fork: true
EOF
cp  /mongodb/38021/conf/mongodb.conf  /mongodb/38022/conf/
cp  /mongodb/38021/conf/mongodb.conf  /mongodb/38023/conf/
sed 's#38021#38022#g' /mongodb/38022/conf/mongodb.conf -i
sed 's#38021#38023#g' /mongodb/38023/conf/mongodb.conf -i


sh2:

cat > /mongodb/38024/conf/mongodb.conf<<EOF 
systemLog:
  destination: file
  path: /mongodb/38024/log/mongodb.log   
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/38024/data
  directoryPerDB: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  bindIp: 192.168.86.5,127.0.0.1
  port: 38024
replication:
  oplogSizeMB: 2048
  replSetName: sh2  # 复制集名字,自定义
sharding:
  clusterRole: shardsvr
processManagement: 
  fork: true
EOF

cp  /mongodb/38024/conf/mongodb.conf  /mongodb/38025/conf/
cp  /mongodb/38024/conf/mongodb.conf  /mongodb/38026/conf/
sed 's#38024#38025#g' /mongodb/38025/conf/mongodb.conf -i
sed 's#38024#38026#g' /mongodb/38026/conf/mongodb.conf -i


启动所有节点,并搭建复制集:

mongod -f  /mongodb/38021/conf/mongodb.conf 
mongod -f  /mongodb/38022/conf/mongodb.conf 
mongod -f  /mongodb/38023/conf/mongodb.conf 
mongod -f  /mongodb/38024/conf/mongodb.conf 
mongod -f  /mongodb/38025/conf/mongodb.conf 
mongod -f  /mongodb/38026/conf/mongodb.conf 

或者 for i in {21..26}; do mongod -f /mongodb/380$i/conf/mongodb.conf;
                        
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/Jerry00713/article/details/127487688
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2022-12-31 20:55:19
  • 阅读 ( 100 )
  • 分类:运维

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢