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

搭建高可用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作高可用來提示總體高可用。

©著做權歸做者全部:來自51CTO博客做者KaliArch的原創做品,如需轉載,請註明出處,不然將追究法律責任

你的鼓勵讓我更有動力

相關文章
相關標籤/搜索