zanePerfor前端效能監控系統高可用之Mongodb副本集讀寫分離架構

zane1發表於2018-11-14

HI!,你好,我是zane,zanePerfor是一款最近我開發的一個前端效能監控平臺,現在支援web瀏覽器端和微信小程式段。

我定義為一款完整,高效能,高可用的前端效能監控系統,這是未來會達到的目的,現今的架構也基本支援了高可用,高效能的部署。實際上還不夠,在很多地方還有優化的空間,我會持續的優化和升級。

開源不易,如果你也熱愛技術,擁抱開源,希望能小小的支援給個star。

專案的github地址:

github.com/wangweiange…

專案開發文件說明:

blog.seosiwei.com/performance…


Mongodb副本集架構

優勢:

MongoDB 副本集(Replica Set)是有自動故障恢復功能的主從叢集,有一個Primary節點和一個或多個Secondary節點組成。

當主節點掛掉之後,會由多個副本節點選舉產生出新的主節點。(節點數請保持為基數個)。

這樣就能保證應用的高可用,其中一個或多個節點掛掉之後還能正常執行和服務。

劣勢:

資料丟失:主節點掛掉之後,副本節點選舉出新的主節點需要一定的時間,這段時間會造成資料的丟失。

不能承受高吞吐量:副本集架構追根還是單機執行寫任務,在高併發應用中效能受限,不能解決流量洪峰時的實時讀寫。

不能完全保證專案的高可用:在副本集的環境中,要是所有的Secondary都當機了,只剩下Primary。最後Primary會變成Secondary,將不能再提供服務。

總結:

在大多數情況下推薦使用副本集架構,副本集架構在保證高可用的同時還能降低伺服器成本,相對於叢集分片來說配置也更簡單,更易於維護,具體選擇什麼架構需要根據自己的專案來覺定。


Mongodb副本集架構搭建:

Mongodb副本集搭建比價簡單,你只需要根據下面的步驟一步一步操作即可(以下內容以Linux或mac為例進行搭建)。

一:安裝Mongodb (略)

請參考: LINUX系統下安裝mongodb

關於副本集搭建還可參考我的另一篇文章: MongoDB主從副本集架構


二:副本集搭建

(備註:鑑於成本,以下內容在單機下部署為例,多機部署只需要替換下IP即可)

1、建立資料和日誌存放目錄

// 資料存放目錄
mkdir -p /data/replication/s0
mkdir -p /data/replication/s1
mkdir -p /data/replication/s2
// 日誌存放目錄
mkdir -p /data/replication/log複製程式碼

2、啟動Mongodb服務

(下面以28100,28101,28100三個埠為例)
// 啟動mongodb服務
mongod --dbpath /data/replication/s0 --logpath /data/replication/log/s0.log --fork --smallfiles --port 28100 --replSet rs1
mongod --dbpath /data/replication/s1 --logpath /data/replication/log/s1.log --fork --smallfiles --port 28101 --replSet rs1
mongod --dbpath /data/replication/s2 --logpath /data/replication/log/s2.log --fork --smallfiles --port 28102 --replSet rs1複製程式碼
  • --dbpath:存放資料目錄

  • --logpath:存放日誌目錄

  • --smallfiles:是否使用較小的預設檔案。預設為false,不使用。

  • --replSet: 副本集名稱,副本集名稱必須一致

進入28100服務設定副本集

// 登入 mongodb
mongo localhost:28100

// 切換到admin使用者
use admin

// 初始化副本集
rs.initiate({_id:"rs1",members:[{_id:0,host:"127.0.0.1:28100"},{_id:1,host:"127.0.0.1:28101"},{_id:2,host:"127.0.0.1:28102"}]})

// 檢視副本集狀態
rs.status()複製程式碼


副本集設定成功之後,檢視狀態會看到如下資訊即標識成功。

{
	"set" : "rs1",
	"date" : ISODate("2018-11-14T08:40:44.659Z"),
	"myState" : 1,
	"term" : NumberLong(2),
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1542184835, 1),
			"t" : NumberLong(2)
		},
		"readConcernMajorityOpTime" : {
			"ts" : Timestamp(1542184835, 1),
			"t" : NumberLong(2)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1542184835, 1),
			"t" : NumberLong(2)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1542184835, 1),
			"t" : NumberLong(2)
		}
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "127.0.0.1:28100",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 5977,
			"optime" : {
				"ts" : Timestamp(1542184835, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2018-11-14T08:40:35Z"),
			"electionTime" : Timestamp(1542178880, 1),
			"electionDate" : ISODate("2018-11-14T07:01:20Z"),
			"configVersion" : 1,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "127.0.0.1:28101",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 5970,
			"optime" : {
				"ts" : Timestamp(1542184835, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1542184835, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2018-11-14T08:40:35Z"),
			"optimeDurableDate" : ISODate("2018-11-14T08:40:35Z"),
			"lastHeartbeat" : ISODate("2018-11-14T08:40:43.345Z"),
			"lastHeartbeatRecv" : ISODate("2018-11-14T08:40:43.603Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "127.0.0.1:28102",
			"configVersion" : 1
		},
		{
			"_id" : 2,
			"name" : "127.0.0.1:28102",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 5970,
			"optime" : {
				"ts" : Timestamp(1542184835, 1),
				"t" : NumberLong(2)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1542184835, 1),
				"t" : NumberLong(2)
			},
			"optimeDate" : ISODate("2018-11-14T08:40:35Z"),
			"optimeDurableDate" : ISODate("2018-11-14T08:40:35Z"),
			"lastHeartbeat" : ISODate("2018-11-14T08:40:43.345Z"),
			"lastHeartbeatRecv" : ISODate("2018-11-14T08:40:43.575Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "127.0.0.1:28100",
			"configVersion" : 1
		}
	],
	"ok" : 1,
	"operationTime" : Timestamp(1542184835, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1542184835, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}複製程式碼


3、設定Mongodb副本可讀

在mac和linux系統中,一般在~目錄下會有個.mongorc.js檔案,給此檔案新增一句rs.slaveOk();即可。

​檢視是否有次檔案:


cd ~
ll -a複製程式碼

若無,則全域性查詢:

// 全域性搜尋
sudo find / -name .mongorc.js複製程式碼

新增rs.slaveOk();

vi ~/.mongorc.js

// 此檔案預設為空
// 增加一行,儲存退出
rs.slaveOk();複製程式碼

重啟Mongodb,這時所有副本節點都可讀。


在zanePerfor (前端效能監控平臺)生產環境中使用,並做讀寫分離。

一:找到專案的 config/config.prod.js檔案

更改如下Mongodb配置即可:
// mongodb 服務
// 此處替換 url 引數為連結副本集方式即可
const dbclients = {
        db3: {
           url: 'mongodb://127.0.0.1:28100,127.0.0.1:28101,127.0.0.1:28102/performance?replicaSet=rs1',
            options: {
                poolSize: 100,
                keepAlive: 10000,
                connectTimeoutMS: 10000,
                autoReconnect: true,
                reconnectTries: 100,
                reconnectInterval: 1000,
            },
        },
 };複製程式碼


讀寫分離:

專案所有查詢已經做好了讀寫分離操作,例如查詢page頁列表,其他皆如此即可,這樣就保證了服務的讀寫壓力(主節點負責寫資料,副本節點負責讀取資料)。

zanePerfor前端效能監控系統高可用之Mongodb副本集讀寫分離架構

read引數說明

primary - (預設值)    只從主節點讀取。如果主節點不可用則報錯。不能跟 tags 選項組合使用。
secondary            只有當從節點可用時,從中讀取,否則報錯。
primaryPreferred     優先讀取主節點,不可用時讀取從節點。
secondaryPreferred   優先讀取從節點,不可用時讀取主節點。
nearest              所有操作都讀最近的候選節點,不同於其他模式,該選項會隨機選取所有主、從節點。複製程式碼

選項別名:

p   primary
pp  primaryPreferred
s   secondary
sp  secondaryPreferred
n   nearest複製程式碼

zanePerfor下一步篇:

zanePerfor前端效能監控平臺高可用之Mongodb叢集分片架構

zanePerfor github地址:

github.com/wangweiange…

zanePerfor 開發文件:

blog.seosiwei.com/performance…


相關文章