前言:MongoDB 安装路径以及配置路径
MongDB 安装位置 /usr/local/mongodb3.26/
bin
conf
dbs
logs
workspaces(独自新建)
--mongo_01 (单个配置)
--dbs 三个配置的数据库文件存储目录
--logs 日志目录
--mongodb.conf 每个配置下独立的配置文件
--mongo_02
--mongo_03

一、单点结构
结构简单,一台机器即可,搭建快速,适用小数据量,对数据安全性要求低的情况
1.jpg

配置文件文件
vim /usr/local/mongodb3.26/conf/mongodb.conf
dbpath = /usr/local/mongodb3.26/dbs
logpath = /usr/local/mongodb3.26/logs/mongodb.log
bind_ip = 127.0.0.1
port = 27017
fork = true
nohttpinterface = true
启动:
/usr/local/mongodb3.26/bin/mongod --config /usr/local/mongodb3.26/conf/mongodb.conf

二、主从复制结构
结构简单,搭建快速,有一定的容灾性,当主库数据遭破坏后,可快速恢复服务和数据,但无法做到自动切换
2.jpg

vim /usr/local/mongodb3.26/workspaces/mongo_01/mongodb_01.conf
dbpath = /usr/local/mongodb3.26/workspaces/mongo_01/dbs
logpath = /usr/local/mongodb3.26/workspaces/mongo_01/logs/mongodb.log
bind_ip = 127.0.0.1
port = 27001
fork = true
nohttpinterface = true
master=true (主库)
#启动
/usr/local/mongodb3.26/bin/mongod --config /usr/local/mongodb3.26/workspaces/mongo_01/mongodb_01.conf

vim /usr/local/mongodb3.26/workspaces/mongo_02/mongodb_02.conf
dbpath = /usr/local/mongodb3.26/workspaces/mongo_02/dbs
logpath = /usr/local/mongodb3.26/workspaces/mongo_02/logs/mongodb.log
bind_ip = 127.0.0.1
port = 27002
fork = true
nohttpinterface = true
slave=true  (从库)
source=127.0.0.1:27001 (接收主库数据)
#启动
/usr/local/mongodb3.26/bin/mongod --config /usr/local/mongodb3.26/workspaces/mongo_02/mongodb_02.conf
启动后,在从库查询会暴错.
[thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }
解决方案:
rs.slaveOk(); 设置允许读写操作.

可以通过 mongo 127.0.0.1:27001 或者更换端口来切换库

如果后期想再拓展增加一个从库
vim workspaces/mongo_03/mongodb_03.conf
dbpath = /usr/local/mongodb3.26/workspaces/mongo_03/dbs
logpath = /usr/local/mongodb3.26/workspaces/mongo_03/logs/mongodb.log
bind_ip = 127.0.0.1
port = 27003
fork = true
nohttpinterface = true
slave = true
source = 127.0.0.1:27001
#启动
/usr/local/mongodb3.26/bin/mongod --config /usr/local/mongodb3.26/workspaces/mongo_03/mongodb_03.conf
数据启动后,会主动从主库复制一份数据,如果在从库执行操作会提示.
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })

三、副本集结构
由数据结点,投票结点组成,需要配置集群信息,可自动检测集群中的结点健康状态,当有结点出故障时,自动下线和切换主从结点。适用于数据量较大,高可用服务
3.jpg

mongodb Replica Set 副本集构建:
Replica Set 节点类型分为三种:

standard:常规节点,它存储一份完整的数据副本,参与选举投票,有可能成为primary节点;
passive:存储了完整的数据副本,参与投票,不能成为primary节点;
arbiter:仲裁节点,只参与投票,不接收复制的数据,也不能成为primary节点。
2个常规节点和一个arbiter节点,arbiter节点由于不同步数据,所以负载会很小,部署对硬件没有太大的要求。

###arbiter 节点###
dbpath  = /usr/local/mongodb3.26/workspaces/mongo_04/dbs
logpath = /usr/local/mongodb3.26/workspaces/mongo_04/logs/mongodb.log
bind_ip = 127.0.0.1
port = 27004
#以守护进程启动
fork = true
nohttpinterface = true
directoryperdb=true
#master = true 否则会报错
#F CONTROL  [main] Failed global initialization: BadValue: replication.replSet is not allowed when master is specified
replSet=rs_setname/127.0.0.1:27005,127.0.0.1:27006

启动:
/usr/local/mongodb3.26/bin/mongod -f /usr/local/mongodb3.26/workspaces/mongo_04/mongodb_04.conf


其他两个常规节点配置相同,只是端口不同

分别启动三个机器上的mongodb实例,使用mongodb客户端登陆两个常规节点中的任何一个,执行如下命令:

rs.initiate(
    {"_id" : "rs_setname",
     "members" : [
        {"_id" : 1, "host" : "127.0.0.1:27005"},
        {"_id" : 2, "host" : "127.0.0.1:27006"},
        {"_id" : 3, "host" : "127.0.0.1:27004", "arbiterOnly" : true}
    ]
});

或

rs.initiate(
    {"_id" : "rs_setname",
     "members" : [
        {"_id" : 1, "host" : "127.0.0.1:27005"},
        {"_id" : 2, "host" : "127.0.0.1:27006"}
    ]
});

rs.addArb('127.0.0.1:27004');

启动后发现情况:三台机器
.1:27004 为Arbite
.1:27005 为Primary
.1:27006 为Secondary
在创建数据的时候只允许在主机中创建,其他都报错

为了验证能主动容灾,所以我主动kill掉.1:27005
kill 前:
rs_setname:PRIMARY> rs.status();
{
    "set" : "rs_setname",
    "date" : ISODate("2016-06-13T09:10:47.616Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "members" : [
        {
            "_id" : 1,
            "name" : "127.0.0.1:27005",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1413,
            "optime" : {
                "ts" : Timestamp(1465808561, 2),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2016-06-13T09:02:41Z"),
            "electionTime" : Timestamp(1465808234, 1),
            "electionDate" : ISODate("2016-06-13T08:57:14Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "127.0.0.1:27006",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 823,
            "optime" : {
                "ts" : Timestamp(1465808561, 2),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2016-06-13T09:02:41Z"),
            "lastHeartbeat" : ISODate("2016-06-13T09:10:45.625Z"),
            "lastHeartbeatRecv" : ISODate("2016-06-13T09:10:47.191Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "127.0.0.1:27005",
            "configVersion" : 1
        },
        {
            "_id" : 3,
            "name" : "127.0.0.1:27004",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 823,
            "lastHeartbeat" : ISODate("2016-06-13T09:10:45.625Z"),
            "lastHeartbeatRecv" : ISODate("2016-06-13T09:10:46.407Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 1
        }
    ],
    "ok" : 1
}

kill 后: 
.1:27005 在stateStr 模块出现一个问题提醒.
.1:27006 变化为了 PRIMARY
rs_setname:PRIMARY> rs.status();
{
    "set" : "rs_setname",
    "date" : ISODate("2016-06-13T09:14:34.470Z"),
    "myState" : 1,
    "term" : NumberLong(2),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "members" : [
        {
            "_id" : 1,
            "name" : "127.0.0.1:27005",
            "health" : 0,
            "state" : 8,
            "stateStr" : "(not reachable/healthy)",
            "uptime" : 0,
            "optime" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
            },
            "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
            "lastHeartbeat" : ISODate("2016-06-13T09:14:33.996Z"),
            "lastHeartbeatRecv" : ISODate("2016-06-13T09:11:53.721Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "Connection refused",
            "configVersion" : -1
        },
        {
            "_id" : 2,
            "name" : "127.0.0.1:27006",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 1614,
            "optime" : {
                "ts" : Timestamp(1465809124, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2016-06-13T09:12:04Z"),
            "electionTime" : Timestamp(1465809123, 1),
            "electionDate" : ISODate("2016-06-13T09:12:03Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 3,
            "name" : "127.0.0.1:27004",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 1048,
            "lastHeartbeat" : ISODate("2016-06-13T09:14:33.918Z"),
            "lastHeartbeatRecv" : ISODate("2016-06-13T09:14:31.542Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 1
        }
    ],
    "ok" : 1
}

当恢复后,发现中间停顿大约3秒左右又重新回复正常,在损坏期间的数据自动同步好了。

到此,如果我kill掉 .1:27006 会怎样?

实验,如果仲裁者的服务挂掉后,主服务器挂了还是从服务器还能否顶上?
答案 是否定的.

#-----相关命令:
rs.conf()查看配置情况
rs.status()查看各个节点的状态
经过一小段时间后,他们会选一台作为PRIMARY,其他的常规节点为SECONDARY,同时在js shell中看到提示符从">"变为对应的 "PRIMARY>" 或 "SECONDARY>" 或 "ARBITER>"。可以在PRIMARY是通过rs.stepDown()来切换PRIMARY,执行此命令后会在剩余的常规节点选一个来充当PRIMARY。

四、分片集群结构
由多个副本集组成,配置较为复杂,维护结点较多,使用分片策略减少单点压力,高可用性,但当chunck迁移时,有可能带来性能下降
4.jpg
名词解释
Mongod:mongo数据库实例,用于存储数据库表,配置等信息。根据具体的配置,可以作为存储数据的数据结点,存储配置信息的mongo config;

Mongos:mongo集群服务的路由,读取mongo config信息,根据配置分发请求到指定的shard上,可理解为一种特殊的mongod;

Config Servers : Config服务器存储着集群的metadata信息,包括每个服务器,每个shard的基本信息和chunk信息Config服务器主要存储的是chunk信息。每一个config服务器都复制了完整的chunk信息。

Shards : 每一个shard包括一个或多个服务和存储数据的mongod进程(mongod是MongoDB数据的核心进程)典型的每个shard开启多个服务来提高服务的可用性。这些服务/mongod进程在shard中组成一个复制集;

Chunks: Chunk是一个来自特殊集合中的一个数据范围,(collection,minKey,maxKey)描叙一个chunk,它介于minKey和maxKey范围之间。例如chunks 的maxsize大小是100M,如果一个文件达到或超过这个范围时,会被切分到2个新的chunks中。当一个shard的数据过量时,chunks将会被迁移到其他的shards上。同样,chunks也可以迁移到其他的shards上