MongoDB高可用集群配置的方案

高可用性即HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性。

高可用集群的解决方案

计算机系统的高可用在不同的层面上有不同的表现:

(1)网络高可用

由于网络存储的快速发展,网络冗余技术被不断提升,提高IT系统的高可用性的关键应用就是网络高可用性,网络高可用性与网络高可靠性是有区别的,网络高可用性是通过匹配冗余的网络设备实现网络设备的冗余,达到高可用的目的。
比如冗余的交换机,冗余的路由器等

(2)服务器高可用

服务器高可用主要使用的是服务器集群软件或高可用软件来实现。

(3)存储高可用

使用软件或硬件技术实现存储的高度可用性。其主要技术指标是存储切换功能,数据复制功能,数据快照功能等。当一台存储出现故障时,另一台备用的存储可以快速切换,达一存储不停机的目的。

MongoDB的高可用集群配置

高可用集群,即High Availability Cluster,简称HA Cluster。
集群(cluster)就是一组计算机,它们作为一个整体向用户提供一组网络资源。
这些单个的计算机系统 就是集群的节点(node)。
搭建高可用集群需要合理的配置多台计算机之间的角色,数据恢复,一致性等,主要有以下几种方式:

(1)主从方式 (非对称方式)

主机工作,备机处于监控准备状况;当主机宕机时,备机接管主机的一切工作,待主机恢复正常后,按使用者的设定以自动或手动方式将服务切换到主机上运行,数据的一致性通过共享存储系统解决。

(2)双机双工方式(互备互援)

两台主机同时运行各自的服务工作且相互监测情况,当任一台主机宕机时,另一台主机立即接管它的一切工作,保证工作实时,应用服务系统的关键数据存放在共享存储系统中。

(3)集群工作方式(多服务器互备方式)

多台主机一起工作,各自运行一个或几个服务,各为服务定义一个或多个备用主机,当某个主机故障时,运行在其上的服务就可以被其它主机接管。

MongoDB集群配置的几种方案也遵循了这几种解决办法。

Master-Slave主从结构

image

主从架构一般用于备份或者做读写分离。一般有一主一从设计和一主多从设计。

由两种角色构成:

(1)主(Master)

可读可写,当数据有修改的时候,会将oplog同步到所有连接的salve上去。

(2)从(Slave)

只读不可写,自动从Master同步数据。

特别的,对于Mongodb来说,并不推荐使用Master-Slave架构,因为Master-Slave其中Master宕机后不能自动恢复,推荐使用Replica Set,后面会有介绍,除非Replica的节点数超过50,才需要使用Master-Slave架构,正常情况是不可能用那么多节点的。

还有一点,Master-Slave不支持链式结构,Slave只能直接连接Master。Redis的Master-Slave支持链式结构,Slave可以连接Slave,成为Slave的Slave。

下面为主从配置高可用方案搭建过程(此高可用方案不推荐使用,只做参考):

1)机器环境
182.48.115.238    master-node
182.48.115.236    slave-node
 
两台机器都关闭防火墙和selinux
mongodb的安装参考:https://www.jianshu.com/p/5ed4ab8f60cc
 
2)主从配置
.............master-node节点配置.............
[root@master-node ~]# vim /usr/local/mongodb/mongodb.conf
port=27017
bind_ip = 182.48.115.238
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongo.log
logappend=true
journal = true
fork = true
master = true        //确定自己是主服务器

[root@master-node ~]# nohup /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf &
 
[root@master-node ~]# ps -ef|grep mongodb
root     15707 15514 23 16:45 pts/2    00:00:00 /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf
root     15736 15514  0 16:45 pts/2    00:00:00 grep mongodb
[root@master-node ~]# lsof -i:27017
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mongod  15707 root    7u  IPv4 153114      0t0  TCP 182.48.115.238:27017 (LISTEN)
 
由于mongodb.conf里绑定了本机的ip地址182.48.115.238,所以连接mongodb的时候必须用这个ip地址,不能使用默认的127.0.0.1,也就是说:
[root@master-node ~]# mongo 182.48.115.238:27017     //这样才能连接mongodb
[root@master-node ~]# mongo 或者 mongodb 127.0.0.1:27017    // 这样不能连接mongodb

.............slave-node节点配置.............
[root@slave-node ~]# vim /usr/local/mongodb/mongodb.conf
port=27017
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongo.log
logappend=true
journal = true
fork = true
bind_ip = 182.48.115.236            //确定主数据库端口
source = 182.48.115.238:27017      //确定主数据库端口
slave = true               //确定自己是从服务器
 
[root@slave-node ~]# nohup /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf &
 
[root@slave-node ~]# ps -ef|grep mongo
root     26290 26126  8 16:47 pts/0    00:00:00 /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf
root     26316 26126  0 16:47 pts/0    00:00:00 grep mongo
[root@slave-node ~]# lsof -i:27017
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mongod  26290 root    7u  IPv4 663904      0t0  TCP slave-node1:27017 (LISTEN)
mongod  26290 root   25u  IPv4 663917      0t0  TCP slave-node1:51060->slave-node2:27017 (ESTABLISHED)

Relica Set副本集方式

Mongodb的Replica Set即副本集方式主要有两个目的,一个是数据冗余做故障恢复使用,当发生硬件故障或者其它原因造成的宕机时,可以使用副本进行恢复。

另一个是做读写分离,读的请求分流到副本上,减轻主(Primary)的读压力。

1.Primary和Secondary搭建的Replica Set

image

Replica Set是mongod的实例集合,它们有着同样的数据内容。包含三类角色:

(1)主节点(Primary)

接收所有的写请求,然后把修改同步到所有Secondary。一个Replica Set只能有一个Primary节点,当Primary挂掉后,其他Secondary或者Arbiter节点会重新选举出来一个主节点。默认读请求也是发到Primary节点处理的,需要转发到Secondary需要客户端修改一下连接配置。

(2)副本节点(Secondary)

与主节点保持同样的数据集。当主节点挂掉的时候,参与选主。

(3)仲裁者(Arbiter)

不保有数据,不参与选主,只进行选主投票。使用Arbiter可以减轻数据存储的硬件需求,Arbiter跑起来几乎没什么大的硬件资源需求,但重要的一点是,在生产环境下它和其他数据节点不要部署在同一台机器上。

注意,一个自动failover的Replica Set节点数必须为奇数,目的是选主投票的时候要有一个大多数才能进行选主决策。

(4)选主过程

其中Secondary宕机,不受影响,若Primary宕机,会进行重新选主:

image

2.使用Arbiter搭建Replica Set

偶数个数据节点,加一个Arbiter构成的Replica Set方式:

image

Relica Set副本集方式整体大概如图:


下面为副本集高可用方案搭建过程(此高可用方案也不推荐使用,只做参考):
1)机器环境
182.48.115.236 master-node(主节点)
182.48.115.237 slave-node1(从节点)
182.48.115.238 slave-node2(从节点)

MongoDB 安装目录:/usr/local/mongodb
MongoDB 数据库目录:/usr/local/mongodb/data
MongoDB 日志目录:/usr/local/mongodb/log/mongo.log
MongoDB 配置文件:/usr/local/mongodb/mongodb.conf

对以上三台服务器部署Mongodb的副本集功能,定义副本集名称为:hqmongodb
关闭三台服务器的iptables防火墙和selinux

2)确保三台副本集服务器上的配置文件完全相同(即三台机器的mongodb.conf配置一样,除了配置文件中绑定的ip不一样)。下面操作在三台节点机上都要执行:

编写配置文件,不同的机器修改bind_ip就可以了

[root@master-node ~]# cat /usr/local/mongodb/mongodb.conf
port=27017
bind_ip = 182.48.115.236                 //这个最好配置成本机的ip地址。否则后面进行副本集初始化的时候可能会失败!           
dbpath=/usr/local/mongodb/data
logpath=/usr/local/mongodb/log/mongo.log
pidfilepath=/usr/local/mongodb/mongo.pid
fork=true
logappend=true
shardsvr=true
directoryperdb=true
oplogSize=10000
noprealloc=true
#auth=true
#keyFile =/usr/local/mongodb/keyfile
replSet =shard002

........................具体配置........................

  # master.conf
  dbpath=/opt/mongodb/data/master
  logpath=/opt/mongodb/logs/master.log
  pidfilepath=/opt/mongodb/logs/master.pid
  directoryperdb=true
  logappend=true
  replSet=ynzw
  bind_ip=10.211.55.10
  port=27017
  oplogSize=10000
  fork=true
  noprealloc=true


  # slaver1.conf
  dbpath=/opt/mongodb/data/slaver1
  logpath=/opt/mongodb/logs/slaver1.log
  pidfilepath=/opt/mongodb/logs/slaver1.pid
  directoryperdb=true
  logappend=true
  replSet=ynzw
  bind_ip=10.211.55.10
  port=27018
  oplogSize=10000
  fork=true
  noprealloc=true


  # slaver2.conf
  dbpath=/opt/mongodb/data/slaver2
  logpath=/opt/mongodb/logs/slaver2.log
  pidfilepath=/opt/mongodb/logs/slaver2.pid
  directoryperdb=true
  logappend=true
  replSet=ynzw
  bind_ip=10.211.55.10
  port=27019
  oplogSize=10000
  fork=true
  noprealloc=true


  # arbiter.conf
  dbpath=/opt/mongodb/data/arbiter
  logpath=/opt/mongodb/logs/arbiter.log
  pidfilepath=/opt/mongodb/logs/arbiter.pid
  directoryperdb=true
  logappend=true
  replSet=ynzw
  bind_ip=10.211.55.10
  port=27020
  oplogSize=10000
  fork=true
  noprealloc=true

启动4个节点

 /opt/mongodb/bin/mongod -f /opt/mongodb/conf/master.conf
 /opt/mongodb/bin/mongod -f /opt/mongodb/conf/slaver1.conf
 /opt/mongodb/bin/mongod -f /opt/mongodb/conf/slaver2.conf
 /opt/mongodb/bin/mongod -f /opt/mongodb/conf/arbiter.conf

配置主,备,仲裁节点
客户端连接master、slaver中任意一个节点mongodb

/opt/mongodb/bin/mongo 10.211.55.10:27017  #ip和port是某个节点的地址

开始配置

> use admin
> cfg = {_id: "ynzw",members:[{_id: 0,host: '10.211.55.10:27017',priority: 3},{_id: 1,host: '10.211.55.10:27018',priority: 2},{_id: 2,host: '10.211.55.10:27019',priority: 1},{_id: 3,host: '10.211.55.10:27020',arbiterOnly: true}]};
> rs.initiate(cfg)    #使配置生效

cfg是可以任意的名字,当然最好不要是mongodb的关键字,conf,config都可以。最外层的_id表示replica set的名字,members里包含的是所有节点的地址以及优先级。优先级最高的即成为主节点,即这里的10.211.55.10:27017。特别注意的是,对于仲裁节点,需要有个特别的配置——arbiterOnly:true。这个千万不能少了,不然主备模式就不能生效。

检验
配置的生效时间根据不同的机器配置会有长有短,配置不错的话基本上十几秒内就能生效,有的配置需要一两分钟。如果生效了,执行rs.status()命令会看到如下信息:

 ynzw:SECONDARY> rs.status()
  {
          "set" : "ynzw",
          "date" : ISODate("2017-05-26T06:47:32.069Z"),
          "myState" : 1,
          "term" : NumberLong(8),
          "heartbeatIntervalMillis" : NumberLong(2000),
          "members" : [
                  {
                          "_id" : 0,
                          "name" : "10.211.55.10:27017",
                          "health" : 1,
                          "state" : 1,
                          "stateStr" : "PRIMARY",
                          "uptime" : 24,
                          "optime" : {
                                  "ts" : Timestamp(1495781239, 2),
                                  "t" : NumberLong(8)
                          },
                          "optimeDate" : ISODate("2017-05-26T06:47:19Z"),
                          "electionTime" : Timestamp(1495781239, 1),
                          "electionDate" : ISODate("2017-05-26T06:47:19Z"),
                          "configVersion" : 1,
                          "self" : true
                  },
                  {
                          "_id" : 1,
                          "name" : "10.211.55.10:27018",
                          "health" : 1,
                          "state" : 2,
                          "stateStr" : "SECONDARY",
                          "uptime" : 18,
                          "optime" : {
                                  "ts" : Timestamp(1495781239, 2),
                                  "t" : NumberLong(8)
                          },
                          "optimeDate" : ISODate("2017-05-26T06:47:19Z"),
                          "lastHeartbeat" : ISODate("2017-05-26T06:47:31.424Z"),
                          "lastHeartbeatRecv" : ISODate("2017-05-26T06:47:31.247Z"),
                          "pingMs" : NumberLong(0),
                          "syncingTo" : "10.211.55.10:27017",
                          "configVersion" : 1
                  },
                  {
                          "_id" : 2,
                          "name" : "10.211.55.10:27019",
                          "health" : 1,
                          "state" : 2,
                          "stateStr" : "SECONDARY",
                          "uptime" : 18,
                          "optime" : {
                                  "ts" : Timestamp(1495781239, 2),
                                  "t" : NumberLong(8)
                          },
                          "optimeDate" : ISODate("2017-05-26T06:47:19Z"),
                          "lastHeartbeat" : ISODate("2017-05-26T06:47:31.424Z"),
                          "lastHeartbeatRecv" : ISODate("2017-05-26T06:47:31.734Z"),
                          "pingMs" : NumberLong(0),
                          "syncingTo" : "10.211.55.10:27018",
                          "configVersion" : 1
                  },
                  {
                          "_id" : 3,
                          "name" : "10.211.55.10:27020",
                          "health" : 1,
                          "state" : 7,
                          "stateStr" : "ARBITER",
                          "uptime" : 18,
                          "lastHeartbeat" : ISODate("2017-05-26T06:47:31.424Z"),
                          "lastHeartbeatRecv" : ISODate("2017-05-26T06:47:30.437Z"),
                          "pingMs" : NumberLong(0),
                          "configVersion" : 1
                  }
          ],
          "ok" : 1
  }
  ynzw:PRIMARY> 

如果配置正在生效,其中会包含如下信息:"stateStr" : "RECOVERING"

附录
mongodb配置文件具体属性解释

 dbpath:数据存放目录
 logpath:日志存放路径
 pidfilepath:进程文件,方便停止mongodb
 directoryperdb:为每一个数据库按照数据库名建立文件夹存放
 logappend:以追加的方式记录日志
 replSet:replica set的名字
 bind_ip:mongodb所绑定的ip地址
 port:mongodb进程所使用的端口号,默认为27017
 oplogSize:mongodb操作日志文件的最大大小。单位为Mb,默认为硬盘剩余空间的5%
 fork:以后台方式运行进程
 noprealloc:不预先分配存储

Sharding分片技术

当数据量比较大的时候,我们需要把数据分片运行在不同的机器中,以降低CPU、内存和IO的压力,Sharding就是数据库分片技术。

MongoDB分片技术类似MySQL的水平切分和垂直切分,数据库主要由两种方式做Sharding:垂直扩展和横向切分。

垂直扩展的方式就是进行集群扩展,添加更多的CPU,内存,磁盘空间等。

横向切分则是通过数据分片的方式,通过集群统一提供服务:

image

(1)MongoDB的Sharding架构

image

(2)MongoDB分片架构中的角色

A.数据分片(Shards)

用来保存数据,保证数据的高可用性和一致性。可以是一个单独的mongod实例,也可以是一个副本集。

在生产环境下Shard一般是一个Replica Set,以防止该数据片的单点故障。所有Shard中有一个PrimaryShard,里面包含未进行划分的数据集合:

image

B.查询路由(Query Routers)

路由就是mongos的实例,客户端直接连接mongos,由mongos把读写请求路由到指定的Shard上去。

一个Sharding集群,可以有一个mongos,也可以有多mongos以减轻客户端请求的压力。

C.配置服务器(Config servers)

保存集群的元数据(metadata),包含各个Shard的路由规则。

Sharding分片技术(混合模式)高可用方案的大体架构图:

Sharding分片技术(混合模式)高可用方案架构下向mongodb写数据的流程图:

Sharding分片技术(混合模式)高可用方案架构下向mongodb读数据的流程图:

下面为Sharding分片高可用方案搭建过程(推荐使用此方案):

1、MongoDB机器信息

192.168.252.121 192.168.252.122 192.168.252.123
mongos mongos mongos
config server config server config server
shard server1 主节点 shard server1 副节点 shard server1 仲裁
shard server2 仲裁 shard server2 主节点 shard server2 副节点
shard server3 副节点 shard server3 仲裁 shard server3 主节点

端口分配:

mongos:20000
config:21000
shard1:27001
shard2:27002
shard3:27003

下载并且安装

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.6.2.tgz
tar -xzvf mongodb-linux-x86_64-amazon-3.6.2.tgz  -C /usr/local/

所有版本二进制文件,自行下载

https://www.mongodb.org/dl/win32/x86_64-2008plus-ssl?_ga=2.87139544.1567998244.1517190032-1153843332.1517190032&_gac=1.204211492.1517212002.EAIaIQobChMI44v9_9b82AIV1AcqCh0lcABIEAAYASAAEgKI1_D_BwE

改名

cd /usr/local/
mv  mongodb-linux-x86_64-amazon-3.6.2 mongodb

分别在每台机器建立conf、mongos、config、shard1、shard2、shard3六个目录,因为mongos不存储数据,只需要建立日志文件目录即可。

mkdir -p /usr/local/mongodb/conf \
mkdir -p /usr/local/mongodb/mongos/log \
mkdir -p /usr/local/mongodb/config/data \
mkdir -p /usr/local/mongodb/config/log \
mkdir -p /usr/local/mongodb/shard1/data \
mkdir -p /usr/local/mongodb/shard1/log \
mkdir -p /usr/local/mongodb/shard2/data \
mkdir -p /usr/local/mongodb/shard2/log \
mkdir -p /usr/local/mongodb/shard3/data \
mkdir -p /usr/local/mongodb/shard3/log

配置环境变量

vi /etc/profile
# MongoDB 环境变量内容
export MONGODB_HOME=/usr/local/mongodb
export PATH=$MONGODB_HOME/bin:$PATH

使立即生效

source /etc/profile

2、config server配置服务器

mongodb3.4以后要求配置服务器也创建副本集,不然集群搭建不成功。
(三台机器)添加配置文件

vi /usr/local/mongodb/conf/config.conf

## 配置文件内容
pidfilepath = /usr/local/mongodb/config/log/configsrv.pid
dbpath = /usr/local/mongodb/config/data
logpath = /usr/local/mongodb/config/log/congigsrv.log
logappend = true
 
bind_ip = 0.0.0.0
port = 21000
fork = true
 
#declare this is a config db of a cluster;
configsvr = true

#副本集名称
replSet = configs
 
#设置最大连接数
maxConns = 20000

启动三台服务器的config server

mongod -f /usr/local/mongodb/conf/config.conf

登录任意一台配置服务器,初始化配置副本集
连接 MongoDB

mongo --port 21000

config 变量

config = {
    _id : "configs",
    members : [
    {_id : 0, host : "192.168.252.121:21000" },
    {_id : 1, host : "192.168.252.122:21000" },
    {_id : 2, host : "192.168.252.123:21000" }
    ]
}

初始化副本集

rs.initiate(config)

其中,"_id" : "configs"应与配置文件中配置的 replicaction.replSetName 一致,"members" 中的 "host" 为三个节点的 ip 和 port
响应内容如下

> config = {
... _id : "configs",
... members : [
... {_id : 0, host : "192.168.252.121:21000" },
... {_id : 1, host : "192.168.252.122:21000" },
... {_id : 2, host : "192.168.252.123:21000" }
... ]
... }
{
    "_id" : "configs",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.252.121:21000"
        },
        {
            "_id" : 1,
            "host" : "192.168.252.122:21000"
        },
        {
            "_id" : 2,
            "host" : "192.168.252.123:21000"
        }
    ]
}
> rs.initiate(config);
{
    "ok" : 1,
    "operationTime" : Timestamp(1517369899, 1),
    "$gleStats" : {
        "lastOpTime" : Timestamp(1517369899, 1),
        "electionId" : ObjectId("000000000000000000000000")
    },
    "$clusterTime" : {
        "clusterTime" : Timestamp(1517369899, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
configs:SECONDARY>

此时会发现终端上的输出已经有了变化。

//从单个一个
>
//变成了
configs:SECONDARY>

查询状态

configs:SECONDARY> rs.status()

3. 配置分片副本集

3.1 设置第一个分片副本集

(三台机器)设置第一个分片副本集
配置文件

vi /usr/local/mongodb/conf/shard1.conf

#配置文件内容
#——————————————–
pidfilepath = /usr/local/mongodb/shard1/log/shard1.pid
dbpath = /usr/local/mongodb/shard1/data
logpath = /usr/local/mongodb/shard1/log/shard1.log
logappend = true

bind_ip = 0.0.0.0
port = 27001
fork = true
 
#副本集名称
replSet = shard1
 
#declare this is a shard db of a cluster;
shardsvr = true
 
#设置最大连接数
maxConns = 20000

启动三台服务器的shard1 server

mongod -f /usr/local/mongodb/conf/shard1.conf

登陆任意一台服务器,初始化副本集(除了192.168.252.123)
连接 MongoDB

mongo --port 27001

使用admin数据库

use admin

定义副本集配置

config = {
    _id : "shard1",
     members : [
         {_id : 0, host : "192.168.252.121:27001" },
         {_id : 1, host : "192.168.252.122:27001" },
         {_id : 2, host : "192.168.252.123:27001" , arbiterOnly: true }
     ]
 }

初始化副本集配置

rs.initiate(config)

响应内容如下

> use admin
switched to db admin
> config = {
...     _id : "shard1",
...      members : [
...          {_id : 0, host : "192.168.252.121:27001" },
...          {_id : 1, host : "192.168.252.122:27001" },
...          {_id : 2, host : "192.168.252.123:27001" , arbiterOnly: true }
...      ]
...  }
{
    "_id" : "shard1",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.252.121:27001"
        },
        {
            "_id" : 1,
            "host" : "192.168.252.122:27001"
        },
        {
            "_id" : 2,
            "host" : "192.168.252.123:27001",
            "arbiterOnly" : true
        }
    ]
}
> rs.initiate(config)
{ "ok" : 1 }

此时会发现终端上的输出已经有了变化。

//从单个一个
>
//变成了
shard1:SECONDARY>

查询状态

shard1:SECONDARY> rs.status()

3.2 设置第二个分片副本集

设置第二个分片副本集
配置文件

vi /usr/local/mongodb/conf/shard2.conf

#配置文件内容
#——————————————–
pidfilepath = /usr/local/mongodb/shard2/log/shard2.pid
dbpath = /usr/local/mongodb/shard2/data
logpath = /usr/local/mongodb/shard2/log/shard2.log
logappend = true

bind_ip = 0.0.0.0
port = 27002
fork = true
 
#副本集名称
replSet=shard2
 
#declare this is a shard db of a cluster;
shardsvr = true
 
#设置最大连接数
maxConns=20000

启动三台服务器的shard2 server

mongod -f /usr/local/mongodb/conf/shard2.conf

连接 MongoDB

mongo --port 27002

使用admin数据库

use admin

定义副本集配置

config = {
    _id : "shard2",
     members : [
         {_id : 0, host : "192.168.252.121:27002"  , arbiterOnly: true },
         {_id : 1, host : "192.168.252.122:27002" },
         {_id : 2, host : "192.168.252.123:27002" }
     ]
 }

初始化副本集配置

rs.initiate(config)

响应内容如下

> use admin
switched to db admin
> config = {
...     _id : "shard2",
...      members : [
...          {_id : 0, host : "192.168.252.121:27002"  , arbiterOnly: true },
...          {_id : 1, host : "192.168.252.122:27002" },
...          {_id : 2, host : "192.168.252.123:27002" }
...      ]
...  }
{
    "_id" : "shard2",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.252.121:27002",
            "arbiterOnly" : true
        },
        {
            "_id" : 1,
            "host" : "192.168.252.122:27002"
        },
        {
            "_id" : 2,
            "host" : "192.168.252.123:27002"
        }
    ]
}
> rs.initiate(config)
{ "ok" : 1 }
shard2:SECONDARY> rs.status()

3.3 设置第三个分片副本集

vi /usr/local/mongodb/conf/shard3.conf

#配置文件内容
#——————————————–
pidfilepath = /usr/local/mongodb/shard3/log/shard3.pid
dbpath = /usr/local/mongodb/shard3/data
logpath = /usr/local/mongodb/shard3/log/shard3.log
logappend = true

bind_ip = 0.0.0.0
port = 27003
fork = true

#副本集名称
replSet=shard3
 
#declare this is a shard db of a cluster;
shardsvr = true
 
#设置最大连接数
maxConns=20000

启动三台服务器的shard3 server

mongod -f /usr/local/mongodb/conf/shard3.conf

登陆任意一台服务器,初始化副本集(除了192.168.252.121)

mongo --port 27003

使用admin数据库

use admin

定义副本集配置

config = {
    _id : "shard3",
     members : [
         {_id : 0, host : "192.168.252.121:27003" },
         {_id : 1, host : "192.168.252.122:27003" , arbiterOnly: true},
         {_id : 2, host : "192.168.252.123:27003" }
     ]
 }

初始化副本集配置

rs.initiate(config)

响应内容如下

> use admin
switched to db admin
> config = {
...     _id : "shard3",
...      members : [
...          {_id : 0, host : "192.168.252.121:27003" },
...          {_id : 1, host : "192.168.252.122:27003" , arbiterOnly: true},
...          {_id : 2, host : "192.168.252.123:27003" }
...      ]
...  }
{
    "_id" : "shard3",
    "members" : [
        {
            "_id" : 0,
            "host" : "192.168.252.121:27003"
        },
        {
            "_id" : 1,
            "host" : "192.168.252.122:27003",
            "arbiterOnly" : true
        },
        {
            "_id" : 2,
            "host" : "192.168.252.123:27003"
        }
    ]
}
> rs.initiate(config)
{ "ok" : 1 }
shard3:SECONDARY> rs.status()

3.4 配置路由服务器 mongos

(三台机器)先启动配置服务器和分片服务器,后启动路由实例启动路由实例:

vi /usr/local/mongodb/conf/mongos.conf

#内容
pidfilepath = /usr/local/mongodb/mongos/log/mongos.pid
logpath = /usr/local/mongodb/mongos/log/mongos.log
logappend = true

bind_ip = 0.0.0.0
port = 20000
fork = true

#监听的配置服务器,只能有1个或者3个 configs为配置服务器的副本集名字
configdb = configs/192.168.252.121:21000,192.168.252.122:21000,192.168.252.123:21000
 
#设置最大连接数
maxConns = 20000

启动三台服务器的mongos server

mongos -f /usr/local/mongodb/conf/mongos.conf

4. 串联路由服务器

目前搭建了mongodb配置服务器、路由服务器,各个分片服务器,不过应用程序连接到mongos路由服务器并不能使用分片机制,还需要在程序里设置分片配置,让分片生效。
登陆任意一台mongos

mongo --port 20000

使用admin数据库

use  admin

串联路由服务器与分配副本集

sh.addShard("shard1/192.168.252.121:27001,192.168.252.122:27001,192.168.252.123:27001");
sh.addShard("shard2/192.168.252.121:27002,192.168.252.122:27002,192.168.252.123:27002");
sh.addShard("shard3/192.168.252.121:27003,192.168.252.122:27003,192.168.252.123:27003");

查看集群状态

sh.status()

响应内容如下

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
    "_id" : 1,
    "minCompatibleVersion" : 5,
    "currentVersion" : 6,
    "clusterId" : ObjectId("5a713a37d56e076f3eb47acf")
  }
  shards:
        {  "_id" : "shard1",  "host" : "shard1/192.168.252.121:27001,192.168.252.122:27001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/192.168.252.122:27002,192.168.252.123:27002",  "state" : 1 }
        {  "_id" : "shard3",  "host" : "shard3/192.168.252.121:27003,192.168.252.123:27003",  "state" : 1 }
  active mongoses:
        "3.6.2" : 3
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }

mongos>

5. 启用集合分片生效

目前配置服务、路由服务、分片服务、副本集服务都已经串联起来了,但我们的目的是希望插入数据,数据能够自动分片。连接在mongos上,准备让指定的数据库、指定的集合分片生效。
登陆任意一台mongos

mongo --port 20000

使用admin数据库

use  admin

指定testdb分片生效,如下图:

db.runCommand( { enablesharding :"testdb"});

或

mongos> sh.enablesharding("testdb")
sh.enablesharding("testdb")

指定数据库里需要分片的集合和片键,哈希name分片,如下图:

db.runCommand( { shardcollection : "testdb.table1",key : {"name": "hashed"} } );

或

mongos> sh.shardcollection("testdb.table1", {"name": "hashed"})
sh.shardcollection("testdb.table1", {"name": "hashed"})

通过命令查看mongodb路由服务器上的shards集合会有数据展示,如下图:


shards数据

通过命令查看mongodb路由服务器上的chunks集合会有数据展示,如下图:


chunks数据

我们设置testdb的 table1 表需要分片,根据 id 或name自动分片到 shard1 ,shard2,shard3 上面去。要这样设置是因为不是所有mongodb 的数据库和表 都需要分片!
测试分片配置结果
连接 MongoDB 路由服务

mongo  127.0.0.1:20000

切换到 testdb 数据库

use  testdb;

插入测试数据

for(i=1;i<=100000;i++){db.table1.insert({"id":i,"name":"penglei"})};

总条数

db.table1.aggregate([{$group : {_id : "$name", totle : {$sum : 1}}}])

查看分片情况如下

  • shard1: "count": 33755

  • shard2: "count": 33143,

  • shard3: "count": 33102

结论数据基本均匀

db.table1.stats();
mongos> db.table1.stats();
{
    "sharded": true,
    "capped": false,
    "ns": "testdb.table1",
    "count": 100000,
    "size": 5200000,
    "storageSize": 1519616,
    "totalIndexSize": 3530752,
    "indexSizes": {
        "_id_": 892928,
        "id_hashed": 2637824
    },
    "avgObjSize": 52,
    "nindexes": 2,
    "nchunks": 6,
    "shards": {
        "shard1": {
            "ns": "testdb.table1",
            "size": 1755260,
            "count": 33755,
            "avgObjSize": 52,
            "storageSize": 532480,
            "capped": false,
            "wiredTiger": {
            ...省略很多
            }
        },
        "shard2": {
            "ns": "testdb.table1",
            "size": 1723436,
            "count": 33143,
            "avgObjSize": 52,
            "storageSize": 479232,
            "capped": false,
            "wiredTiger": {
            ...省略很多
            }
        },
        "shard3": {
            "ns": "testdb.table1",
            "size": 1721304,
            "count": 33102,
            "avgObjSize": 52,
            "storageSize": 507904,
            "capped": false,
            "wiredTiger": {
            ...省略很多
            }
        }
    },
    "ok": 1,
    "$clusterTime": {
        "clusterTime": Timestamp(1517488062, 350),
        "signature": {
            "hash": BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId": NumberLong(0)
        }
    },
    "operationTime": Timestamp(1517488062, 350)
}
mongos> 

分组查看总数量是:100000

mongos> db.table1.aggregate([{$group : {_id : "$name", totle : {$sum : 1}}}])
{ "_id" : "penglei", "totle" : 100000 }
mongos>

后期运维

参考

手把手教你 MongoDB 的安装与详细使用(一)

http://www.ymq.io/2018/01/26/MongoDB-1/

手把手教你 MongoDB 的安装与详细使用(二)

http://www.ymq.io/2018/01/29/MongoDB-2/

创建索引

db.table1.createIndex({"name":1})
db.table1.getIndexes()

image.png
image.png
image.png

启动

mongodb的启动顺序是,先启动配置服务器,在启动分片,最后启动mongos.

mongod -f /usr/local/mongodb/conf/config.conf
mongod -f /usr/local/mongodb/conf/shard1.conf
mongod -f /usr/local/mongodb/conf/shard2.conf
mongod -f /usr/local/mongodb/conf/shard3.conf
mongod -f /usr/local/mongodb/conf/mongos.conf

启动报错

about to fork child process, waiting until server is ready for connections.
forked process: 1303
child process started successfully, parent exiting
[root@node1 ~]# mongod -f /usr/local/mongodb/conf/shard1.conf
about to fork child process, waiting until server is ready for connections.
forked process: 1384

删除 mongod.lock

cd /usr/local/mongodb/shard1/data
rm -rf mongod.lock

关闭

#debian、ubuntu系统下:

apt-get install psmisc

#centos或、rhel系统下:

yum install psmisc

关闭时,直接killall杀掉所有进程

killall mongod
killall mongos

参考:

百度百科-高可用集群

MongoDB 教程

https://www.cnblogs.com/binyue/p/5901328.html

Runoob 教程:http://www.runoob.com/mongodb/mongodb-tutorial.html

MongoDB 官网地址:https://www.mongodb.com

MongoDB 官方英文文档:https://docs.mongodb.com/manual

MongoDB 各平台下载地址:https://www.mongodb.com/download-center#community

MongoDB 安装 https://docs.mongodb.com/manual/tutorial/install-mongodb-enterprise-on-ubuntu

mongodb高可用具体配置参考:

Mongodb主从复制 及 副本集+分片集群梳理:
https://www.cnblogs.com/nulige/p/7613721.html

搭建 MongoDB分片(sharding) / 分区 / 集群环境:https://www.jianshu.com/p/66e7ba201545

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270