MongoDB高可用性集群部署

MongoDB高可用性集群部署

介绍

基本介绍

MongoDB是一种非关系型数据库(NoSQL),也就说其数据存储的类型为Key:Value,原生支持分布式、高可用、大数据量;其主要具有以下特点:

  1. 高性能
    • 提供高性能的数据持久性,尤其是支持嵌入式数据模型减少数据库系统上的I/O 操作,可建立索引以支持更快速的查询,并且可以包括嵌入式文档和数组中的键
  2. 丰富的语言查询
    • 支持丰富的查询语言CRUD(增删改查)以及数据汇总,文本搜索和地理位置空间索引
  3. 高可用性
    • 原生支持高可用性集群建构,通过创建一定数量的副本集来实现数据高可用服务高可用,支持自动故障转移
  4. 可扩展性
    • 如果其高可用集群架构依然无法满足业务增长的需求,可考虑进行水平扩展,其大致原理为将数据分片存储在一组主机上,类似于Redisslot
  5. 支持多种存储引擎
    • WiredTigerMMAPv1InMemory等存储引擎

不同于关系型数据库的语法,MongoDB采用的语法为JSON格式的语句,查询时展示数据也是采用JSON的形式。

应用场景
  • 游戏

    存储用户的基本信息,装备、积分、金币等等,以内嵌文档的形式,方便进行查询和更新

  • 直播平台

    存储用户的基本信息,道具等(什么跑车、火箭、小黄瓜啥玩意的)

  • 社交软件

    存储用户的基本信息,以及地理位置关联形式的信息推送(附近的人、附近有啥好吃的、好玩的)

  • 电商/外卖/O2O/共享单车等

    商品的种类通常非常复杂,同一商品通常具有不同的属性以及附加的属性,使用传统的关系型数据库虽然也能满足要求,但不适用于高性能高并发场景,也无法提供灵活的可扩展性(如果商品新增加了属性,就要涉及到调整表结构)

  • 物流业

    存储订单信息,位置信息追踪,方便跟进运输进度

  • IoT

    存储各种智能设备的信息以及设备上传的日志信息(智能硬件/智能家居/智慧农业)

......

基本规划

架构图

MongoDB_Cluster20190907141356

IP地址规划

主机名IP地址描述
mdb01172.16.1.51用作Master-Node
mdb02172.16.1.52用作Slave-Node
mdb03172.16.1.53用作Slave-Node
mdb04172.16.1.54用作Slave-NodeArbitration-Node,多实例

下载&安装

MongoDB也是开源的软件,其也是提供社区版和商业版。本文使用的为社区版。

官方下载地址:https://mongodb.com/download-center/community

MongoDB也提供多种形式的安装方案,你可以使用RPM的形式,也可以使用预编译的二进制压缩包的形式,本文使用了第二种形式。

本文使用的软件包版本:mongodb-linux-x86_64-3.6.13.tgz

系统环境:CentOS Linux release 7.6.1810

以下内容所有主机全部执行

  1. 将下载的包上传到服务器,并创建数据目录、用户组、启动别名

    #本文的目录规划
    #/opt/mongo_cluster
    #├── mongo_cfg						#所有实例相关的配置文件存放在此
    #│   ├── conf						#多实例的配置文件集中放在这里
    #│   ├── env						#systemd启动服务从此目录文件读取不同实例的配置文件位置
    #│   ├── logs						#存放所多实例的日志
    #│   └── run						#存放多实例的PID文件
    #├── mongo_data						#多实例的数据目录,不同的监听端口对应不同的目录
    #│   ├── mongo_27017
    #│   └── mongo_28017
    #├── mongodb -> /opt/mongo_cluster/mongodb-linux-x86_64-3.6.13		#软链接
    #└── mongodb-linux-x86_64-3.6.13	#带版本号的官方原版可执行文件
    #    ├── bin						#可执行文件目录
    #    ├── LICENSE-Community.txt		#社区版LICENSE等
    #    ├── MPL-2
    #    ├── README
    #    ├── THIRD-PARTY-NOTICES
    #    └── THIRD-PARTY-NOTICES.gotools
    #添加节点间的hosts本地解析
    cat > /etc/hosts<<EOF
    172.16.1.51 mdb01
    172.16.1.52 mdb02
    172.16.1.53 mdb03
    172.16.1.54 mdb04
    EOF
    #创建自定以的配置文件及数据目录
    mkdir /opt/mongo_cluster/mongo_cfg/{conf,env,logs,run} -p
    mkdir /opt/mongo_cluster/mongo_data/{mongo_27017,mongo_28017} -p
    #上传包
    #rz.........
    #创建用户,稍后授权时会使用
    useradd mongo
    #解压包
    tar xf mongodb-linux-x86_64-3.6.13.tgz -C /opt/mongo_cluster
    #创建软链接
    ln -s /opt/mongo_cluster/mongodb-linux-x86_64-3.6.13 /opt/mongo_cluster/mongodb
    
  2. 添加到systemd的启动服务,编辑vim /usr/lib/systemd/system/mongod@.service文件,我们添加的是一个使用systemd管理的多实例配置,加入下面的内容:

    [Unit]
    Description=MongoDB Service.
    After=network.target remote-fs.target nss-lookup.target
    
    [Service]
    Type=forking
    User=mongo
    EnvironmentFile=-/opt/mongo_cluster/mongo_cfg/env/cfg_env%i
    ExecStart=/opt/mongo_cluster/mongodb/bin/mongod --config $MDB_CFG
    ExecStop=/opt/mongo_cluster/mongodb/bin/mongod --shutdown --config $MDB_CFG
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    

    注: 服务文件名中的@表示该配置可以传递参数启动,在配置文件中使用%i来指代该变量。我们并没有定义systemdExecReload方法,所以不支持重载服务,仅支持重启方法。

    粘贴该配置文件并保存,设置文件权限以及重载systemd

    #设置文件权限
    chmod 754 /usr/lib/systemd/system/mongod@.service
    #重载systemd
    systemctl daemon-reload
    
  3. 添加系统环境变量,方便命令行的mongo客户端登陆管理,还有两个官方建议添加的参数,否则登陆时会出现一些警告

    cat > /etc/profile.d/mongodb.sh <<EOF
    export PATH=$PATH:/opt/mongo_cluster/mongodb/bin
    /usr/bin/echo "never"  > /sys/kernel/mm/transparent_hugepage/enabled
    /usr/bin/echo "never" > /sys/kernel/mm/transparent_hugepage/defrag
    EOF
    #立即生效
    source /etc/profile.d/mongodb.sh
    

配置&启动

准备配置文件

基础的工作基本做完,现在我们需要添加不同的配置文件以及systemd多实例的环境配置文件。

  1. 添加多实例下需要传递的systemd启动参数的变量文件,执行vim /opt/mongo_cluster/mongo_cfg/env/cfg_env27017命令,添加监听27017端口配置文件的路径定义。该参数最终会根据用户启动的参数传递给systemdsystemd根据文件定义选择不同的配置文件来启动实例。将下面的文件内容写入该文件。

    MDB_CFG="/opt/mongo_cluster/mongo_cfg/conf/mongodb_27017.yaml"
    
  2. 再添加一个仲裁节点使用的配置,执行vim /opt/mongo_cluster/mongo_cfg/env/cfg_env28017 命令,添加监听28017端口的配置文件的路径定义。虽然只有172.16.1.54这台主机使用该配置,但为了具备通用性,我们在所有的主机套用了完全一致的配置文件。启动时仅需传递不同的启动参数即可。粘贴下面的内容到该文件

    MDB_CFG="/opt/mongo_cluster/mongo_cfg/conf/mongodb_28017.yaml"
    
  3. 添加监听27017端口的mongodb主配置文件,执行vim /opt/mongo_cluster/mongo_cfg/conf/mongodb_27017.yaml,将下面的内容粘贴到该文件。

    systemLog:
      destination: file 
      logAppend: true 
      path: /opt/mongo_cluster/mongo_cfg/logs/mongodb_27017.log
    
    storage:
      journal:
        enabled: true
      dbPath: /opt/mongo_cluster/mongo_data/mongo_27017
      directoryPerDB: true
    
      wiredTiger:
        engineConfig:
          cacheSizeGB: 1
          directoryForIndexes: true
        collectionConfig:
          blockCompressor: zlib
        indexConfig:
          prefixCompression: true
    
    processManagement:
      fork: true
      pidFilePath: /opt/mongo_cluster/mongo_cfg/run/mongod_27017.pid
    
    net:
      port: 27017
      bindIp: 0.0.0.0
    
    replication:
      oplogSizeMB: 1024 
      replSetName: Test
    
  4. 添加监听28017端口的mongodb配置文件,该配置文件为启动多实例所用的配置文件,我们的仲裁节点的实例依赖此配置文件,执行vim /opt/mongo_cluster/mongo_cfg/conf/mongodb_28017.yaml,将下面的内容粘贴到该文件。

    systemLog:
      destination: file 
      logAppend: true 
      path: /opt/mongo_cluster/mongo_cfg/logs/mongodb_28017.log
    
    storage:
      journal:
        enabled: true
      dbPath: /opt/mongo_cluster/mongo_data/mongo_28017
      directoryPerDB: true
    
      wiredTiger:
        engineConfig:
          cacheSizeGB: 1
          directoryForIndexes: true
        collectionConfig:
          blockCompressor: zlib
        indexConfig:
          prefixCompression: true
    
    processManagement:
      fork: true
      pidFilePath: /opt/mongo_cluster/mongo_cfg/run/mongod_28017.pid
    
    net:
      port: 28017
      bindIp: 0.0.0.0
    
    replication:
      oplogSizeMB: 1024
      replSetName: Test
    
  5. 调整目录权限为mongo用户,否则无法启动

    chown mongo.mongo /opt/mongo_cluster/ -R
    
  6. 启动各节点的27017端口的实例

    #所有节点启动27017端口的实例(mdb01/mdb02/mdb03/mdb04)
    systemctl start mongod@27017
    #加入开机自启
    systemctl enable mongod@27017
    #验证各节点的服务状态信息
    systemctl status mongod@27017
    #注: 可使用xshell将命令发送到所有终端
    

    各节点服务状态信息:

    MDB01

    mdb01_service_status20190907182100

    MDB02

    mdb02_service_status20190907182213

    MDB03

    mdb03_service_status20190907182259

    MDB04

    mdb04_service_status20190907182337

  7. 启动mdb04(172.16.1.54)主机的28017端口的实例(仲裁)

    #其它节点不启动,仅mdb04启动,除了Master不能部署仲裁服务外,其它任何从节点都可以启动一个多实例作为仲裁服务,需要注意的是: 在我们的当前的架构中仅允许一个仲裁节点
    #也就是说我们的mdb04既做从(既做副本)又做仲裁节点
    systemctl start mongod@28017
    systemctl enable mongod@28017
    #查看服务状态
    systemctl status mongod@28017
    

    服务状态信息:

    mongodb_service_status20190907181656

添加集群配置

主节点的基本配置
  1. 登陆到主节点(mdb01)的27017端口实例

    mongo 127.0.0.1:27017
    

    查看有哪些库

    show dbs
    

    输出信息:

    MONGO_showdbs20190907181143

  2. 现在我们将从节点的IP地址信息添加到主节点的库内,执行以下JSON语句

    config = {
        _id : "Test",
        members : [
            {_id : 0, host : "172.16.1.51:27017"},
            {_id : 1, host : "172.16.1.52:27017"},
            {_id : 2, host : "172.16.1.53:27017"},
            {_id : 3, host : "172.16.1.54:27017"},
            {_id : 4, host : "172.16.1.54:28017", arbiterOnly: true},
        ]
    }
    rs.initiate(config)
    
  3. 查看各节点状态

    rs.status()
    

    如有以下输出,则表明集群已成功建立

    {
    	"set" : "Test",
    	"date" : ISODate("2019-09-07T15:54:11.571Z"),
    	"myState" : 1,
    	"term" : NumberLong(23),
    	"syncingTo" : "",
    	"syncSourceHost" : "",
    	"syncSourceId" : -1,
    	"heartbeatIntervalMillis" : NumberLong(2000),
    	"optimes" : {
    		"lastCommittedOpTime" : {
    			"ts" : Timestamp(1567871644, 1),
    			"t" : NumberLong(23)
    		},
    		"readConcernMajorityOpTime" : {
    			"ts" : Timestamp(1567871644, 1),
    			"t" : NumberLong(23)
    		},
    		"appliedOpTime" : {
    			"ts" : Timestamp(1567871644, 1),
    			"t" : NumberLong(23)
    		},
    		"durableOpTime" : {
    			"ts" : Timestamp(1567871644, 1),
    			"t" : NumberLong(23)
    		}
    	},
    	"members" : [
    		{
    			"_id" : 0,
    			"name" : "172.16.1.51:27017",
    			"health" : 1,
    			"state" : 1,
    			"stateStr" : "PRIMARY",
    			"uptime" : 70,
    			"optime" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDate" : ISODate("2019-09-07T15:54:04Z"),
    			"syncingTo" : "",
    			"syncSourceHost" : "",
    			"syncSourceId" : -1,
    			"infoMessage" : "",
    			"electionTime" : Timestamp(1567871622, 1),
    			"electionDate" : ISODate("2019-09-07T15:53:42Z"),
    			"configVersion" : 4,
    			"self" : true,
    			"lastHeartbeatMessage" : ""
    		},
    		{
    			"_id" : 1,
    			"name" : "172.16.1.52:27017",
    			"health" : 1,
    			"state" : 2,
    			"stateStr" : "SECONDARY",
    			"uptime" : 67,
    			"optime" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDurable" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDate" : ISODate("2019-09-07T15:54:04Z"),
    			"optimeDurableDate" : ISODate("2019-09-07T15:54:04Z"),
    			"lastHeartbeat" : ISODate("2019-09-07T15:54:11.019Z"),
    			"lastHeartbeatRecv" : ISODate("2019-09-07T15:54:09.919Z"),
    			"pingMs" : NumberLong(1),
    			"lastHeartbeatMessage" : "",
    			"syncingTo" : "172.16.1.51:27017",
    			"syncSourceHost" : "172.16.1.51:27017",
    			"syncSourceId" : 0,
    			"infoMessage" : "",
    			"configVersion" : 4
    		},
    		{
    			"_id" : 2,
    			"name" : "172.16.1.53:27017",
    			"health" : 1,
    			"state" : 2,
    			"stateStr" : "SECONDARY",
    			"uptime" : 67,
    			"optime" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDurable" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDate" : ISODate("2019-09-07T15:54:04Z"),
    			"optimeDurableDate" : ISODate("2019-09-07T15:54:04Z"),
    			"lastHeartbeat" : ISODate("2019-09-07T15:54:11.015Z"),
    			"lastHeartbeatRecv" : ISODate("2019-09-07T15:54:10.983Z"),
    			"pingMs" : NumberLong(1),
    			"lastHeartbeatMessage" : "",
    			"syncingTo" : "172.16.1.51:27017",
    			"syncSourceHost" : "172.16.1.51:27017",
    			"syncSourceId" : 0,
    			"infoMessage" : "",
    			"configVersion" : 4
    		},
    		{
    			"_id" : 3,
    			"name" : "172.16.1.54:27017",
    			"health" : 1,
    			"state" : 2,
    			"stateStr" : "SECONDARY",
    			"uptime" : 67,
    			"optime" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDurable" : {
    				"ts" : Timestamp(1567871644, 1),
    				"t" : NumberLong(23)
    			},
    			"optimeDate" : ISODate("2019-09-07T15:54:04Z"),
    			"optimeDurableDate" : ISODate("2019-09-07T15:54:04Z"),
    			"lastHeartbeat" : ISODate("2019-09-07T15:54:11.021Z"),
    			"lastHeartbeatRecv" : ISODate("2019-09-07T15:54:11.451Z"),
    			"pingMs" : NumberLong(1),
    			"lastHeartbeatMessage" : "",
    			"syncingTo" : "172.16.1.53:27017",
    			"syncSourceHost" : "172.16.1.53:27017",
    			"syncSourceId" : 2,
    			"infoMessage" : "",
    			"configVersion" : 4
    		},
    		{
    			"_id" : 4,
    			"name" : "172.16.1.54:28017",
    			"health" : 1,
    			"state" : 7,
    			"stateStr" : "ARBITER",
    			"uptime" : 67,
    			"lastHeartbeat" : ISODate("2019-09-07T15:54:11.020Z"),
    			"lastHeartbeatRecv" : ISODate("2019-09-07T15:54:09.918Z"),
    			"pingMs" : NumberLong(1),
    			"lastHeartbeatMessage" : "",
    			"syncingTo" : "",
    			"syncSourceHost" : "",
    			"syncSourceId" : -1,
    			"infoMessage" : "",
    			"configVersion" : 4
    		}
    	],
    	"ok" : 1,
    	"operationTime" : Timestamp(1567871644, 1),
    	"$clusterTime" : {
    		"clusterTime" : Timestamp(1567871644, 1),
    		"signature" : {
    			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
    			"keyId" : NumberLong(0)
    		}
    	}
    }
    

注: 从侧默认没法用命令读内容,需要执行rs.slaveOk()或将该值写入用户家目录下的.mongorc.js文件内。

测试

打开4个终端窗口,登陆各自的27017端口服务,观察提示符的变化。

  • 停掉当前的PRIMARY节点的27017端口服务,观察其它窗口能否发生故障转移(需要键入回车交互)
    • 过程略,成功转移。
  • 在停掉一个转移后的PRIMARY节点,看看能否再次执行故障转移
    • 过程略,成功转移。
  • 停掉3个SECONDARY,观察PRIMARY节点的变化
    • 过程略,主节点会变为SECONDARY

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×