0%

搭建MongoDB副本集&分片

副本集

什么是副本集?

顾名思义,副本集是一个集合,即MongoDB实例的集合,集合中的每个成员拥有相同的数据集合;一个副本集包含多个数据节点和一个可选的仲裁节点,在数据节点中,只有一个可以作为主节点(Primary Node),其他节点只能是第二节点(Secondary Nodes)。

主节点接收所有的写操作,一个副本集只能有一个能够确认写入的主节点(Primary Node),如下图:

第二节点复制主节点的操作日志并且将所有的操作应用到自己的数据集合中,复制过程是异步的,如果主节点不可用,一个可以被选举的第二节点将会被选举为主节点,所以在副本集中,即使一个或者多个成员没有正常运行,但整个副本集仍然可以正常工作;主副节点关系如下图:

在某些情况下(比如受硬件条件所限,只有一个主节点和一个副节点,无法添加更多的副节点),你可以选择将mongod实例添加进副本集,并作为仲裁者(仲裁者只负责选举新的主节点,不持有数据),在副本集中,如果主节点与其他节点无法通信的时间超过配置的时间值( electionTimeoutMillis ),那么副本集将视主节点出现故障,此时将会重新选举一个正常副节点来作为新的主节点,从而让整个副本集系统正常工作,如下图:

副本集搭建(文中为三个mongod实例的副本集)

副本集的搭建的步骤为:同时启动多个mongod实例(可以在一台服务器上,也可以在不同的服务器上),然后在每个实例的配置文件中配置相应的配置项,最后启动实例后,登录并且在做一次配置即可。

注意: 文中都是通过配置文件的方式来启动mongod实例的,你也可以通过启动参数来启动实例,同时本文中的mongod实例是通过supervisor 来管理的,关于如何通过supervisor管理进程,可以自行查阅相关资料或者参考这里

  1. /usr/local/etc(目录根据自己机器的实际情况来选择)目录下添加三个mongodb的配置文件,文件名随意,为了方便起见,这里分别命名为: mongod0.conf, mongod1.conf, mongod2.conf, 如下图:

    文件内容为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    systemLog:
    destination: file
    path: "/var/log/mongod0.log"
    logAppend: true
    processManagement:
    fork: false #因为supervisor本身就是以fork的形式启动进程,所以这里填false
    pidFilePath: "/var/run/mongod0.pid"
    net:
    bindIp: 127.0.0.1
    port: 27017
    maxIncomingConnections: 2000
    storage:
    dbPath: "/usr/local/mongodb-4.4.5/mongod0/shard0"
    journal:
    enabled: true
    engine: wiredTiger
    wiredTiger:
    engineConfig:
    cacheSizeGB: 2
    security:
    authorization: disabled
    replication:
    oplogSizeMB: 120
    replSetName: replica-set

    对于每一个配置项,如果不明白每个配置项的释义,请参考: mongo配置文件 。另外,如果实例在同一台机器上,则针对每个实例,需要区分path, pidFilePath, port, dbPath这几个的配置值,并且每个配置文件中的replSetName必须相同。

  2. 添加每一个实例在supervisor中的启动文件,mongod0.ini, mongod1.ini, mongod2.ini, 文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [program:shard0]
    command=/usr/local/mongodb-4.4.5/bin/mongod --config /usr/local/etc/mongod0.conf
    process_name=%(program_name)s
    numprocs=1
    directory=/usr/local/mongodb-4.4.5
    autostart=true
    startretries=3
    autorestart=unexpected
    stopsignal=QUIT
    user=user
    stdout_logfile=/var/log/mongod/mongod0.log
    stderr_logfile=/var/log/mongod/mongod0-err.log

在supervisorctl中执行update,此时三个实例便启动成功。

  1. 三个实例启动成功后,只是启动了三个独立的mongod实例,实例之间并没有形成副本集,此时需要通过mongo客户端登录某一个实例,完成最后一步配置。登录进mongo shell后,依次执行以下命令:

    1
    2
    3
    replica-set > mongo --host 127.0.0.1 --port 27017
    replica-set > conf = {_id: "replica-set(这个值必须与mongod实例配置文件中的replSetName相同)", members: [{_id: 0, host: "127.0.0.1:27017"}, {_id: 1, host: "127.0.0.1:27018"}, {_id: 2, host: "127.0.0.1:27019"}]}
    replica-set > rs.initiate(conf)

    rs.initiate(conf)是初始化副本集配置的命令,初始化后副本集才算配置成功,上面初始化的配置是不带仲裁节点的配置,如果需要仲裁节点,则需要将配置改为: conf = {_id: replica-set, members: [{_id: 0, host: “127.0.0.1:27017”}, {_id: 1, host: “127.0.0.1:27018”}, {_id: 2, host: “127.0.0.1:27019”, arbiter: true}]}, 这样id为2,地址为127.0.0.1:27019的节点即为仲裁节点,如果不在初始化的时候指定仲裁节点,后期也可以通过mongo客户端设置。

  2. 至此,副本集已经搭建完成,可以对副本集的数据分布以及存储情况进行验证。在默认情况下,只能在主节点中进行查询操作,副本集中副节点(Secondary Nodes)是不能执行mongodb查询命令的,如果需要在副本节点中执行,则需要通过mongo shell登录主节点,并在客户端中执行下面的命令:

    1
    2
    replica-set(Primary) > mongo --host 127.0.0.1 --port 27017
    replica-set(Primary) > rs.slaveOk()

    通过Shell客户端或者代码向副本集中插入数据,然后查看数据分布情况,是否与预期的一致。同时,如果通过代码连接mongodb,那么在保持连接的时候,将主节点断开连接,查看代码中的mongodb连接是否还存在。

    注意: 通过代码连接副本集时,在连接的URI中填某一个节点即可,不需要每一个节点地址都填写,如: mongodb://127.0.0.1:27017/?replicaSet=replica-set;slaveOk=true;w=majority;wtimeoutMS=2000

分片

什么是分片?

分片是将MongoDB中的数据集分割成多个数据片,每片数据存放在不同的MongoDB实例中,可以理解为将一个MongoDB数据集拆分成多个小型数据集,而小数据集分布在相同或者不同的物理机器上,分割只是从物理层面进行分割,逻辑上仍然属于同一个数据集合。

分片的目的
  1. 如果不进行分割,则数据库所有的读写操作都在同一个MongoDB实例或者同一台机器上,对于资源有限(特别是CPU)的服务器来说,随着数据量增大以及数据IO越来越频繁,最终将会导致服务器不堪重负。
  2. 对于大型系统来说,一台数据库服务器或者一个数据库实例无法满足数据存储的需求
  3. 数据分散存储,可以多个实例同时执行读写,满足更高的并发需求。
搭建分片实例

分片包含三部分, 如下图所示:

  1. 分片(Shards):一般来说,分片为一组MongoDB实例的集群,每个分片与副本集结合使用,即每个分片是一组副本集,数据存储在每一个分片上。
  2. 配置服务器(Config Servers):配置服务器存储分片集群的元数据,该元数据反应了所有分片集群的状态和组件,元数据包含了每个分片上的chunk列表以及定义块的范围,配置服务器同样存储了权限验证的配置信息,比如角色权限控制和集群内部验证设置。MongoDB同样使用配置服务器来管理分布式锁。
  3. 路由器(Mongos):Mongos缓存了配置服务器的元数据信息,并且通过这些数据来将数据读写路由到正确的分片上,当配置服务器的元数据有更新时,Mongos同时也会更新缓存。

注意: 不同的分片集群必须使用不同的配置服务器(Config Servers),不能使用同一个配置服务器(Config Servers)

分片实例的搭建与副本集类似,都是配置不同的配置文件,然后启动相应的实例:

  1. Shards: 按照架构图,每个Shards节点可以是单个Mongod实例,也可以是副本集,比如: 每个Shards节点由一个副本集构成,而副本集由3个Mongod实例构成,每个Mongod实例的配置文件如下:

这里只给出了关键配置项,其他配置项根据自己的实际情况配置,图中的replSetName表示当前实例属于哪个副本集,该副本集中的每个节点的该配置项必须一致,clusterRole表示当前节点在分片中的的角色,可选值有: shardsvrconfigsvrshardsvr表示该节点是作为Shards节点提供服务,而configsvr表示该节点作为Config Server节点提供服务。

  1. Config Servers: 按照架构图中所示,Config Servers为一个副本集,配置方式与Shards一样,不同的是clusterRole配置项的值应该配置为configsvr, 如下图:

  2. Mongos: 路由服务器作为分片架构中开放给应用服务器的唯一节点,可以存在多个路由服务器指向同一个分片系统。路由服务器也需要配置启动项,而启动项中需要指定对应的配置服务器副本集,如下图:

  3. 配置成功后,先启动Shards节点,然后启动Config Servers节点,最后启动Mongos节点,启动成功后,需要通过Mongo客户端连接进Mongos,然后执行如下命令添加Shards节点:

    1
    sh.addShard("replName/mongodb3.example.net:27327")

至此,分片搭建完成。