高可用的MongoDB集羣

1.序言

  MongoDB 是一個可擴展的高性能,開源,模式自由,面向文檔的數據庫。 它使用 C++編寫。MongoDB 包含一下特色:linux

  • l  面向集合的存儲:適合存儲對象及JSON形式的數據。程序員

  • l  動態查詢:Mongo 支持豐富的查詢方式,查詢指令使用 JSON 形式的標記,可輕易查詢文檔中內嵌的對象及數組。mongodb

  • l  完整的索引支持:包括文檔內嵌對象及數組。Mongo 的查詢優化器會分析查詢表達式,並生成一個高效的查詢計劃。數據庫

  • l  查詢監視:Mongo包含一個監控工具用於分析數據庫操做性能。數組

  • l  複製及自動故障轉移:Mongo 數據庫支持服務器之間的數據複製,支持主-從模式及服務器之間的相互複製。複製的主要目的是提供冗餘及自動故障轉移。緩存

  • l  高效的傳統存儲方式:支持二進制數據及大型對象(如:照片或圖片)。服務器

  • l  自動分片以支持雲級別的伸縮性:自動分片功能支持水平的數據庫集羣,可動態添加額外的機器。架構

2.背景

  MongoDB 的主要目標是在鍵值對存儲方式(提供了高性能和高度伸縮性) 以及傳統的 RDBMS(關係性數據庫)系統,集二者的優點於一身。Mongo 使用 一下場景:app

  • l  網站數據:Mongo 很是適合實時的插入,更新與查詢,並具有網站實時數據存儲所需的複製及高度伸縮性。
  • l  緩存:因爲性能很高,Mongo 也適合做爲信息基礎設施的緩存層。在系統重啓以後,由 Mongo 搭建的持久化緩存能夠避免下層的數據源過載。 
  • l  大尺寸,低價值的數據:使用傳統的關係數據庫存儲一些數據時可能會比較貴,在此以前,不少程序員每每會選擇傳統的文件進行存儲。
  • l  高伸縮性的場景:Mongo很是適合由數十或數百臺服務器組成的數據庫
  • l  用於對象及JSON數據的存儲:Mongo的BSON數據格式很是適合文檔格式化的存儲及查詢。

  注:這裏須要說明下,本文旨在介紹高可用的 MongoDB 集羣;這裏不討論 Hadoop 平臺的 HDFS。可根據公司實際業務需求,選擇合適的存儲系統。工具

  固然 MongDB 也有不適合的場景:

  • l  高度事務性的系統:例如銀行或會計系統。傳統的關係型數據庫目前仍是更適用於須要大量原子性複製事物的應用程序。

  • l  傳統的商業智能應用:針對特定問題的 BI 數據庫會對產生高度優化的查詢方式。對於此類應用,數據倉庫可能時更適合的選擇(如Hadoop套件中的Hive)。

  • l  須要SQL的問題。 

3.搭建

3.1環境準備

  在 Mongo 的官網下載 Linux 版本安裝包,而後解壓到對應的目錄下;因爲資源有限,咱們採用 Replica Sets + Sharding 方式來配置高可用。結構圖以下所示:

 

  這裏我說明下這個圖所表達的意思。

  • l Shard服務器:使用Replica Sets確保每一個數據節點都具備備份、自動容錯轉移、自動恢復的能力。
  • l  配置服務器:使用使用3個配置服務器確保元數據完整性。

  • l  路由進程:使用3個路由進程實現平衡,提升客戶端接入性能

  • l  3 個分片進程:Shard11,Shard12,Shard13 組成一個副本集,提供Sharding 中 shard1 的功能。

  • l  3 個分片進程:Shard21,Shard22,Shard23 組成一個副本集,提供Sharding 中 Shard2 的功能。

  • l  3個配置服務器進程和3個路由器進程。

  構建一個 mongoDB Sharding Cluster 須要三種角色:shard 服務器(ShardServer)、配置服務器(config Server)、路由進程(Route Process)

  Shard 服務器

  shard 服務器即存儲實際數據的分片,每一個 shard 能夠是一個 mongod 實例, 也能夠是一組 mongod 實例構成的 Replica Sets.爲了實現每一個 Shard 內部的故障 自動轉換,MongoDB 官方建議每一個 shard 爲一組 Replica Sets.
  配置服務器

  爲了將一個特定的 collection 存儲在多個 shard 中,須要爲該 collection 指定 一個 shard key,決定該條記錄屬於哪一個 chunk,配置服務器能夠存儲如下信息, 每一個shard節點的配置信息,每一個chunk的shard key範圍,chunk在各shard 的分佈狀況,集羣中全部 DB 和 collection 的 sharding 配置信息。
  路由進程

  它是一個前段路由,客戶端由此接入,首先詢問配置服務器須要到哪一個 shard 上查詢或保存記錄,而後鏈接相應的 shard 執行操做,最後將結果返回給客戶端,客 戶端只須要將本來發給 mongod 的查詢或更新請求原封不動地發給路由進程,而 沒必要關心所操做的記錄存儲在哪一個 shard 上。

按照架構圖,理論上是須要 16 臺機器的,因爲資源有限,用目錄來替代物理機(有風險,若其中某臺機器宕機,配置在該機器的服務都會 down 掉),下面給出配置表格: 

服務器

Host

服務和端口

1

10.211.55.28

Shard11:10011 Shard21:10021 ConfigSvr:10031 Mongos:10040

2

10.211.55.28

Shard12:10012 Shard22:10022 ConfigSvr:10032 Mongos:10042

3       

10.211.55.28

Shard13:10013 Shard23:10023 ConfigSvr:10033 Mongos:10043

3.2.環境變量

  下面給出 MongoDB 的環境變量配置,輸入命令並配置: 

[root@mongo ~]# vi /etc/profile
export MONGO_HOME=/root/mongodb-linux-x86_64-2.6.7 
export PATH=$PATH:$MONGO_HOME/bin

  而後保存退出,輸入如下命令配置文件當即生效:

[root@mongo ~]# . /etc/profile

3.3.配置 Shard+Replica Sets

  咱們分別啓動 Shard1 的全部進程,並設置副本集爲:shard1。下面給出啓動 Shard1 的腳本文件。

  • l shard11.conf 
dbpath=/mongodb/data/shard11 
logpath=/mongodb/log/shard11.log
pidfilepath=/mongodb/pid/shard11.pid
directoryperdb=true logappend=true replSet=shard1 port=10011 fork=true shardsvr=true journal=true
  • l shard12.conf 
dbpath=/mongodb/data/shard12 
logpath=/mongodb/log/shard12.log
pidfilepath=/mongodb/pid/shard12.pid directoryperdb=true logappend=true replSet=shard1 port=10012 fork=true shardsvr=true journal=true
  • l shard13.conf 
dbpath=/mongodb/data/shard13 
logpath=/mongodb/log/shard13.log 
pidfilepath=/mongodb/pid/shard13.pid 
directoryperdb=true
logappend=true 
replSet=shard1 
port=10013 
fork=true 
shardsvr=true 
journal=true
  • l shard21.conf 
dbpath=/mongodb/data/shard21
logpath=/mongodb/log/shard21.log 
pidfilepath=/mongodb/pid/shard21.pid 
directoryperdb=true
logappend=true 
replSet=shard2 
port=10021 
fork=true 
shardsvr=true 
journal=true
  • l shard22.conf 

 

dbpath=/mongodb/data/shard22
logpath=/mongodb/log/shard22.log 
pidfilepath=/mongodb/pid/shard22.pid 
directoryperdb=true
logappend=true 
replSet=shard2 
port=10022
fork=true 
shardsvr=true 
journal=true
  • l shard23.conf 
dbpath=/mongodb/data/shard23
logpath=/mongodb/log/shard23.log 
pidfilepath=/mongodb/pid/shard23.pid 
directoryperdb=true
logappend=true 
replSet=shard2 
port=10023
fork=true 
shardsvr=true 
journal=true
  • l config1.conf 
dbpath=/mongodb/config/config1 
logpath=/mongodb/log/config1.log
pidfilepath=/mongodb/pid/config1.pid directoryperdb=true logappend=true port=10031 fork=true configsvr=true journal=true
  • l config2.conf 
dbpath=/mongodb/config/config2 
logpath=/mongodb/log/config2.log 
pidfilepath=/mongodb/pid/config2.pid 
directoryperdb=true
logappend=true 
port=10032 
fork=true 
configsvr=true 
journal=true
  • l config3.conf 
dbpath=/mongodb/config/config3 
logpath=/mongodb/log/config3.log 
pidfilepath=/mongodb/pid/config3.pid 
directoryperdb=true
logappend=true 
port=10033 
fork=true 
configsvr=true 
journal=true
  • route.conf 
configdb=mongo:10031,mongo:10032,mongo:10033 
pidfilepath=/mongodb/pid/route.pid port=10040 chunkSize=1 logpath=/mongodb/log/route.log logappend=true fork=true
  • route2.conf 
configdb=mongo:10031,mongo:10032,mongo:10033 
pidfilepath=/mongodb/pid/route.pid
port=10042
chunkSize=1
logpath=/mongodb/log/route2.log 
logappend=true
fork=true
  • route3.conf 
configdb=mongo:10031,mongo:10032,mongo:10033 
pidfilepath=/mongodb/pid/route3.pid
port=10043
chunkSize=1
logpath=/mongodb/log/route3.log 
logappend=true
fork=true

  注:配置文件中的目錄必須存在,不存在需建立。

3.4.啓動批處理 

  下面給出啓動批處理的腳本,內容以下:

mongod -f /etc/shard11.conf
mongod -f /etc/shard12.conf
mongod -f /etc/shard13.conf
mongod -f /etc/shard21.conf
mongod -f /etc/shard22.conf
mongod -f /etc/shard23.conf
mongod -f /etc/config1.conf
mongod -f /etc/config2.conf
mongod -f /etc/config3.conf
mongos -f /etc/route.conf
mongos -f /etc/route2.conf
mongos -f /etc/route3.conf 

3.5.參數說明

dbpath:數據存放目錄
logpath:日誌存放路徑 logappend:以追加的方式記錄日誌
replSet:replica set 的名字
port:mongodb 進程所使用的端口號,默認爲 27017 fork:之後臺方式運行進程

journal:寫日誌
smallfiles:當提示空間不夠時添加此參數
其餘參數
pidfilepath:進程文件,方便中止 mongodb directoryperdb:爲每個數據庫按照數據庫名創建文件夾存放 bind_ip:mongodb 所綁定的 ip 地址
oplogSize:mongodb 操做日誌文件的最大大小。單位爲 Mb,默認爲硬盤剩餘 空間的 5%
noprealloc:不預先分配存儲
shardsvr:分片
configsvr:配置服務節點
configdb:配置 config 節點到 route 節點 

3.6.配置分片的表和片鍵 

  首先,咱們須要登陸到路由節點,這裏咱們登陸到其中一個 10040 端口下的節點。輸入以下命令: 

mongo mongo:10040
use admin 
db.runCommand({addshard:
"shard1/mongo:10011,mongo:10012,mongo:10013"})
db.runCommand({addshard:"shard2/mongo:10021,mongo:10022,mongo:10023"})
db.runCommand({ listshards:1 }) #列出 shard 個數
db.runCommand({enablesharding:"friends"}); #建立 friends 庫 db.runCommand( { shardcollection : "friends.user",key : {id: 1},unique : true } ) # 使用 user 表來作分片,片鍵爲 id 且惟一

3.7.驗證 

  至此,整個集羣的搭建完成,下面咱們測試集羣的高可用性。下面給出截圖:

  首先是查看集羣的狀態圖 :

  能夠看到,集羣中存有數據,這是我以前爲了測試存的數據,注意,Mongo 只有數據達到必定量纔會分片,全部我插入的數據比較大,每次測試都是 10w 的記錄插入。

  下面,我 kill 掉 shard11 服務,看會發生什麼狀況?截圖以下: 

  這裏我已經 kill 了 shard11 的進程服務。接下來,咱們在 10040 端口的路由 節點輸入:db.user.stats()查看狀態,顯示運行正常。截圖以下所示: 

 

  一樣能夠在該路由節點插入 10w 條記錄,看是否成功,下面給出插入腳本, 內容以下: 

for(var i=1;i<=100000;i++)db.user.save({id:i,value1:"1234567890",value2:"1234567890",value3:"123 4567890",value4:"1234567890"});

4.總結

  這片文章就分享到這裏,若在研究的過程當中有什麼問題能夠加羣討論或發送郵件給我,我會盡我所能爲您解答,與君共勉!

相關文章
相關標籤/搜索