1. 程式人生 > >高可用的MongoDB集群

高可用的MongoDB集群

dir 重啟 解答 驗證 rtl 事務 blog mon 腳本

1.序言

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

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

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

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

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

  • l? 復制及自動故障轉移:Mongo 數據庫支持服務器之間的數據復制,支持主-從模式及服務器之間的相互復制。復制的主要目的是提供冗余及自動故障轉移。

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

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

2.背景

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

  • 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.總結

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

轉載:http://www.cnblogs.com/smartloli/

高可用的MongoDB集群