阅读 661

MongoDB 实战

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。——百度百科(懒得写概念了)

一.MongoDB 常用命令

1.1 数据库启动

命令行启动:

./mongod -dbpath /mongodb/db -logpath /mongodb/log/mongo.log -fork
复制代码

配置文件启动:

./mongod -f  /mongodb/mongo.conf
复制代码

数据库关闭:

1.直接kill 掉进程

> ps -ef|grep mongo
  501  6187   956   0  2:11下午 ttys001    0:36.65 /Users/kux_testMac/soft/mongodb/bin/mongod -f /Users/kux_testMac/soft/mongodb/mongo.conf
  501  6221  4299   0  2:11下午 ttys006    0:00.33 ./mongo
  501  8797  6232   0  4:19下午 ttys007    0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn mongo
kux_testMac@zyquan-2:~/soft/mongodb/bin|
> kill -9 6187
kux_testMac@zyquan-2:~/soft/mongodb/bin|
> 

复制代码

2.使用数据库命令: 注意只有root 角色的用户才可以执行db.shutdowbServer()

> db.shutdownServer()
2020-04-27T08:18:18.950+0000 I  NETWORK  [js] DBClientConnection failed to receive message from 127.0.0.1:27017 - HostUnreachable: Connection closed by peer
server should be down...
复制代码

1.2 配置文件

#日志文件位置:改为实际路径
logpath=/root/mongodb/logs/mongo.log
#数据库存储位置:改为实际路径
dbpath=/root/mongodb/data/
#以追加的方式写日志
logappend=true
#端口
port=27017
#是否以守护进程的方式运行
fork=true
#是否以认证方式运行
auth=true

# 启用定期记录CPU利用率和 I/O 等待
#cpu = true
# 详细记录输出
#verbose = true
# Inspect all client data for validity on receipt (useful for
# developing drivers)用于开发驱动程序时验证客户端请求
# objcheck = true
# Enable db quota management
# 启用数据库配额管理
# quota = true
# 设置oplog记录等级
# Set oplogging level where n is
#   0=off (default)
#   1=W
#   2=R
#   3=both
#   7=W+some reads
# diaglog=0
# Diagnostic/debugging option 动态调试项
# nocursors = true
# Ignore query hints 忽略查询提示
# nohints = true
# 禁用http界面,默认为localhost:28017
# nohttpinterface = true
# 关闭服务器端脚本,这将极大的限制功能
# Turns off server-side scripting.  This will result in greatly limited
# functionality
# noscripting = true
# 关闭扫描表,任何查询将会是扫描失败
# Turns off table scans.  Any query that would do a table scan fails.
# notablescan = true
# 关闭数据文件预分配
# Disable data file preallocation.
# noprealloc = true
# 为新数据库指定.ns文件的大小,单位:MB
# Specify .ns file size for new databases.
# nssize = 
# Replication Options 副本集选项
# in replicated mongo databases, specify the replica set name here
# replSet=setname
# maximum size in megabytes for replication operation log
# oplogSize=1024
# path to a key file storing authentication info for connections
# between replica set members
# 指定存储身份验证信息的密钥文件的路径
# keyFile=/path/to/keyfile
复制代码

1.3 数据库备份与恢复

假设数据库用户名/密码: admin / kux

备份数据库:

./mongodump --username admin --password kux --authenticationDatabase admin
复制代码

恢复数据库:

注意:E:/test 存放的是上一步备份的数据库文件

./mongorestore -h 127.0.0.1:27017 -u admin -p kux --authenticationDatabase admin -d test E:/test
复制代码

二. MongoDB 用户授权

2.1 MongoDB 刚刚安装好是不需要授权的可以用mongo 命令直接连接数据库

root@36ec95eccef3:/usr/bin# ./mongo
MongoDB shell version v4.2.6
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5918b349-a425-4cac-af01-e3cf68e584ad") }
MongoDB server version: 4.2.6
> 
复制代码

2.2 创建admin超级管理员用户

#customDate 为自定义数据,可有可无
#userAdminAnyDatabase 为用户角色
>use admin
db.createUser(  
  { 
     user: "admin",  
     pwd: "admin",  
     customDate:"xxx", // 自定义数据可有可无
     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] 
  }  
)  
复制代码

2.3 开启访问控制

开启访问控制在mongod 进程启动的时候加上--auth 选项或者在配置文件中加入auth=true。并且重新启动实例

./mongod -dbpath /mongodb/db -logpath /mongodb/log/mongo.log --auth
复制代码
#是否以认证方式运行
auth=true
复制代码

2.4 用户验证

可以在mongo shell登录的时候验证用户权限

root@36ec95eccef3:/usr/bin# ./mongo -u admin -p admin --authenticationDatabase admin
MongoDB shell version v4.2.6
connecting to: mongodb://127.0.0.1:27017/?authSource=admin&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("9f00cee6-d24d-49b0-9437-50a228d2ce38") }
MongoDB server version: 4.2.6
> use admin 
switched to db admin
> show users
{
	"_id" : "admin.admin",
	"userId" : UUID("6cbfae29-0a66-400e-a206-b065e11af182"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}
> 

复制代码

也可以在进入mongo shell 后使用db.auth 进行验证

> db.auth('admin', 'admin')
1
> show users
{
	"_id" : "admin.admin",
	"userId" : UUID("6cbfae29-0a66-400e-a206-b065e11af182"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}
> 
复制代码

2.5 创建普通用户

创建了一个普通用户user1, 另外创建了一个数据库eva。现在user1 对于数据库eva有dbOwner的权限

> db.createUser(
...  {
...    user: "user1",
...    pwd: "pwd1",
...    roles: [
...       { role: "dbOwner", db: "eva" }
...    ]
...  }
... )
Successfully added user: {
	"user" : "user1",
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "eva"
		}
	]
}
复制代码

可以在使用user1的账户访问数据eva, 我们可以测试一下。

root@36ec95eccef3:/usr/bin# ./mongo -u user1 -p pwd1 --authenticationDatabase eva
MongoDB shell version v4.2.6
connecting to: mongodb://127.0.0.1:27017/?authSource=eva&compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("1ebd017b-95d5-4688-b17d-42b3de454964") }
MongoDB server version: 4.2.6
> use eva
switched to db eva
> show dbs
> show users
{
   "_id" : "eva.user1",
   "userId" : UUID("f38602a6-4578-4c71-b1b1-1c48923946e6"),
   "user" : "user1",
   "db" : "eva",
   "roles" : [
   	{
   		"role" : "dbOwner",
   		"db" : "eva"
   	}
   ],
   "mechanisms" : [
   	"SCRAM-SHA-1",
   	"SCRAM-SHA-256"
   ]
}
> 
复制代码

Mongodb 创建的用户是放在一个个数据里边,比如admin, 或者自己建的数据库,具体在用户是建在哪个数据库,和db.createUser命令中的数据库无关。是最开始在控制台中use admin 还是use 自己数据有关。

Mongodb 中--authenticationDatabase也指用户的所在的数据库。

use admin
> db.createUser(
...  {
...    user: "pmtools",
...    pwd: "pwd1",
...    roles: [
...       { role: "dbOwner", db: "pmtools" }
...    ]
...  }
... )
复制代码

那授权的时候--authenticationDatabase用的数据库就是admin,但是他对数据库pmtools 有dbOwner 的权限

Mongodb的admin数据库是一个比较特别的数据库

2.6 其他用户操作

查看用户信息

> db.getUser("user1", { showPrivileges: true })
{
	"_id" : "eva.user1",
	"userId" : UUID("f38602a6-4578-4c71-b1b1-1c48923946e6"),
	"user" : "user1",
	"db" : "eva",
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	],
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "eva"
		}
	],
	"inheritedRoles" : [
		{
			"role" : "dbOwner",
			"db" : "eva"
		}
	],
	"inheritedPrivileges" : [
		{
			"resource" : {
				"db" : "eva",
				"collection" : ""
			},
			"actions" : [
				"bypassDocumentValidation",
				"changeCustomData",
				"changePassword",
				"changeStream",
				"collMod",
				"collStats",
				"compact",
				"convertToCapped",
				"createCollection",
				"createIndex",
				"createRole",
				"createUser",
				"dbHash",
				"dbStats",
				"dropCollection",
				"dropDatabase",
				"dropIndex",
				"dropRole",
				"dropUser",
				"emptycapped",
				"enableProfiler",
				"find",
				"grantRole",
				"insert",
				"killCursors",
				"listCollections",
				"listIndexes",
				"planCacheIndexFilter",
				"planCacheRead",
				"planCacheWrite",
				"reIndex",
				"remove",
				"renameCollectionSameDB",
				"revokeRole",
				"setAuthenticationRestriction",
				"storageDetails",
				"update",
				"validate",
				"viewRole",
				"viewUser"
			]
		},
		{
			"resource" : {
				"db" : "eva",
				"collection" : "system.js"
			},
			"actions" : [
				"changeStream",
				"collStats",
				"convertToCapped",
				"createCollection",
				"createIndex",
				"dbHash",
				"dbStats",
				"dropCollection",
				"dropIndex",
				"emptycapped",
				"find",
				"insert",
				"killCursors",
				"listCollections",
				"listIndexes",
				"planCacheRead",
				"remove",
				"renameCollectionSameDB",
				"update"
			]
		},
		{
			"resource" : {
				"db" : "eva",
				"collection" : "system.profile"
			},
			"actions" : [
				"changeStream",
				"collStats",
				"convertToCapped",
				"createCollection",
				"dbHash",
				"dbStats",
				"dropCollection",
				"find",
				"killCursors",
				"listCollections",
				"listIndexes",
				"planCacheRead"
			]
		}
	],
	"inheritedAuthenticationRestrictions" : [ ]
}
> 
复制代码

为用户添加角色, 注意要使用超级管理员账号操作

> db.grantRolesToUser("user1", [{role: "readWrite", db: "test"}])
> show users
{
	"_id" : "admin.admin",
	"userId" : UUID("6cbfae29-0a66-400e-a206-b065e11af182"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}
{
	"_id" : "admin.user1",
	"userId" : UUID("22d5e21c-1870-4ebd-9b79-28ec5ee1a538"),
	"user" : "user1",
	"db" : "admin",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "test"
		},
		{
			"role" : "dbOwner",
			"db" : "eva"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}
> 
复制代码

更新用户信息

>  db.updateUser('user1',{roles: [{role: "dbOwner", db: "eva"}]})
> show users
{
	"_id" : "admin.admin",
	"userId" : UUID("6cbfae29-0a66-400e-a206-b065e11af182"),
	"user" : "admin",
	"db" : "admin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}
{
	"_id" : "admin.user1",
	"userId" : UUID("22d5e21c-1870-4ebd-9b79-28ec5ee1a538"),
	"user" : "user1",
	"db" : "admin",
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "eva"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}
> 
复制代码
> db.runCommand(
    {
        updateUser: "user1",
        roles: [
            { role: "dbOwner", db: "eva" },
        ]
    }
)
复制代码

收回用户角色

> use admin
> db.revokeRolesFromUser(
    "user1",
    [
        { role: "read", db: "test" }
    ]
)
复制代码
> use admin
> db.runCommand(
    {
        revokeRolesFromUser: "user1",
        roles:
            [
                { role: "read", db: "test" }
            ]
    }
)
复制代码

更改用户密码

> use admin
> db.changeUserPassword("user1", "pwd2")
复制代码

删除用户

> use admin
> db.dropUser("user1")
复制代码
> use admin
> db.runCommand({ dropUser: "dbabd_user" })
复制代码

2.7 MongoDB 内置角色

角色分类角色名称角色描述
数据库用户read允许用户读取指定数据库
数据库用户readWrite允许用户读写指定数据库
数据库管理员dbAdmin允许用户进行索引创建、删除,查看统计或访问system.profile,但没有角色和用户管理的权限;
数据库管理员userAdmin提供了在当前数据库中创建和修改角色和用户的能力;
数据库管理员dbOwner提供对数据库执行任何操作的能力。这个角色组合了readWrite、dbAdmin和userAdmin角色授权的特权;
集群管理角色hostManager提供监视和管理服务器的能力
集群管理角色clusterManager在集群上提供管理和监视操作。可以访问配置和本地数据库,这些数据库分别用于分片和复制;
集群管理角色clusterMonitor提供对监控工具的只读访问
集群管理角色clusterAdmin提供最强大的集群管理访问(副本集、分片、主从等)。组合了clusterManager、clusterMonitor和hostManager角色的能力,还提供了dropDatabase操作
备份恢复角色backup提供备份数据所需的能力
备份恢复角色restore提供使用mongorestore恢复数据的能力;
所有数据库角色readAnyDatabase只在admin数据库中可用,赋予用户所有数据库的读权限
所有数据库角色readWriteAnyDatabase只在admin数据库中可用,赋予用户所有数据库的读写权限
所有数据库角色userAdminAnyDatabase只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
所有数据库角色dbAdminAnyDataBase只在admin数据库中可用,赋予用户所有数据库的adAdmin权限
超级用户角色root超级权限,只能针对admin库;
内部角色__system提供对数据库中任何对象的任何操作的特权

2.8 mongodb 自定义角色

一般情况下mongodb 内置角色是够用的,当内置角色不满足需求的时候可以使用db.createRole()方法来自定义角色。

在创建角色时,必须明确Role的四个特性:

  • Scope:角色作用的范围,创建在Admin中的角色,能够在其他DB中使用;在其他DB中创建的角色,只能在当前DB中使用;
  • Resource:角色控制的资源,表示授予在该资源上执行特定操作的权限;
  • Privilege Actions:定义了User能够在资源上执行的操作,系统定义Action是:Privilege Actions
  • Inherit:角色能够继承其他角色权限

注意的是: 在admin 数据库中创建的角色,Scope是全局的,能够在admin,其他DB和集群中使用,并且能够继承其他DB的Role;而在非admin中创建的角色,Scope是当前数据库,只能在当前DB中使用,只能继承当前数据库的角色。

三. 如何使用docker 运行MongoDB

3.1.docker 的安装

具体安装方法www.runoob.com/docker/maco…

高速下载地址:get.daocloud.io/

安装后修改docker 下载源为国内的地址

安装成功后查看docker 版本

⇒  docker --version
Docker version 19.03.5, build 633a0ea
复制代码

3.2 下载mongo 镜像

首先搜索mongo 镜像:

> docker search mongo
NAME   DESCRIPTION                                     STARS   OFFICIAL            AUTOMATED
mongo  MongoDB document databases provide high avai…   6804    [OK]                
.
.
.
复制代码

其中第一个mongo 就是官方的mongo镜像

> docker pull mongo
复制代码

查看下载的镜像:

⇒  docker image ls 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mongo               latest              3f3daf863757        4 days ago          388MB
ubuntu              latest              549b9b86cb8d        4 months ago        64.2MB
hello-world         latest              fce289e99eb9        16 months ago       1.84kB
复制代码

3.3 运行容器

最简单的一条命令

#--name 指的容器的名称
# -p 27017:27107 对应的是本机端口:容器端口的映射
# -d 以守护进程运行
# mongo 是对应的mongo容器
⇒  docker run --name mymongo -p 27017:27017 -d mongo
复制代码

查看对应的镜像

⇒  docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
dac2ae3b1c4a        mongo               "docker-entrypoint.s…"   28 seconds ago      Up 27 seconds       0.0.0.0:27017->27017/tcp   mymongo
复制代码

开启授权模式,修改容器内运行端口号:

docker run --name mymongo -p 27017:27018 -d mongo --auth --port=27018
复制代码

停止容器

⇒  docker stop mymongo
mymongo
复制代码

删除容器

⇒  docker rm mymongo
mymongo
复制代码

四.MongoDB 副本集(Replica Sets)

4.1 why not 主从复制(master-slave)

主从复制是MongoDB最常用的复制方式,也是一个简单的数据库同步备份的集群技术,这种方式很灵活.可用于备份,故障恢复,读扩展等。最基本的设置方式就是建立一个主节点和一个或多个从节点,每个从节点要知道主节点的地址。采用双机备份后主节点挂掉了后需要手动选择一个从节点接替主机继续服务。所以主从复制不适合生产模式,MongoDB 从3.2 版本以后就移除了主从复制。

副本集已经在大多数场合下替代了主从复制。副本集除了提供主从复制的所有功能之外,还更适合生产使用。

4.2. 副本集原理

副本集是一组维护相同数据集的mongod实例。一个副本集包含几个数据承载节点和一个仲裁器节点(可选)。在数据承载节点中,只有一个成员被视为主要节点,而其他节点则被视为次要节点。

副本集Master故障的时候,副本集可以自动投票,选举出新的Master,并引导其余的Slave服务器连接新的Master,而这个过程对于应用是透明的。可以说MongoDB的副本集是自带故障转移功能的主从复制。

也可以配置一个额外的仲裁节点

4.3 配置副本集

1 启动三个mongo服务(也可以通过配置文件来启动)

# dbpath: 数据库存放地址, --port 端口号, --fork后台运行 --syslog 使用系统日志, replSet副本集名称为kux。
mongod --dbpath=../db1 --port=27018 --fork --syslog --replSet=kux
mongod --dbpath=../db2 --port=27019 --fork --syslog --replSet=kux
mongod --dbpath=../db3 --port=27020 --fork --syslog --replSet=kux
复制代码

我们预设端口为27018端口的服务是主节点,27019的是从节点,27020是仲裁节点

使用shell 登录27018

 mongo localhost:27018
复制代码

2.初始化副本集/设置本机为主节点

> rs.initiate()
{
	"ok" : 0,
	"errmsg" : "This node was not started with the replSet option",
	"code" : 76,
	"codeName" : "NoReplicationEnabled"
}
> 
复制代码

在shell 中回车几次,发现由SECONDARY变为PRIMARY节点

kux:SECONDARY> 
kux:PRIMARY> 
kux:PRIMARY> 
kux:PRIMARY> 
复制代码

也可以查看当前配置

 kux:PRIMARY> rs.conf()
{
	"_id" : "kux",
	"version" : 1,
	"protocolVersion" : NumberLong(1),
	"writeConcernMajorityJournalDefault" : true,
	"members" : [
		{
			"_id" : 0,
			"host" : "localhost:27018",
			"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("5eaa3720074889fad47be807")
	}
}
kux:PRIMARY> 
复制代码
  1. 添加27019为从节点
kux:PRIMARY> rs.add('localhost:27019')
{
	"ok" : 1,
	"operationTime" : Timestamp(1588213805, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1588213805, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
kux:PRIMARY> 
复制代码

4.添加27020为仲裁节点

kux:PRIMARY> rs.addArb('localhost:27020')
{
	"ok" : 1,
	"operationTime" : Timestamp(1588213864, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1588213864, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
复制代码

查看现在的副本集状态

kux:PRIMARY> rs.status()
{
	"set" : "kux",
	"date" : ISODate("2020-04-30T02:31:32.801Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncingTo" : "",
	"syncSourceHost" : "",
	"syncSourceId" : -1,
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1588213888, 1),
			"t" : NumberLong(1)
		},
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1588213888, 1),
			"t" : NumberLong(1)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1588213888, 1),
			"t" : NumberLong(1)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1588213888, 1),
			"t" : NumberLong(1)
		}
	},
	"lastStableCheckpointTimestamp" : Timestamp(1588213838, 1),
	"members" : [
		{
			"_id" : 0,
			"name" : "localhost:27018",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 457,
			"optime" : {
				"ts" : Timestamp(1588213888, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-04-30T02:31:28Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1588213536, 2),
			"electionDate" : ISODate("2020-04-30T02:25:36Z"),
			"configVersion" : 3,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 1,
			"name" : "localhost:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 87,
			"optime" : {
				"ts" : Timestamp(1588213888, 1),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1588213888, 1),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2020-04-30T02:31:28Z"),
			"optimeDurableDate" : ISODate("2020-04-30T02:31:28Z"),
			"lastHeartbeat" : ISODate("2020-04-30T02:31:32.160Z"),
			"lastHeartbeatRecv" : ISODate("2020-04-30T02:31:32.160Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "localhost:27018",
			"syncSourceHost" : "localhost:27018",
			"syncSourceId" : 0,
			"infoMessage" : "",
			"configVersion" : 3
		},
		{
			"_id" : 2,
			"name" : "localhost:27020",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 28,
			"lastHeartbeat" : ISODate("2020-04-30T02:31:32.160Z"),
			"lastHeartbeatRecv" : ISODate("2020-04-30T02:31:32.243Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 3
		}
	],
	"ok" : 1,
	"operationTime" : Timestamp(1588213888, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1588213888, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
kux:PRIMARY> 
复制代码

5.验证副本集

首先在主库上建一个test数据库

kux:PRIMARY> use test
switched to db test
kux:PRIMARY> db.test.insert({name: 'zyquan', phonenumber: '1866579xxxx'})
WriteResult({ "nInserted" : 1 })
kux:PRIMARY> db.test.find()
{ "_id" : ObjectId("5eaa3965e5c7a96472a041ce"), "name" : "zyquan", "phonenumber" : "1866579xxxx" }
kux:PRIMARY> 
复制代码

然后杀掉主库进程, mongo 连接localhost:27019 我们发现之前的从库27019已经变为主库,并且test数据库已同步过来了

⇒  ps -ef|grep mongod
  501  2100     1   0 10:23上午 ??         0:03.27 mongod --dbpath=../db1 --port=27018 --fork --syslog --replSet=kux
  501  2125     1   0 10:24上午 ??         0:03.09 mongod --dbpath=../db2 --port=27019 --fork --syslog --replSet=kux
  501  2129     1   0 10:24上午 ??         0:02.42 mongod --dbpath=../db3 --port=27020 --fork --syslog --replSet=kux
  501  2243  2208   0 10:36上午 ttys000    0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn mongod
  501  1514   470   0 10:03上午 ttys008    0:10.27 /Users/kux_testMac/soft/mongodb/bin/mongod -f /Users/kux_testMac/soft/mongodb/mongo.conf
kux_testMac@zyquan-2:~/soft/mongodb/bin|
⇒  kill -9 2100
⇒  mongo localhost:27019
kux:PRIMARY> db.test.find()
{ "_id" : ObjectId("5eaa3965e5c7a96472a041ce"), "name" : "zyquan", "phonenumber" : "1866579xxxx" }
kux:PRIMARY> 
复制代码

4.4 副本集授权验证

4.4.1 keyfile 认证

1.1 要求

(1)通过密钥文件进行身份验证时,副本集中的每个mongo实例都使用密钥文件的内容作为与其他成员进行身份验证的共享密码。只有拥有正确密钥文件的Mongod实例才能加入副本集。

(2)密钥文件的内容必须在6到1024个字符之间,并且对于副本集的所有成员必须是相同的。

1.2 创建

可以使用选择的任何方法生成密钥文件。例如,以下操作用于openssl生成用于密钥文件。

openssl rand -base64 756 > ./keyfile
复制代码

主要:key的长度必须是6-1024的base64字符,unix下必须相同组权限,windows下不需要。

1.3 更改权限

chmod 600 ./keyfile

1.4 将密钥文件复制到托管副本集成员的每个服务器上。确保运行mongod实例的用户是该文件的所有者,并且可以访问密钥文件。

4.4.2 主库中新建管理员用户

kux:PRIMARY> use admin
switched to db admin
kux:PRIMARY> db.createUser(  
...   { 
...      user: "admin",  
...      pwd: "admin",  
...      roles: [ { role: "root", db: "admin" } ] 
...   }  
... )
Successfully added user: {
	"user" : "admin",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
kux:PRIMARY> 
复制代码

4.4.3 重新使用auth 方式启动三个数据库

kill 掉原来的三个进程,然后重启启动以下服务

mongod --dbpath=../db1 --port=27018 --fork --syslog --replSet=kux --keyFile=../keyfile --auth
mongod --dbpath=../db2 --port=27019 --fork --syslog --replSet=kux --keyFile=../keyfile --auth
mongod --dbpath=../db3 --port=27020 --fork --syslog --replSet=kux --keyFile=../keyfile --auth
复制代码

4.4.4 测试

连接主库,使用 db.auth('admin', 'admin')后可查看数据库

⇒  mongo localhost:27018
MongoDB shell version v4.0.11
connecting to: mongodb://localhost:27018/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("cc18f704-fe07-465f-b0a8-91bd8b440086") }
MongoDB server version: 4.0.11
kux:PRIMARY> use admin
switched to db admin
kux:PRIMARY> show dbs
kux:PRIMARY> db.auth('admin', 'admin')
1
kux:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
kux:PRIMARY> 
复制代码

杀掉主库进行,连接从库, 发现从库已经自动变为主库,我们执行同样的操作

⇒  mongo localhost:27019
MongoDB shell version v4.0.11
connecting to: mongodb://localhost:27019/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f86278d5-9c9b-485e-a4e2-8e24a0b9257e") }
MongoDB server version: 4.0.11
kux:PRIMARY> use admin
switched to db admin
kux:PRIMARY> show dbs
kux:PRIMARY> db.auth('admin', 'admin')
1
kux:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
kux:PRIMARY> 
复制代码

五. 参考文档

  1. mongoing.com/docs/introd…

  2. www.cnblogs.com/dbabd/p/108…

  3. cloud.tencent.com/developer/a…

  4. 官方文档

  5. mongoing.com/docs/core/s…

  6. www.ibm.com/developerwo…

文章分类
后端
文章标签