【启动和停止MongoDB】
『从命令行启动』
执行mongod,启动MongoDB服务器。mongod有很多可配置的启动选项:在命令行运行mongod --help可以查看所有选项。一些主要选项如下:
· --dbpath
指定数据目录;默认值是/data/db/(Windows下是C:\data\db\)。每个mongod进程都需要独立的数据目录,所以要是有3个mongod实例,必须要有3个独立的数据目录。当mongod启动时,会在数据目录中创建mongod.lock文件,这个文件用于防止其他mongod进程使用该数据目录。如果使用同一个数据目录启动另一个MongoDB服务器,则会报错:
"Unable to acquire lock for lockfilepath: /data/db/mongod.lock."
· --port
指定服务器监听的端口号。默认值是27017,是个其他进程不怎么用的端口(除了其他mongod进程)。要是运行多个mongod进程,则要给每个制定不同的端口号。如果启动mongod时端口被占用,则报错:
"Address already in use for socket: 0.0.0.0:27017"
· --fork
以守护进程的方式运行MongoDB,创建服务器进程。
· --logpath
指定日志输出路径,而不是输出到命令行。如果对文件夹有写权限的话,系统会在文件不存在时创建它。它会将已有文件覆盖掉,清除所有原来的日志记录。如果想要保留原来的日志,还需要使用--logappend选项。
· --config
指定配置文件,加载命令行未指定的各种选项。
现在启动MongoDB服务器,让其作为守护进程监听5586号端口,并将所有输出记录到mongod.log:
$ ./mongod --port 5586 --fork --logpath mongodb.log
forked process: 45082
all output going to: mongodb.log
『配置文件』
指定配置文件可以用-f或者--config选项。
例如,运行mongod --config ~/.mongod.conf就会使用~/.mongod.conf作为配置文件。
# Start MongoDB as a daemon on port port =
fork = true # daemonize it! logpath = mongodb.log
这个配置文件指定的选项和我们之前使用常规的命令行参数时所使用的相同。它还体现了配置文件的一些特点:
· 以#开头的行是注释。
· 指定选项的语法就是“选项 = 值”的形式,其中选项是区分大小写的。
· 命令行中那些如--fork的开关选项,其值要设为true。
『停止MongoDB』
稳妥停止MongoDB最基本的方法是想MongoDB服务器发送一个SIGINT或者SIGTERM信号。如果服务器是作为前台进程运行在终端的,就直接按Ctrl+C。否则,就用kill命令发出信号。如果mongodb的PID是10014,就可以kill -2 10014(SIGINT)或者kill 10014(SIGTERM)。
当mongod收到SIGINT或者SIGTERM时,会稳妥退出。也就是说会等到当前运行的操作或者文件预分配完成(需要一些时间),关闭所有打开的连接,将缓存的数据刷新到磁盘,最后停止。
注:千万不要向运行中的MongoDB发送SIGKILL(kill -9)。这样会导致数据库直接关闭,上面讲到的步骤都将被忽略,这会使数据文件损毁。要是真的发生了不幸,一定要在启动备份之前修复数据库。
另一种稳妥的方式是使用shutdown命令,{"shutdown" : 1}。这是管理命令,要在admin数据库下使用。shell提供了辅助函数,来简化这一过程:
> use admin
switched to db admin
> db.shutdownServer();
server should be down...
【监控】
『使用管理接口』
默认情况下,启动mongod时还会启动一个(非常)基本的HTTP服务器,该服务器监听的端口号比主服务的端口号大1000。这个服务器提供了HTTP几口,可以查看MongoDB的一些基本信息。
启动服务器,然后再浏览器里面查看http://localhost:28017 ,就能看见管理接口。(如果用--port指定了端口,则要用比它大1000的端口号。)
在管理接口可以看到断言、锁、索引和复制等相关信息。还有些更加常见的信息,如日志前导、数据库命令列表。
要想利用好管理接口(比如,访问命令列表),需要用--rest选项开启REST支持。也可以在mongod时使用--nohttpinterface关闭管理接口。
『serverStatus』
使用serverStatus命令获取运行中的MongoDB服务器统计信息:
> db.runCommand({"serverStatus" : })
{
"version" : "1.5.3",
"uptime" : ,
"localtime" : "Thu Jun 10 2010 15:47:40 GMT-0400 (EDT)",
"globalLock" : {
"totalTime" : ,
"lockTime" : ,
"ratio" : 0.551083556358441
},
"mem" : {
"bits" : ,
"resident" : ,
"virtual" : ,
"supported" : true,
"mapped" :
},
"connections" : {
"current" : ,
"available" :
},
"extra_info" : {
"note" : "fields vary by platform"
},
"indexCounters" : {
"btree" : {
"accesses" : ,
"hits" : ,
"misses" : ,
"resets" : ,
"missRatio" :
}
},
"backgroundFlushing" : {
"flushes" : ,
"total_ms" : ,
"average_ms" : ,
"last_ms" : ,
"last_finished" : "Thu Jun 10 2010 15:46:54 GMT-0400 (EDT)"
},
"opcounters" : {
"insert" : ,
"query" : ,
"update" : ,
"delete" : ,
"getmore" : ,
"command" :
},
"asserts" : {
"reqular" : ,
"warning" : ,
"msg" : ,
"user" : ,
"rollovers" :
}
"ok" : true
}
注:原始的统计信息同样可以由HTTP接口以JSON的形式得到,位置在/_status(http://localhost:28017/_status)。
serverStatus显示了MongoDB内部的详细信息。比如当前服务器版本、运行时间(以秒计)、当前连接数。
"globalLock"的值表示全局写入锁占用了服务器多少时间(以微秒计)。"mem"包含服务器内存映射了多少数据,服务器进程的虚拟内存和常驻内存的占用情况(单位是MB)。"indexCounters"表示B树在磁盘检索("misses")和内存检索("hits")的次数。如果这个比值开始上升就要考虑添加内存了,否则系统性能会受到影响。"backgroundFlushing"表示后台做了多少次fsync以及用了多少时间。"opcounters"文档包含了主要操作的次数。"asserts"统计了断言的次数。
serverStatus结果中的所有计数都是在服务器启动时开始计数的,如果过大就会复位。当发生复位时,所有计数器都复位,"asserts"中的"rollovers"值会增加。
『mongostat』
mongostat相对于serverStatus,可以便捷地查看serverStatus的结果。
『第三方插件』
serverStatus和/_status URL的出现使得编写MongoDB的监控插件非常容易。
许多监控系统都有了MongoDB插件,例如Nagios、Munin、Ganglia、Cacti。
登录https://docs.mongodb.org/manual/administration/monitoring/ 查看与监控工具有关的文档。
【安全和认证】
MongoDB支持对单个连接的认证,几遍这个认证的权限模式很简陋。
『认证的基础知识』
每个MongoDB实例中的数据库都可以有许多用户。如果开启了安全性检查,则只有数据库认证用户才能执行读或者写操作。在认证的上下文中,MongoDB会将普通的数据作为admin数据库处理。admin数据库中的用户被视为超级用户(即管理员)。在认证之后,管理员可以读写所有数据库,执行特定的管理命令,如listdatabases和shutdown。
在开启安全检查之前,一定要至少有个管理员账号。例:开始时shell连接的是没有开启安全检查的服务器:
> use adminswitched to db admin
> db.addUser("root", "abcd")
{
"user" : "root",
"readOnly" : false,
"pwd" : "1a0f1c3aa1d592f490a2addc559383"
}
> use test
switched to db test
> db.addUser("test_user", "efgh")
{
"user" : "test_user",
"readOnly" : false,
"pwd" : "6076b96fc3fe6002c810268702646eec"
}
> db.addUser("read_only", "ijkl", true)
{
"user" : "read_only",
"readOnly" : true,
"pwd" : "f497e180c9dc0655292fee5893c162f1"
}
上面添加了管理员root,在test数据库添加了两个普通账号。其中一个有只读权限,不能对数据库写入。在shell中创建只读用户只要将addUser的第3个参数设为true就可以了。调用addUser必须有相应数据库的写权限。这里可以对所有数据库调用addUser,因为还没有开启安全检查。
注:addUser不仅能够添加新用户,还能修改用户口令或者只读状态。
现在重启服务器,这次加入--auth命令行选项,开启安全检查。之后通过shell重新连接数据库:
> use test
switched to db test
> db.test.find();
error: { "$err" : "unauthorized for db [test] lock type: -1" }
> db.auth("readOnly", "ijkl");
1
> db.test.find();
{ "_id" : ObjectId("4bb007f53e8424663ea6848a"), "x" : 1 }
> db.test.insert({"x" : 2});
unauthorized
> db.auth("test_user", "efgh");
1
> db.test.insert({"x" : 2});
> db.test.find();
{ "_id" : ObjectId("4bb007f53e8424663ea6848a"), "x" : 1 }
{ "_id" : ObjectId("4bb0088cbe17157d7b9cac07"), "x" : 2 }
> show dbs
assert: assert failed : listDatabases failed:{
"assertion" : "unauthorized for db [admin] lock type: 1",
"errmsg" : "db assertion failure",
"ok" : 0
}
> use admin
switched to db admin
> db.auth("root", "abcd");
1
> show dbs
admin
local
test
『认证的工作原理』
数据库的用户账号以文档的形式存储在system.users集合里面。稳当的结构是{"user" : username, "readOnly" : true, "pwd" : password hash}。password hash是根据用户名和密码生成的散列。
知道了用户信息是如何存储的以及存储位置后,有些日常管理任务执行起来就很轻松了。例如,在system.users集合中删掉用户账号文档,就可以删除用户:
> db.auth("test_user", "efgh");
1
> db.system.users.remove({"user" : "test_user"});
> db.auth("test_user", "efgh")
0
『其他安全考虑』
即使用了认证,MongoDB传输协议也是不加密的。如果需要加密,可以用SSH隧道或者类似的计数做客户端和服务器之间的加密。
建议将MongoDB服务器布置在防火墙后或者布置在只有应用服务器能访问的网络中。但要是MongoDB必须能被外面访问的话,建议使用--bindip选项,可以指定mongd绑定到的本地IP地址。例如,只能从本机应用服务器访问,可以运行"mongod --bindip localhost"。
默认情况下MongoDB会开启一个简单的HTTP服务器,便于查看运行、锁、复制等方面的信息。要是不想公开这些信息,就应该通过--nohttpinter-face将管理接口关闭。
最后,还可以用--noscripting完全禁止服务器端JavaScript的执行。
【备份和修复】
『数据文件备份』
MongoDB将所有数据都存放在数据目录下。默认目录是/data/db/(Windows下是C:\data\db\)。启动MongoDB的时候可以用--dbpath指定数据目录。不论数据目录在哪里,它都存放着MongoDB的所有数据。也就是说,要想备份MongoDB,只要简单创建数据目录中所有文件的副本就可以了。一种简单的方法是在服务器重启之前,复制目录作为备份。下面会介绍不需要停机的备份方式。
『mongodump和mongorestore』
mongodump对运行的MongoDB做查询,然后将所有查到的文档写入磁盘。
注:mongodump使用普通的查询机制,所以产生的备份不一定是服务器数据的实时快照。mongodump还带来一个问题,备份时的查询会对其他客户端的性能产生不利影响。
想大多数MongoDB的命令行工具一样,mongodump也可以通过运行--help选项查看所有选项:
$ ./mongodump --help
options:
-- help produce help message
-v [ --verbose ] be more verbose (include multiple times for more
verbosity e.g. -vvvvv)
-h [ --host ] arg mongo host to connect to ("left,right" for pairs)
-d [ --db ] arg database to use
-c [ --collection ] arg collection to use (some commands)
-u [ --username ] arg username
-p [ --password ] arg password
--dbpath arg directly access mongod data files in the given path,
instead of connecting to a mongod instance - needs
to lock the data directory, so cannot be used if a
mongod is currently accessing the same path
--directoryperdb if dbpath specified, each db is in a separate directory
-o [ --out ] arg (=dump) output directory
除了mongodump,MongoDB还提供了从备份中恢复数据的工具mongorestore。mongorestore获取mongodump的输出结果,并将备份的数据插入到运行的MongoDB实例中。下面的例子演示了从数据库test到backup目录的热备份,接着还调用了mongorestore:
$ ./mongodump -d test -o backup
connected to: 127.0.0.1
DATABASE: test to backup/test
test.x to backup/test/x.bson
1 objects
$ ./mongorestore -d foo --drop backup/test/
connected to: 127.0.0.1
backup/test/x.bson
going into namespace [foo.x]
dropping
1 objects
上面的例子中,-d制定了要恢复的数据库,这里是foo。这个选项可以将备份恢复到与原来不同名的数据库中。--drop代表在恢复前删除集合(若存在)。否则,数据就会与现有几何数据合并,可能会覆盖一些文档。
注:要获得完整的选项列表,可以运行mongorestore --help。
『fsync和锁』
虽然mongodump和mongorestore能不停机备份,但是却不能获取实时数据视图。
fsync命令会强制服务器将所有缓冲区写入磁盘。还可以选择上锁组织对数据库的进一步写入,直到释放锁为止。写入锁是让fsync在备份时发挥作用的关键。下面的例子展示了如何在shell中操作,牵制执行了fsync并获得了写入锁:
> use admin
switched to db admin
> db.runCommand({"fsync" : 1, "lock" : 1});
{
"info":"now locked against writes, use db.$cmd.sys.unlock.findOne( to unlock)", "ok" : 1
}
至此,数据目录的数据就是一致的,且为数据的实时快照。因为上了写入锁,可以安全地将数据目录副本用作备份。要是数据库运行在有快照功能的文件系统上时,比如LVM或者EBS,这个就很有用了,因为拍个数据库目录非常之快。
备份好了,就要解锁:
> db.$cmd.sys.unlock.findOne();
{ "ok" : 1, "info" : "unlock required" }
> db.currentOp();
{ "inprog" : [ ] }
运行currentOp是为了确保已经解锁了。(初次请求解锁会花点时间。)
有了fsync命令,就能非常灵活地备份,不用停掉服务器,也不用牺牲备份的实时特性。要付出的代价就是一些写入操作被暂时阻塞了。唯一不耽误读写还能保证实时快照的备份方式就是通过从服务器备份。
『从属备份』
在从服务器上进行备份:关停、转储和恢复工具或fsync命令。
在从服务器上备份时MongoDB推荐的备份方式。
『修复』
未能正常停止MongoDB后应该修复数据库。要是未正常停止,下次启动服务器备份时MongoDB会提示:
**************
old lock file: /data/db/mongod.lock probably means unclean shutdown recommend removing file and running --repair
see: http://dochub.mongodb.org/core/repair for more information
*************
修复所有数据库最简单的方法就是加上--repair:使用mongod --repair来启动服务器。
修复数据库的实际过程就是:将所有的文档导出然后马上倒入,忽略那些无效的文档。
注:修复数据库还能起到压缩数据的作用。限制的空间(比如删除体积较大的集合,或删除大量文档后腾出的空间)在修复后被重新回收。
修复运行中的服务器上的数据库,要在shell中国用repairDatabase。使用下列方法修复一下test数据库:
> use test
switched to db test
> db.repairDatabase()
{ "ok" : 1 }
要是不通过shell而是通过驱动程序,可以用repairDatabase来完成相同的事情:
{"repairDatebase" : 1}
修复损毁的数据是不得已时的最后一招。尽可能稳妥地停掉服务器,利用复制功能实现故障恢复,经常做备份,这才是最有效的管理数据的手段。