搭建高可用MongoDB集羣(分片)

MongoDB基礎請參考:https://blog.51cto.com/kaliarch/2044423前端

MongoDB(replica set)請參考:http://www.javashuo.com/article/p-evgbnpka-kx.htmllinux

1、概述mongodb

1.1 背景數據庫

爲解決mongodb在replica set每一個從節點上面的數據庫均是對數據庫的全量拷貝,從節點壓力在高併發大數據量的場景下存在很大挑戰,同時考慮到後期mongodb集羣的在數據壓力巨大時的擴展性,應對海量數據引出了分片機制。後端

1.2 分片概念緩存

分片是將數據庫進行拆分,將其分散在不一樣的機器上的過程,無需功能強大的服務器就能夠存儲更多的數據,處理更大的負載,在總數據中,將集合切成小塊,將這些塊分散到若干片中,每一個片只負載總數據的一部分,經過一個知道數據與片對應關係的組件mongos的路由進程進行操做。bash

1.3 基礎組件服務器

其利用到了四個組件:mongos,config server,shard,replica set網絡

mongos:數據庫集羣請求的入口,全部請求須要通過mongos進行協調,無需在應用層面利用程序來進行路由選擇,mongos其自身是一個請求分發中心,負責將外部的請求分發到對應的shard服務器上,mongos做爲統一的請求入口,爲防止mongos單節點故障,通常須要對其作HA。架構

config server:配置服務器,存儲全部數據庫元數據(分片,路由)的配置。mongos自己沒有物理存儲分片服務器和數據路由信息,只是存緩存在內存中來讀取數據,mongos在第一次啓動或後期重啓時候,就會從config server中加載配置信息,若是配置服務器信息發生更新會通知全部的mongos來更新本身的狀態,從而保證準確的請求路由,生產環境中一般也須要多個config server,防止配置文件存在單節點丟失問題。

shard:在傳統意義上來說,若是存在海量數據,單臺服務器存儲1T壓力很是大,不管考慮數據庫的硬盤,網絡IO,又有CPU,內存的瓶頸,若是多臺進行分攤1T的數據,到每臺上就是可估量的較小數據,在mongodb集羣只要設置好分片規則,經過mongos操做數據庫,就能夠自動把對應的操做請求轉發到對應的後端分片服務器上。

replica set:在整體mongodb集羣架構中,對應的分片節點,若是單臺機器下線,對應整個集羣的數據就會出現部分缺失,這是不能發生的,所以對於shard節點須要replica set來保證數據的可靠性,生產環境一般爲2個副本+1個仲裁。

1.4 架構圖

圖片.png

2、安裝部署

2.1 基礎環境

爲了節省服務器,採用多實例配置,三個mongos,三個config server,單個服務器上面運行不通角色的shard(爲了後期數據分片均勻,將三臺shard在各個服務器上充當不一樣的角色。),在一個節點內採用replica set保證高可用,對應主機與端口信息以下:

主機名
IP地址
組件mongos
組件config server
shard



mongodb-1




172.20.6.10



 

  端口:20000



端口:21000

主節點:   22001
副本節點:22002
仲裁節點:22003


mongodb-2


172.20.6.11


  端口:20000


端口:21000

仲裁節點:22001
主節點:   22002
副本節點:22003


mongodb-3


172.20.6.12


  端口:20000


端口:21000

副本節點:22001
仲裁節點:22002
主節點:   22003

圖片.png

2.二、安裝部署

2.2.1 軟件下載目錄建立

wget -c https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.10.tgz
tar -zxvf mongodb-linux-x86_64-rhel62-3.4.10.tgz
ln -sv mongodb-linux-x86_64-rhel62-3.4.10 mongodb
echo "PATH=$PAHT:/usr/local/mongodb/bin">/etc/profile.d/mongodb.sh
source /etc/profile.d/mongodb.sh

2.2.2 建立目錄

分別在mongodb-1/mongodb-2/mongodb-3建立目錄及日誌文件

mkdir -p /data/mongodb/mongos/{log,conf}
mkdir -p /data/mongodb/mongoconf/{data,log,conf}
mkdir -p /data/mongodb/shard1/{data,log,conf}
mkdir -p /data/mongodb/shard2/{data,log,conf}
mkdir -p /data/mongodb/shard3/{data,log,conf}
touch /data/mongodb/mongos/log/mongos.log
touch /data/mongodb/mongoconf/log/mongoconf.log
touch /data/mongodb/shard1/log/shard1.log
touch /data/mongodb/shard2/log/shard2.log
touch /data/mongodb/shard3/log/shard3.log

2.2.3 配置config server副本集

在mongodb3.4版本後要求配置服務器也建立爲副本集,在此副本集名稱:replconf

在三臺服務器上配置config server副本集配置文件,並啓動服務

cat>/data/mongodb/mongoconf/conf/mongoconf.conf<<EOFdbpath=/data/mongodb/mongoconf/data
logpath=/data/mongodb/mongoconf/log/mongoconf.log        #定義config server日誌文件
logappend=true
port = 21000
maxConns = 1000            #連接數
journal = true            #日誌開啓
journalCommitInterval = 200
fork = true            #後臺執行
syncdelay = 60
oplogSize = 1000
configsvr = true        #配置服務器
replSet=replconf        #config server配置集replconf
EOF

mongod -f /data/mongodb/mongoconf/conf/mongoconf.conf        #三臺服務器均啓動config server

圖片.png

任意登陸一臺服務器進行配置服務器副本集初始化

use admin                
config = {_id:"replconf",members:[             
{_id:0,host:"172.20.6.10:21000"},
{_id:1,host:"172.20.6.11:21000"},
{_id:2,host:"172.20.6.12:21000"},]
}
rs.initiate(config);

圖片.png

查看集羣狀態:

replconf:OTHER> rs.status()
{
    "set" : "replconf",
    "date" : ISODate("2017-12-04T07:42:09.054Z"),
    "myState" : 1,
    "term" : NumberLong(1),
    "configsvr" : true,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1512373328, 1),
            "t" : NumberLong(1)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1512373328, 1),
            "t" : NumberLong(1)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1512373328, 1),
            "t" : NumberLong(1)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1512373328, 1),
            "t" : NumberLong(1)
        }
    },
    "members" : [
        {
            "_id" : 0,
            "name" : "172.20.6.10:21000",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 221,
            "optime" : {
                "ts" : Timestamp(1512373328, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T07:42:08Z"),
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1512373296, 1),
            "electionDate" : ISODate("2017-12-04T07:41:36Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "172.20.6.11:21000",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 42,
            "optime" : {
                "ts" : Timestamp(1512373318, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1512373318, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T07:41:58Z"),
            "optimeDurableDate" : ISODate("2017-12-04T07:41:58Z"),
            "lastHeartbeat" : ISODate("2017-12-04T07:42:08.637Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T07:42:07.648Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "172.20.6.10:21000",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "172.20.6.12:21000",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 42,
            "optime" : {
                "ts" : Timestamp(1512373318, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1512373318, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T07:41:58Z"),
            "optimeDurableDate" : ISODate("2017-12-04T07:41:58Z"),
            "lastHeartbeat" : ISODate("2017-12-04T07:42:08.637Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T07:42:07.642Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "172.20.6.10:21000",
            "configVersion" : 1
        }
    ],
    "ok" : 1
}

此時config server集羣已經配置完成,mongodb-1爲primary,mongdb-2/mongodb-3爲secondary

2.2.4 配置shard集羣

三臺服務器均進行shard集羣配置

shard1配置

cat >/data/mongodb/shard1/conf/shard.conf <<EOF
dbpath=/data/mongodb/shard1/data
logpath = /data/mongodb/shard1/log/shard1.log
port = 22001
logappend = true
nohttpinterface = true
fork = true
oplogSize = 4096
journal = true
#engine = wiredTiger
#cacheSizeGB = 38G
smallfiles=true
shardsvr=true        #shard服務器
replSet=shard1        #副本集名稱shard1
EOF

mongod -f /data/mongodb/shard1/conf/shard.conf        #啓動shard服務

圖片.png

查看此時服務已經正常啓動,shard1的22001端口已經正常監聽,接下來登陸mongodb-1服務器進行shard1副本集初始化

mongo 172.20.6.10:22001
use admin                
config = {_id:"shard1",members:[             
{_id:0,host:"172.20.6.10:22001"},
{_id:1,host:"172.20.6.11:22001",arbiterOnly:true},
{_id:2,host:"172.20.6.12:22001"},]
}
rs.initiate(config);

圖片.png

查看集羣狀態,只列出了部分信息:

{
            "_id" : 0,
            "name" : "172.20.6.10:22001",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",            #mongodb-1爲primary
            "uptime" : 276,
            "optime" : {
                "ts" : Timestamp(1512373911, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T07:51:51Z"),
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1512373879, 1),
            "electionDate" : ISODate("2017-12-04T07:51:19Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "172.20.6.11:22001",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",            #mongodb-2爲arbiter
            "uptime" : 45,
            "lastHeartbeat" : ISODate("2017-12-04T07:51:53.597Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T07:51:51.243Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "172.20.6.12:22001",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",        #mongodb-3爲secondary
            "uptime" : 45,
            "optime" : {
                "ts" : Timestamp(1512373911, 1),
                "t" : NumberLong(1)
            },

此時shard1 副本集已經配置完成,mongodb-1爲primary,mongodb-2爲arbiter,mongodb-3爲secondary。

一樣的操做進行shard2配置和shard3配置

注意:進行shard2的副本集初始化,在mongodb-2, 初始化shard3副本集在mongodb-3上進行操做。

shard2配置文件

cat >/data/mongodb/shard2/conf/shard.conf <<EOF
dbpath=/data/mongodb/shard2/data
logpath = /data/mongodb/shard2/log/shard2.log
port = 22002
logappend = true
nohttpinterface = true
fork = true
oplogSize = 4096
journal = true
#engine = wiredTiger
#cacheSizeGB = 38G
smallfiles=true
shardsvr=true
replSet=shard2
EOF

mongod -f /data/mongodb/shard2/conf/shard.conf

shard3配置文件

cat >/data/mongodb/shard3/conf/shard.conf <<EOF
dbpath=/data/mongodb/shard3/data
logpath = /data/mongodb/shard3/log/shard3.log
port = 22003
logappend = true
nohttpinterface = true
fork = true
oplogSize = 4096
journal = true
#engine = wiredTiger
#cacheSizeGB = 38G
smallfiles=true
shardsvr=true
replSet=shard3
EOF

mongod -f /data/mongodb/shard2/conf/shard.conf

圖片.png

在mongodb-2上進行shard2副本集初始化

mongo 172.20.6.11:22002    #登陸mongodb-2

use admin                
config = {_id:"shard2",members:[             
{_id:0,host:"172.20.6.10:22002"},
{_id:1,host:"172.20.6.11:22002"},
{_id:2,host:"172.20.6.12:22002",arbiterOnly:true},]
}
rs.initiate(config);

查看shard2副本集狀態

{
            "_id" : 0,
            "name" : "172.20.6.10:22002",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",        #mongodb-2爲secondary
            "uptime" : 15,
            "optime" : {
                "ts" : Timestamp(1512374668, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1512374668, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T08:04:28Z"),
            "optimeDurableDate" : ISODate("2017-12-04T08:04:28Z"),
            "lastHeartbeat" : ISODate("2017-12-04T08:04:30.527Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T08:04:28.492Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "172.20.6.11:22002",
            "configVersion" : 1
        },
        {
            "_id" : 1,
            "name" : "172.20.6.11:22002",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",        #mongodb-2爲primary
            "uptime" : 211,
            "optime" : {
                "ts" : Timestamp(1512374668, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T08:04:28Z"),
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1512374666, 1),
            "electionDate" : ISODate("2017-12-04T08:04:26Z"),
            "configVersion" : 1,
            "self" : true
        },
        {
            "_id" : 2,
            "name" : "172.20.6.12:22002",        #mongodb-3爲arbiter
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 15,
            "lastHeartbeat" : ISODate("2017-12-04T08:04:30.527Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T08:04:28.384Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 1
        }

登陸mongodb-3進行shard3副本集初始化

mongo 172.20.6.12:22003    #登陸mongodb-3

use admin                
config = {_id:"shard3",members:[             
{_id:0,host:"172.20.6.10:22003",arbiterOnly:true},
{_id:1,host:"172.20.6.11:22003"},
{_id:2,host:"172.20.6.12:22003"},]
}
rs.initiate(config);

查看shard3副本集狀態

{
            "_id" : 0,
            "name" : "172.20.6.10:22003",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",        #mongodb-1爲arbiter
            "uptime" : 18,
            "lastHeartbeat" : ISODate("2017-12-04T08:07:37.488Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T08:07:36.224Z"),
            "pingMs" : NumberLong(0),
            "configVersion" : 1
        },
        {
            "_id" : 1,
            "name" : "172.20.6.11:22003",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",        #mongodb-2爲secondary
            "uptime" : 18,
            "optime" : {
                "ts" : Timestamp(1512374851, 1),
                "t" : NumberLong(1)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1512374851, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T08:07:31Z"),
            "optimeDurableDate" : ISODate("2017-12-04T08:07:31Z"),
            "lastHeartbeat" : ISODate("2017-12-04T08:07:37.488Z"),
            "lastHeartbeatRecv" : ISODate("2017-12-04T08:07:36.297Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "172.20.6.12:22003",
            "configVersion" : 1
        },
        {
            "_id" : 2,
            "name" : "172.20.6.12:22003",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",        #mongodb-3爲primary
            "uptime" : 380,
            "optime" : {
                "ts" : Timestamp(1512374851, 1),
                "t" : NumberLong(1)
            },
            "optimeDate" : ISODate("2017-12-04T08:07:31Z"),
            "infoMessage" : "could not find member to sync from",
            "electionTime" : Timestamp(1512374849, 1),
            "electionDate" : ISODate("2017-12-04T08:07:29Z"),
            "configVersion" : 1,
            "self" : true
        }

此時shard集羣所有已經配置完畢。

2.2.5 配置路由服務器mongos

目前三臺服務器的配置服務器和分片服務器均已啓動,配置三臺mongos服務器

因爲mongos服務器的配置是從內存中加載,因此本身沒有存在數據目錄configdb鏈接爲配置服務器集羣

cat >/data/mongodb/mongos/conf/mongos.conf<<EOF
--logpath=/data/mongodb/mongos/log/mongos.log
logappend=true
port = 20000
maxConns = 1000
configdb=replconf/172.20.6.10:21000,172.20.6.11:21000,172.20.6.12:21000	   #制定config server集羣
fork = true
EOF

mongos -f /data/mongodb/mongos/conf/mongos.conf        #啓動mongos服務

圖片.png

目前config server集羣/shard集羣/mongos服務均已啓動,但此時爲設置分片,還不能使用分片功能。須要登陸mongos啓用分片

登陸任意一臺mongos

mongo 172.20.6.10:20000
use admin
db.runCommand({addshard:"shard1/172.20.6.10:22001,172.20.6.11:22001,172.20.6.12:22001"})
db.runCommand({addshard:"shard2/172.20.6.10:22002,172.20.6.11:22002,172.20.6.12:22002"})
db.runCommand({addshard:"shard3/172.20.6.10:22003,172.20.6.11:22003,172.20.6.12:22003"})

圖片.png

查看集羣

圖片.png

3、 測試

目前配置服務、路由服務、分片服務、副本集服務都已經串聯起來了,此時進行數據插入,數據可以自動分片。鏈接在mongos上讓指定的數據庫、指定的集合分片生效。

注意:設置分片須要在admin數據庫進行

use admin
db.runCommand( { enablesharding :"kaliarchdb"});    #開啓kaliarch庫分片功能
db.runCommand( { shardcollection : "kaliarchdb.table1",key : {_id:"hashed"} } )    #指定數據庫裏須要分片的集合tables和片鍵_id

設置kaliarchdb的 table1 表須要分片,根據 _id 自動分片到 shard1 ,shard2,shard3 上面去。

圖片.png

查看分片信息

圖片.png

測試插入數據

use kaliarchdb;
for (var i = 1; i <= 100000; i++) db.table1.save({_id:i,"test1":"testval1"});

圖片.png

查看分片狀況:(省去部分信息)

db.table1.stats()
{
    "sharded" : true,
    "capped" : false,
    "ns" : "kaliarchdb.table1",
    "count" : 100000,        #總count
    "size" : 3800000,
    "storageSize" : 1335296,
    "totalIndexSize" : 4329472,
    "indexSizes" : {
        "_id_" : 1327104,
        "_id_hashed" : 3002368
    },
    "avgObjSize" : 38,
    "nindexes" : 2,
    "nchunks" : 6,
    "shards" : {
        "shard1" : {
            "ns" : "kaliarchdb.table1",
            "size" : 1282690,
            "count" : 33755,        #shard1的count數
            "avgObjSize" : 38,
            "storageSize" : 450560,
            "capped" : false,
            ......

    "shard2" : {
                "ns" : "kaliarchdb.table1",
                "size" : 1259434,
                "count" : 33143,        #shard2的count數
                "avgObjSize" : 38,
                "storageSize" : 442368,
                "capped" : false,
            .......
    "shard3" : {
            "ns" : "kaliarchdb.table1",
            "size" : 1257876,    
            "count" : 33102,            #shard3的count數
            "avgObjSize" : 38,
            "storageSize" : 442368,
            "capped" : false,

此時架構中的mongos,config server,shard集羣均已經搭建部署完畢,在實際生成環境話須要對前端的mongos作高可用來提示總體高可用。

相關文章
相關標籤/搜索