MongoDB 集群配置笔记

MongoDB 集群配置笔记

配置一个含有主从机制、自动分片、去中心化的MongoDB集群

一、配置文件说明

必备的配置项知晓,在命令行启动时只需要指定配置文件地址即可,如:

mongod -port=27017 -f /path/db/conf/mongodb.conf

用这种方式可以减少因命令行启动时参数缺失导致的问题,常用的参数都需要写入配置文件,详细的配置项如下表示:

1.基础参数表

参数名默认值备注
dbpath/[path]数据库路径,不指定则默认在/data/db
verbosefalse是否打印详细记录到logpath中,如要启动需指定vvvv参数。默认false
vvvvtrue日志级别,vv~vvvvv,v越多越详细
port27017端口,推荐写到命令行
bind_ip127.0.0.1绑定的IP,非此IP不可访问。多个用,分隔。绑定的地址并不是客户端的IP而是MongoDB所在的服务器的IP。
maxConns1000000最大连接数,具体值取决于系统和mongodb版本。
objchecktrue2.4版后默认为true,开启时保证客户端插入到库中的数据都是有效的,但会降低性能
noobjcheckfalse与objcheck互斥,明示关闭对象校验
logappendtruetrue表示追加,否则为覆盖
syslogtrue输出到主机的syslog系统而非logpath的路径。syslog与logpath不能一起用
pidfilepath/[path]指定PID文件位置
keyFile/[path]身份验证的密钥信息文件
forktrue后台运行,默认true
authfalse开启身份验证,启动时应增加账号、密码、目标库。如:mongo -utest -ppwd test,表示test用户用pwd密码登录test库。默认false
noauthtrue不认证用户
cpufalsetrue会强制每4秒记录一次CPU利用率和IO等待并写到日志
dbpath/[path]指定数据库位置,必要项
dialog0输出错误日志到dialog.*文件,0=关闭、1=写操作、2=读操作、3=读写、7=写+部分读
directoryperdbfalse如果开启则将数据存到不同的磁盘上以提高读写速度,需要在第一次启动前就要确认此值。否则一旦改变会导致数据丢失(改回去可恢复)。
journal64bit=true,32bit=false是否启用确保一致性的操作日志
nojournaltrue关闭操作日志,64位系统需要强制开启
journalCommitInterval100写刷新间隔,默认100毫秒。数值越小越影响IO,取值范围2-300.
ipv6false开启ipv6支持,默认false
jsonpfalse是否允许jsonp方位http接口
nohttpinterfacefalse是否禁止http接口,即28017端口服务。默认比port大1000
nopreallocfalse如果是写频繁的系统开启的话会提升性能。开启时会在后台提前分配一定空间(0填充)来降低动态分配导致的低效率问题,但启动时会慢点。
noscriptingfalse关闭脚本引擎,默认false
notablescanfalse禁止全表扫描,开启时会提示”table scans not allow”
nssize16块大小,16M(默认)-2G
profile0数据库分析等级。0=关、1=慢操作、2=所有操作
slowms200慢查询的时间,默认200ms
quotafalse是否限制库文件数
quotaFiles8quota开启时,此值表示最大库文件数
restfalse开启RESTful API。开启时将启用一个比port大1000端口的服务,可以查询数据。
repairfalse默认false,修复数据库。此值应该在命令行明示,修复是需要关闭journal。
repairpath_tmp修复路径,默认在dbpath下
smallfilesfalse启用小文件模式,开启时最大为512M的块文件。太小会影响IO。默认false
sysinfofalse开启时启动mongod会显示系统信息而不是启动mongodb,应该在命令行用
traceExceptionsfalse启动内部诊断,默认false
quietfalse安静模式,命令行用。默认false

2.复制项(Replication)

参数名默认值备注
replSet命令行参数,启用时表示要复制副本集。副本名[/主机地址:端口]
fastsyncfalse副本集下设置true将通过快照同步
replIndexPrefetchall默认all、none、id_only,只能在副本集(replSet)中使用。默认情况下,secondary副本集的成员将加载所有索引到内存中(从OPLOG之前的操作有关的)。您可以修改此行为,使secondary只会加载_id索引。指定id或none,防止mongod的任何索引加载到内存。

3.主从复制(Replica set options)

参数名默认值备注
mastertrue表示此节点为master,应该命令行用
slavetrue表示此节点为slave,应该在命令行用,需要指定source
sourcehost:port从节点是,表示其主节点,即从此节点复制数据
onlyxxx只复制此指定数据库,默认空
slavedelay0用于从库,指定其与主库复制数据的间隔,秒计。默认0
autoresyncfalse从库配置,true表示自动同步,如落后主超过10秒则强制同步。

4.分片(Shard options)

参数名默认值备注
configsvrfalse表示此节点为配置库,默认端口27019,默认目录/data/configdb。应该在命令行使用
shardsvrfalse表示为分片节点,默认端口27018

二、主从配置流程(Master & Slave)

主从配置有如下优点:

大数据量,可以通过廉价服务器存储大量的数据,轻松摆脱传统mysql单表存储量级限制。

高扩展性,Nosql去掉了关系数据库的关系型特性,很容易横向扩展,摆脱了以往老是纵向扩展的诟病。

高性能,Nosql通过简单的key-value方式获取数据,非常快速。还有NoSQL的Cache是记录级的,是一种细粒度的Cache,所以NoSQL在这个层面上来说就要性能高很多。

灵活的数据模型,NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。

高可用,NoSQL在不太影响性能的情况,就可以方便的实现高可用的架构。比如mongodb通过mongos、mongo分片就可以快速配置出高可用配置。

此处在明文写到命令行参数,这样便于确认进程。假设目录放到了 /data/db/ 下

  1. 启动进程
# master的mongod.conf配置
master=true
logpath=/data/db/mongodbMaster/logs/mongod.log
logappend=true
fork=true
port=27017
dbpath=/data/db/mongodbMaster/data/
pidfilepath=/data/db/mongodbMaster/conf/mongod.pid
bind_ip=127.0.0.1
noauth=true
directoryperdb=true
# 主节点增加master参数
mongod -f /data/db/mongodbMaster/conf/mongod.conf --master  --port=27017
# slave的mongod.conf配置
slave=true
source=127.0.0.1:27017
logpath=/data/db/mongodbSlave/logs/mongod.log
logappend=true
fork=true
port=27018
dbpath=/data/db/mongodbMaster/data/
pidfilepath=/data/db/mongodbSlave/conf/mongod.pid
bind_ip=127.0.0.1
noauth=true
directoryperdb=true
# slave 增加slave参数外,还需要指定source
mongod -f /data/db/mongodbSlave/conf/mongod.conf --slave --source 127.0.0.1:27017

登录到slave后输入 db.printReplicationInfo();查看

> db.printReplicationInfo();
this is a slave, printing slave replication info.
source: 127.0.0.1:27017
        syncedTo: Fri Mar 09 2018 08:41:41 GMT-0800 (PST)
        3 secs (0 hrs) behind the freshest member (no primary available at the moment)
> 


  1. 初始化集群

登录任意主机执行如下配置

use admin
config = {
"_id":"bsbgpsrs",
"members":[
{"_id":0,"host":"192.168.198.224:27017"},
{"_id":1,"host":"192.168.198.225:27017"},
{"_id":2,"host":"192.168.198.226:27017",arbiterOnly:true}
]
}
rs.initiate(config); # 初始化配置
  1. 通过实例查看主从是否可用
# master上插入数据
use test
db.test.insert({"name":"master1"});

直接在从库上查看数据时会报错

show dbs;
2018-03-09T07:45:34.493-0800 E QUERY    [thread1] Error: listCollections failed: {
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotMasterNoSlaveOk"
} ...
db.mydata.insert({"name":"im slave"});
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })

==原因 mongoDB默认由master读取数据,因此不能直接从slave读取数据。需要设置slave状态==

# 查询前执行此操作即可
db.getMongo().setSlaveOk();
# 执行查询
use test
db.test.find();
{ "_id" : ObjectId("5aa2abeb37bdc4baca1798a0"), "name" : "master1" }

可以看到从库上已经有了数据

  1. 主从切换试验
    如果有必要增加以下参数来设置同步规则
--slavedelay 10      #延时复制 单位为秒
--autoresync         #自动重新同步
--only               #复制指定的数据库,默认复制所有的库
--oplogSize          #主节点的oplog日志大小,单位为M,建议设大点(更改oplog大小时,只需停主库,删除local.*,然后加--oplogSize=* 重新启动即可,*代表大小)

如果不能同步,可以手动试下

db.runCommand({"resync":1}) 

在slave上执行如下命令可以查看状态

db.runCommand({"isMaster":1})
{
        "ismaster" : false,
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : ISODate("2018-03-09T16:58:32.845Z"),
        "maxWireVersion" : 5,
        "minWireVersion" : 0,
        "readOnly" : false,
        "ok" : 1
}

查看从服指向的主服状态(数据源)

> use local
switched to db local
> db.sources.find();
{ "_id" : ObjectId("5aa2b9250eedef392722326e"), "host" : "127.0.0.1:27017", "source" : "main", "syncedTo" : Timestamp(1520614901, 1) }

# 动态增加一个
db.sources.insert({"host": "10.0.0.11:27001"}); 
# 移除它
db.sources.remove({"host": "10.0.0.11:27001"}); 

查看主从复制状态

db.printReplicationInfo(); 

==后记:目前这种方式还不能实现自动主挂切从==

Replica Set集群模式

多机热备构成的集群的解决了其中一台挂掉后,系统自动切换到另一台从而保证服务可用。根据需求预先设定最少3台机器:

  • 主节点:承担所有CRUD操作
  • 备节点:承担查询的任务,主节点不可用时切换成主节点
  • 仲裁节点:无业务任务,仅承担投票选举主节点的功能

准备三份配置,简单如下:

  1. 配置并启动集群
# 主及节点
dbpath=/data/db/mongodbMaster/data
logpath=/data/db/mongodbMaster/logs/mongod.log
port=27017
fork=true

#这里指定了备机的位置
replSet=mtest/127.0.0.1:27018
# 备节点
dbpath=/data/db/mongodbSlave/data
logpath=/data/db/mongodbSlave/logs/mongod.log
port=27018
fork=true

#这里指定了主机的位置
replSet=mtest/127.0.0.1:27017
# 仲裁节点
dbpath=/data/db/mongodbArbiter/data
logpath=/data/db/mongodbArbiter/logs/mongod.log
port=27018
fork=true

#这里指定了主机的位置
replSet=mtest/127.0.0.1:27017
  1. 配置关系节点,用mongo连接到任意节点后执行如下命令
cfg={
    _id:"mtest",
    members:[
        {
            _id:0,
            host:'127.0.0.1:27017',priority:2
        }, {
            _id:1,
            host:'127.0.0.1:27018',priority:1
        }, {
            _id:2,host:'127.0.0.1:27019',arbiterOnly:true}
    ] };  
rs.initiate(cfg);
# priority:优先级,越高越先成为主节点。0时不会参选
# arbiterOnly: true表示仲裁节点

# 执行成功时返回
{ "ok" : 1 }

# 如果其中备份节点有数据会造成启动失败并提示
{
        "ok" : 0,
        "errmsg" : "'127.0.0.1:27018' has data already, cannot initiate set.",
        "code" : 110,
        "codeName" : "CannotInitializeNodeWithData"
}
# 此时删掉备份节点的data再次执行即可

注意,一旦配置成功你会发现提示符变成了 mtest:PRIMARY>,对应的27018节点为mtest:SECONDARY> 、27019节点为mtest:ARBITER>

# 查询状态
rs.status();
{
        "set" : "mtest",
        "date" : ISODate("2018-03-09T18:25:20.896Z"),
        "myState" : 1,
        "term" : NumberLong(1),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1520619920, 1),
                        "t" : NumberLong(1)
                },
                "appliedOpTime" : {
                        "ts" : Timestamp(1520619920, 1),
                        "t" : NumberLong(1)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1520619920, 1),
                        "t" : NumberLong(1)
                }
        },
        "members" : [
                {
                        "_id" : 0,
                        "name" : "127.0.0.1:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 2491,
                        "optime" : {
                                "ts" : Timestamp(1520619920, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2018-03-09T18:25:20Z"),
                        "electionTime" : Timestamp(1520619569, 1),
                        "electionDate" : ISODate("2018-03-09T18:19:29Z"),
                        "configVersion" : 1,
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "127.0.0.1:27018",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 362,
                        "optime" : {
                                "ts" : Timestamp(1520619910, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDurable" : {
                                "ts" : Timestamp(1520619910, 1),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("2018-03-09T18:25:10Z"),
                        "optimeDurableDate" : ISODate("2018-03-09T18:25:10Z"),
                        "lastHeartbeat" : ISODate("2018-03-09T18:25:19.307Z"),
                        "lastHeartbeatRecv" : ISODate("2018-03-09T18:25:19.607Z"),
                        "pingMs" : NumberLong(0),
                        "syncingTo" : "127.0.0.1:27017",
                        "configVersion" : 1
                },
                {
                        "_id" : 2,
                        "name" : "127.0.0.1:27019",
                        "health" : 1,
                        "state" : 7,
                        "stateStr" : "ARBITER",
                        "uptime" : 362,
                        "lastHeartbeat" : ISODate("2018-03-09T18:25:19.307Z"),
                        "lastHeartbeatRecv" : ISODate("2018-03-09T18:25:20.234Z"),
                        "pingMs" : NumberLong(0),
                        "configVersion" : 1
                }
        ],
        "ok" : 1
}

注意看,member中的项目有个stateStr字段表示节点角色,其值为

  • PRIMARY: 表示主节点
  • SECONDARY: 表示从节点
  • ARBITER: 表示仲裁节点

接下来杀掉主服,看看备份节点是否会自动切换到主节点
kill -9 PRIMARY_PID

来到从节点执行

rs.status();
# 可以看到提示符变成 mtest:PRIMARY> 
# 
...
                {
                        "_id" : 1,
                        "name" : "127.0.0.1:27018",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 922,
                        "optime" : {
                                "ts" : Timestamp(1520620472, 1),
                                "t" : NumberLong(2)
                        },
                        "optimeDate" : ISODate("2018-03-09T18:34:32Z"),
                        "infoMessage" : "could not find member to sync from",
                        "electionTime" : Timestamp(1520620450, 1),
                        "electionDate" : ISODate("2018-03-09T18:34:10Z"),
                        "configVersion" : 1,
                        "self" : true
                },
...

# 在从节点执行如下命令即可实现从节点的读取
db.getMongo().setSlaveOk();

# Arbiter上执行查询时会返回
Error: error: {
        "ok" : 0,
        "errmsg" : "node is not in primary or recovering state",
        "code" : 13436,
        "codeName" : "NotMasterOrSecondary"
}
# 即便是setSlaveOk()了也不成

如果后原主机27017恢复后仍然会是PRIMARY节点。

Replica 模式总结

  1. PRIMARY只有一个,它负责读写。只有它挂掉时才会选举新的PRIMARY。
  2. SECONDARY在成为PRIMARY时会异步复制Oplog中的记录,这会导致数据并不是最新的
  3. ARBITER只会投票并无数据需求,配置可以低点
  4. priority=0时表示此节点仅作备份节点
  5. 为了分担PRIMARY的读压力应该开启从SECONDARY读的,开启slave读的另一种办法是
# 修改/root/.mongorc.js,并加入 
rs.slaveOk();

注意这个文件是隐藏的需要用ls -a查看,此方法仅适用于命令行

    原文作者:Nomandia
    原文地址: https://www.jianshu.com/p/13fca10554ae
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞