Mongodb是时下流行的NoSql数据库(MongoDB是一个基于分布式文件存储的数据库),它的存储方式是文档式存储,并不是Key-Value形式。
优势:
快速!(当然,这和具体的应用方式有关,通常来说,它比一般的关系型数据库快5位左右。)
很高的可扩展性�C轻轻松松就可实现PB级的存储(但是可能我们并不需要PB级的存储,10TB可能就够了)
他有一个很好的 replication 模式 (replica sets)
有很完善的Java API
他的存储格式是Json的,这对Java来说非常好处理,对javascirpt亦然。
运维起来非常方便,你不用专门为它安排一个管理员。
它有一个非常活跃的社区(我提出的一个bug在20分钟内就能得到修复。多谢Elliot)
他的版本控制非常清楚。
MongoDB 背后的公司(10gen)已经准备好了明天在 MongoDB 上面的投入的资金了。
劣势
应用经验缺乏,我们都没有相关NoSQL 产品的使用经验。
项目相对来说还比较新。
和以往的存储相比,数据的关系性操作不再存在。
版本历史
时间 |
版本 |
说明 |
编写者 |
2014-07-25 |
1.0 |
mondoDB主从和副本集群配置 |
csc |
2014-11-5 |
1.1 |
mondoDB主从和副本集群配置-修改 |
csc |
服务器资源有限,主从服务 都部署在一台服务器上面,开启不同的端口运行。
该集群优点:master 读写,slave 读 可以减轻master 的压力,数据做冗余备份
缺点: 主master挂了之后,服务不能自动切换到从slave,存在单点故障
mv mongodb-linux-x86_64-1.6.5.tgz /usr/local/
cd /usr/local/
tar -xvzf mongodb-linux-x86_64-1.6.5.tgz
cp -r mongodb-linux-x86_64-1.6.5 mongodb-01
mkdir -p /usr/local/mongodb-01/data/master
#/usr/local/mongodb-01/bin/mongod--dbpath=/usr/local/mongodb-01/data/master --port=10000--master --logpath=/usr/local/mongodb-01/data/mongodb.log --rest &
或者写入配置文档master.conf:
1. port = 27017
2. dbpath = /data/db
3. logpath = /var/log/mongodb.log
4. logappend = true
5. journal = true
6. pidfile = /var/run/mongodb.pid
7. fork = true
8. master = true
9.
10. 启动方式:./mongod -f master.conf
11.
12. 关闭方式
13. ./ mongod--shutdown -f master.conf
14.
15.
启动后测试是否正常运行:
#/usr/local/mongodb-01/bin/mongo 127.0.0.1:10000
MongoDB shell version: 1.6.5
connecting to: 127.0.0.1:10000/test
> show dbs;
admin
local
cp -r mongodb-linux-x86_64-1.6.5 mongodb-02
mkdir -p /usr/local/mongodb-01/data/slave
/usr/local/mongodb-02/bin/mongod--dbpath=/usr/local/mongodb-02/data/slave --port=10001--slave --source=localhost:10000 --logpath=/usr/local/mongodb-02/data/mongodb.log--rest
或者写入配置文档(slave.conf):
1. port=27017
2. dbpath = /data/db
3. logpath = /var/log/mongodb.log
4. logappend = true
5. journal = true
6. fork = true
7. slave = true
8. source = 10.11.20.140:27017
9.
10. 启动方式:./mongod -f master.conf
11.
启动后测试是否正常运行:
#/usr/local/mongodb-02/bin/mongo 127.0.0.1:10001
MongoDB shell version: 1.6.5
connecting to: 127.0.0.1:10001/test
> show dbs;
admin
local
登入 slave 创建表:
创建一个“myTest”的数据库,
先运行use myTest命令,之后就做一些操作(如:db.createCollection('user')),这样就可以创建一个名叫“myTest”的数据库。
在从服务上面创建数据库myTest;
/usr/local/mongodb-02/bin/mongo 127.0.0.1:10001
> use mytest
switched to db mytest
> db.createCollection('user')
{ "errmsg" : "not master", "ok" :0 }
报错信息显示该服务不是主服务,不能插入数据。
但是能查询数据:
admin
local
/usr/local/mongodb-01/bin/mongo 127.0.0.1:10000
> use mytest
switched to db mytest
> db.createCollection('user')
{ "ok" : 1 }
从服务器查询数据库,看是否该库同步过来。如果从服务器没有查询到该库,则检查服务的正确性。
> show dbs;
admin
local
myTest
test
> db.version();
1.6.5
{
"collections" : 3,
"objects" : 4,
"avgObjSize" : 51,
"dataSize" : 204,
"storageSize" : 16384,
"numExtents" : 3,
"indexes" : 1,
"indexSize" : 8192,
"fileSize" : 201326592,
"ok" : 1
}
> db.getMongo();
connection to 127.0.0.1:10000
> db.addUser('names');
{
"user" :"names",
"readOnly" : false,
"pwd" :"29cdbdd1255032d35e099aa7ebf8c3f9"
}
> show users;
{
"_id" :ObjectId("53d0bcfaafa6df02ce900daf"),
"user" :"names",
"readOnly" : false,
"pwd" :"29cdbdd1255032d35e099aa7ebf8c3f9"
}
db.test_1.find();
db.test_1.save({id:1});
我们通过使用“use new-databasename”的语法去使用一个新的数据库,注意,即使你的数据库还没建立起来,依然可以这样使用,因为mongodb会在真正插入了数据后,才会真正建立起来。
>use mkyongdb
switched to db mkyongdb
> show dbs
admin 0.03125GB
local (empty)
注意,在use mkyongdb后,mkyongdb实际上还没真正建立起来,只是表明目前是在使用mkyongdb了。
定义一个collection,名为“users”,然后插入数据,如下:
db.users.save({username:"mkyong"} )
db.users.find()
{ "_id" : ObjectId("4dbac7bfea37068bd0987573"),"username" : "mkyong" }
db.users.count();
1
show dbs
admin 0.03125GB
local (empty)
mkyongdb 0.03125GB
[root@test2 bin]# ./mongod --shutdown -f../data/slaver.conf
不推荐用kill方法杀掉进程
杀掉之后,如果要重启,请先删除掉 *.pid 文件
集群当中包含了多份数据,保证主节点挂掉了,备节点能继续提供数据服务,提供的前提就是数据需要和主节点一致。如下图:
Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。
默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做ReadPreference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。
仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。
介绍完了集群方案,那么现在就开始搭建了。
一般情况下不会把数据目录建立在mongodb的解压目录下,不过这里方便起见,就建在mongodb解压目录下吧。
[plain] viewplaincopy
10.10.148.130 mkdir -p /mongodb/data/master
10.10.148.131 mkdir -p /mongodb/data/slaver
10.10.148.132 mkdir -p /mongodb/data/arbiter
#三个目录分别对应主,备,仲裁节点
由于配置比较多,所以我们将配置写到文件里。
10.10.148.130 master 服务器配置:
[plain] viewplaincopy
#master.conf
dbpath=/mongodb/data/master
logpath=/mongodb/log/master.log
pidfilepath=/mongodb/master.pid
directoryperdb=true
logappend=true
replSet=testrs
bind_ip=10.10.148.130
port=27017
oplogSize=10000
fork=true
noprealloc=true
[plain] viewplaincopy
10.10.148.131slaver服务器配置:
#slaver.conf
dbpath=/mongodb/data/slaver
logpath=/mongodb/log/slaver.log
pidfilepath=/mongodb/slaver.pid
directoryperdb=true
logappend=true
replSet=testrs
bind_ip=10.10.148.131
port=27017
oplogSize=10000
fork=true
noprealloc=true
[plain] viewplaincopy
10.10.148.132arbiter服务器配置:
#arbiter.conf
dbpath=/mongodb/data/arbiter
logpath=/mongodb/log/arbiter.log
pidfilepath=/mongodb/arbiter.pid
directoryperdb=true
logappend=true
replSet=testrs
bind_ip=10.10.148.132
port=27017
oplogSize=10000
fork=true
noprealloc=true
参数解释:
dbpath:数据存放目录
logpath:日志存放路径
pidfilepath:进程文件,方便停止mongodb
directoryperdb:为每一个数据库按照数据库名建立文件夹存放
logappend:以追加的方式记录日志
replSet:replica set的名字
bind_ip:mongodb所绑定的ip地址
port:mongodb进程所使用的端口号,默认为27017
oplogSize:mongodb操作日志文件的最大大小。单位为Mb,默认为硬盘剩余空间的5%
fork:以后台方式运行进程
noprealloc:不预先分配存储
进入每个mongodb节点的bin目录下
[java] viewplaincopy
./monood -f master.conf
./mongod -f slaver.conf
./mongod -f arbiter.conf
注意配置文件的路径一定要保证正确,可以是相对路径也可以是绝对路径。r
如果要开启图形界面管理,则后面加上 --rest 启动
如:
./monood -f master.conf --rest
方法一: 添加节点时候,同时设置优先级,指定节点类型
可以通过客户端连接mongodb,也可以直接在三个节点中选择一个连接mongodb。
随便在一个终端进行,这个终端会被当成primary节点,但是需要把该终端的优先级设置高。
priority 数字越大,优先级越高
[plain] view plaincopy
./mongo 10.10.148.130:27017 #ip和port是某个节点的地址
>use admin
>cfg={ _id:"testrs", members:[ {_id:0,host:'10.10.148.130:27017',priority:2}, {_id:1,host:'10.10.148.131:27017',priority:1},
{_id:2,host:'10.10.148.132:27017',arbiterOnly:true}] };
>rs.initiate(cfg) #使配置生效
方法二:只添加节点,后期设置或者更改优先级和节点类型(不做介绍)
#####################以下可忽略#################################
版本为:2.4.3 按照上诉方法设置通过。
版本为:1.76 的设置过程会报错:
errmsg" : "couldn't parse cfgobject bad config for member[0] this version of mongod only supports priorities0 and 1",
配置的时候报错,只支持0跟1 的优先级
随便在一个终端进行,这个终端会被当成primary节点,因此连接的这个终端priority优先级要设置高,如果设置成 priority:0 ,primary节点会报错:
备注:Priority为0的节点永远不能成为主节点,所以设置Secondary-only节点只需要将其priority设置为0.
errmsg" : "couldn't initiate :initiation and reconfiguration of a replica set must be sent to a node that canbecome primary",
>cfg={_id:"testrs", members:[ {_id:0,host:'127.0.0.1:10001',priority:1},{_id:1,host:'127.0.0.1:10002',priority:0},{_id:2,host:'127.0.0.1:10003',arbiterOnly:true}] };
>rs.initiate(cfg) #使配置生效
############################################################################
cfg是可以任意的名字,当然最好不要是mongodb的关键字,conf,config都可以。最外层的_id表示replicaset的名字,members里包含的是所有节点的地址以及优先级。优先级最高的即成为主节点,即这里的10.10.148.130:27017。特别注意的是,对于仲裁节点,需要有个特别的配置――arbiterOnly:true。这个千万不能少了,不然主备模式就不能生效。
配置的生效时间根据不同的机器配置会有长有短,配置不错的话基本上十几秒内就能生效,有的配置需要一两分钟。如果生效了,执行rs.status()命令会看到如下信息:
[plain] viewplaincopy
{
"set" : "testrs",
"date" : ISODate("2013-01-05T02:44:43Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "10.10.148.130:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 200,
"optime" : Timestamp(1357285565000, 1),
"optimeDate" : ISODate("2013-01-04T07:46:05Z"),
"self" : true
},
{
"_id" : 1,
"name" : "10.10.148.131:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 200,
"optime" : Timestamp(1357285565000, 1),
"optimeDate" : ISODate("2013-01-04T07:46:05Z"),
"lastHeartbeat" : ISODate("2013-01-05T02:44:42Z"),
"pingMs" : 0
},
{
"_id" : 2,
"name" : "10.10.148.132:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 200,
"lastHeartbeat" : ISODate("2013-01-05T02:44:42Z"),
"pingMs" : 0
}
],
"ok" : 1
}
如果配置正在生效,其中会包含如下信息:
[plain] viewplaincopy
"stateStr" : "RECOVERING"
同时可以查看对应节点的日志,发现正在等待别的节点生效或者正在分配数据文件。
新增加一台服务加入到副本集中:
rs.add('192.168.200.25:27017')
加入后,执行,rs.status(); 显示:"errmsg" : "initial sync pending" 显示初始化过程中,一会儿后正常。
rs.remove('192.168.200.25:27017')
rs.status()
db.isMaster(); 查看主备(从)节点的状态
默认情况下,Secondary是不提供服务的,即不能读和写。会提示:
error: { '$err' : 'not master and slaveOk=false', 'code' : 13435 }
在特殊情况下需要读的话则需要执行命令:
rs.slaveOk() ,只对当前连接有效。
051.mmm:PRIMARY> use admin
052.switched to db admin
053.mmm:PRIMARY> db.shutdownServer()
054.
或者见目录一关闭mongodb
所有的Secondary都宕机、或则副本集中只剩下一个节点,则该节点只能为Secondary节点,也就意味着整个集群智能进行读操作而不能进行写操作,当其他的恢复时,之前的primary节点仍然是primary节点。
当某个节点宕机后重新启动该节点会有一段的时间(时间长短视集群的数据量和宕机时间而定)导致整个集群中所有节点都成为secondary而无法进行写操作(如果应用程序没有设置相应的ReadReference也可能不能进行读取操作)。
官方推荐的最小的副本集也应该具备一个primary节点和两个secondary节点,或者1个primary节点和1个secondary节点,加上一个arbiter节点。两个节点的副本集不具备真正的故障转移能力。
1 primary+2 secondary 或者1 primary + 1secondary + 1 arbiter
使用仲裁者主要是因为MongoDB副本集需要奇数成员,而又没有足够服务器的情况。
在服务器充足的情况下,不应该使用仲裁者节点
修改节点的优先级可以触发重新选举,这样可以人工指定主节点。
使用如下命令,在主节点登录,将192.168.1.3提升为Master。
rs.conf();
cfg=rs.conf();
cfg.members[0].priority=1
cfg.members[1].priority=1
cfg.members[2].priority=10
rs.reconfig(cfg);
需要注意的是,修改节点优先级需要登录Master节点运行。否则报错。
再次查看集群状态,可以看到192.168.1.3已经作为Master运行
副本集成员状态指的是rs.status()的stateStr字段
STARTUP:刚加入到复制集中,配置还未加载
STARTUP2:配置已加载完,初始化状态
RECOVERING:正在恢复,不适用读
ARBITER: 仲裁者
DOWN:节点不可到达
UNKNOWN:未获取其他节点状态而不知是什么状态,一般发生在只有两个成员的架构,脑裂
REMOVED:移除复制集
ROLLBACK:数据回滚,在回滚结束时,转移到RECOVERING或SECONDARY状态
FATAL:出错。查看日志grep“replSetFATAL”找出错原因,重新做同步
PRIMARY:主节点
SECONDARY:备份节点
如果Master节点读写压力过大,可以考虑读写分离的方案。
不过需要考虑一种场景,就是主服务器的写入压力非常的大,所以副本节点复制的写入压力同样很大。
这时副本节点如果读取压力也很大的话,根据MongoDB库级别读写锁的机制,
很可能复制写入程序拿不到写锁,从而导致副本节点与主节点有较大延迟。
如果进行读写分离,首先需要在副本节点声明其为slave,
然后在JAVA程序中进行设置
其中的ReadRreference有几种设置,
primary:默认参数,只从主节点上进行读取操作;
primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。
secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。
参考:
Mongodb自带了Web控制台,默认和数据服务一同开启。他的端口在Mongodb数据库服务器端口的基础上加1000,如果是默认的Mongodb数据服务端口(Which is 27017),则相应的Web端口为28017
我的控制台测试:
点击 Replica set status 报错:REST is not enableduse --rest turn on
解决方式:
启动的时候加上 --rest
./monood -f master.conf --rest
./mongod -f slaver.conf --rest
就可以看到Replica set status 界面了