MONGODB 分片集羣技術

1.1 MongoDB複製集簡介

  一組Mongodb複製集,就是一組mongod進程,這些進程維護同一個數據集合。複製集提供了數據冗餘和高等級的可靠性,這是生產部署的基礎。

1.1.1 複製集的目的

  保證數據在生產部署時的冗餘和可靠性,通過在不同的機器上保存副本來保證數據的不會因爲單點損壞而丟失。能夠隨時應對數據丟失、機器損壞帶來的風險。

  換一句話來說,還能提高讀取能力,用戶的讀取服務器和寫入服務器在不同的地方,而且,由不同的服務器爲不同的用戶提供服務,提高整個系統的負載。

1.1.2 簡單介紹

  一組複製集就是一組mongod實例掌管同一個數據集,實例可以在不同的機器上面。實例中包含一個主導,接受客戶端所有的寫入操作,其他都是副本實例,從主服務器上獲得數據並保持同步。

  主服務器很重要,包含了所有的改變操作(寫)的日誌。但是副本服務器集羣包含有所有的主服務器數據,因此當主服務器掛掉了,就會在副本服務器上重新選取一個成爲主服務器。

  每個複製集還有一個仲裁者,仲裁者不存儲數據,只是負責通過心跳包來確認集羣中集合的數量,並在主服務器選舉的時候作爲仲裁決定結果。

1.2 複製的基本架構

  基本的架構由3臺服務器組成,一個三成員的複製集,由三個有數據,或者兩個有數據,一個作爲仲裁者。

1.2.1 三個存儲數據的複製集

具有三個存儲數據的成員的複製集有:

一個主庫;

兩個從庫組成,主庫宕機時,這兩個從庫都可以被選爲主庫。

 

      當主庫宕機後,兩個從庫都會進行競選,其中一個變爲主庫,當原主庫恢復後,作爲從庫加入當前的複製集羣即可。

 

1.2.2 當存在arbiter節點

在三個成員的複製集中,有兩個正常的主從,及一臺arbiter節點:

    一個主庫

    一個從庫,可以在選舉中成爲主庫

    一個aribiter節點,在選舉中,只進行投票,不能成爲主庫

 

說明:

  由於arbiter節點沒有複製數據,因此這個架構中僅提供一個完整的數據副本。arbiter節點只需要更少的資源,代價是更有限的冗餘和容錯。

   當主庫宕機時,將會選擇從庫成爲主,主庫修復後,將其加入到現有的複製集羣中即可。

 

1.2.3 Primary選舉

  複製集通過replSetInitiate命令(或mongo shell的rs.initiate())進行初始化,初始化後各個成員間開始發送心跳消息,併發起Priamry選舉操作,獲得『大多數』成員投票支持的節點,會成爲Primary,其餘節點成爲Secondary。

『大多數』的定義

  假設複製集內投票成員(後續介紹)數量爲N,則大多數爲 N/2 + 1,當複製集內存活成員數量不足大多數時,整個複製集將無法選舉出Primary,複製集將無法提供寫服務,處於只讀狀態。

投票成員數

大多數

容忍失效數

1

1

0

2

2

0

3

2

1

4

3

1

5

3

2

6

4

2

7

4

3

  通常建議將複製集成員數量設置爲奇數,從上表可以看出3個節點和4個節點的複製集都只能容忍1個節點失效,從『服務可用性』的角度看,其效果是一樣的。(但無疑4個節點能提供更可靠的數據存儲)

1.3 複製集中成員說明

1.3.1 所有成員說明 

成員

說明

Secondary

正常情況下,複製集的Seconary會參與Primary選舉(自身也可能會被選爲Primary),並從Primary同步最新寫入的數據,以保證與Primary存儲相同的數據。

Secondary可以提供讀服務,增加Secondary節點可以提供複製集的讀服務能力,同時提升複製集的可用性。另外,Mongodb支持對複製集的Secondary節點進行靈活的配置,以適應多種場景的需求。

Arbiter

Arbiter節點只參與投票,不能被選爲Primary,並且不從Primary同步數據。

比如你部署了一個2個節點的複製集,1Primary1Secondary,任意節點宕機,複製集將不能提供服務了(無法選出Primary),這時可以給複製集添加一個Arbiter節點,即使有節點宕機,仍能選出Primary

Arbiter本身不存儲數據,是非常輕量級的服務,當複製集成員爲偶數時,最好加入一個Arbiter節點,以提升複製集可用性。

Priority0

Priority0節點的選舉優先級爲0,不會被選舉爲Primary

比如你跨機房AB部署了一個複製集,並且想指定Primary必須在A機房,這時可以將B機房的複製集成員Priority設置爲0,這樣Primary就一定會是A機房的成員。

(注意:如果這樣部署,最好將『大多數』節點部署在A機房,否則網絡分區時可能無法選出Primary

Vote0

Mongodb 3.0裏,複製集成員最多50個,參與Primary選舉投票的成員最多7個,其他成員(Vote0)的vote屬性必須設置爲0,即不參與投票。

Hidden

Hidden節點不能被選爲主(Priority0),並且對Driver不可見。因Hidden節點不會接受Driver的請求,可使用Hidden節點做一些數據備份、離線計算的任務,不會影響複製集的服務。

Delayed

Delayed節點必須是Hidden節點,並且其數據落後與Primary一段時間(可配置,比如1個小時)。

Delayed節點的數據比Primary落後一段時間,當錯誤或者無效的數據寫入Primary時,可通過Delayed節點的數據來恢復到之前的時間點。

1.3.2 Priority 0節點

  作爲一個輔助可以作爲一個備用。在一些複製集中,可能無法在合理的時間內添加新成員的時候。備用成員保持數據的當前最新數據能夠替換不可用的成員。

 

1.3.3 Hidden 節點(隱藏節點)

  客戶端將不會把讀請求分發到隱藏節點上,即使我們設定了 複製集讀選項 。

  這些隱藏節點將不會收到來自應用程序的請求。我們可以將隱藏節點專用於報表節點或是備份節點。 延時節點也應該是一個隱藏節點。

 

1.3.4 Delayed 節點(延時節點)

  延時節點的數據集是延時的,因此它可以幫助我們在人爲誤操作或是其他意外情況下恢復數據。

  舉個例子,當應用升級失敗,或是誤操作刪除了表和數據庫時,我們可以通過延時節點進行數據恢復。

 

1.4 配置MongoDB複製集

1.4.1 環境說明

系統環境說明:

[root@MongoDB ~]# cat /etc/redhat-release 
CentOS release 6.9 (Final)
[root@MongoDB ~]# uname -r2.6.32-696.el6.x86_64
[root@MongoDB ~]# /etc/init.d/iptables status
iptables: Firewall is not running.
[root@MongoDB ~]# getenforce 
Disabled
[root@MongoDB ~]# hostname -I10.0.0.152 172.16.1.152

軟件版本說明

  本次使用的mongodb版本爲:mongodb-linux-x86_64-3.2.8.tgz

1.4.2 前期準備,在root用戶下操作

  本次複製集複製採用Mongodb多實例進行

  所有的操作都基於安裝完成的mongodb服務,詳情參照:http://www.cnblogs.com/clsn/p/8214194.html#_label3

#創建mongod用戶
    useradd -u800 mongod
    echo 123456|passwd --stdin mongod 
# 安裝mongodb
    mkdir -p /mongodb/bin
   cd  /mongodb
   wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.2.8.tgz
    tar xf  mongodb-linux-x86_64-3.2.8.tgz
    cd mongodb-linux-x86_64-3.2.8/bin/ &&\
    cp * /mongodb/bin
    chown -R mongod.mongod /mongodb# 切換到mongod用戶進行後續操作
    su - mongod

1.4.3 創建所需目錄

for  i in 28017 28018 28019 28020
    do 
      mkdir -p /mongodb/$i/conf  
      mkdir -p /mongodb/$i/data  
      mkdir -p /mongodb/$i/logdone

1.4.4 配置多實例環境

編輯第一個實例配置文件

cat >>/mongodb/28017/conf/mongod.conf<<'EOF'systemLog:
  destination: file
  path: /mongodb/28017/log/mongodb.log
  logAppend: truestorage:
  journal:
    enabled: true
  dbPath: /mongodb/28017/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      # cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: trueprocessManagement:
  fork: truenet:
  port: 28017replication:
  oplogSizeMB: 2048
  replSetName: my_repl
EOF

複製配置文件

for i in 28018 28019 28020
  do  
   \cp  /mongodb/28017/conf/mongod.conf  /mongodb/$i/conf/done

修改配置文件

for i in 28018 28019 28020
  do 
    sed  -i  "s#28017#$i#g" /mongodb/$i/conf/mongod.confdone

啓動服務

for i in 28017 28018 28019 28020
  do  
    mongod -f /mongodb/$i/conf/mongod.conf 
done

# 關閉服務的方法

for i in 28017 28018 28019 28020
   do  
     mongod --shutdown  -f /mongodb/$i/conf/mongod.conf 
done

1.4.5 配置複製集

登陸數據庫,配置mongodb複製

shell> mongo --port 28017config = {_id: 'my_repl', members: [
                          {_id: 0, host: '10.0.0.152:28017'},
                          {_id: 1, host: '10.0.0.152:28018'},
                          {_id: 2, host: '10.0.0.152:28019'}]
          }

初始化這個配置

> rs.initiate(config)

     到此複製集配置完成

1.4.6 測試主從複製

在主節點插入數據

my_repl:PRIMARY> db.movies.insert([ { "title" : "Jaws", "year" : 1975, "imdb_rating" : 8.1 },
   { "title" : "Batman", "year" : 1989, "imdb_rating" : 7.6 },  ] );

在主節點查看數據

my_repl:PRIMARY> db.movies.find().pretty()
{
    "_id" : ObjectId("5a4d9ec184b9b2076686b0ac"),
    "title" : "Jaws",
    "year" : 1975,
    "imdb_rating" : 8.1}
{
    "_id" : ObjectId("5a4d9ec184b9b2076686b0ad"),
    "title" : "Batman",
    "year" : 1989,
    "imdb_rating" : 7.6}

  注:在mongodb複製集當中,默認從庫不允許讀寫。

在從庫打開配置(危險)

      注意:嚴禁在從庫做任何修改操作

my_repl:SECONDARY> rs.slaveOk()
my_repl:SECONDARY> show tables;
movies
my_repl:SECONDARY> db.movies.find().pretty()
{
    "_id" : ObjectId("5a4d9ec184b9b2076686b0ac"),
    "title" : "Jaws",
    "year" : 1975,
    "imdb_rating" : 8.1}
{
    "_id" : ObjectId("5a4d9ec184b9b2076686b0ad"),
    "title" : "Batman",
    "year" : 1989,
    "imdb_rating" : 7.6}

  在從庫查看完成在登陸到主庫

1.4.7 複製集管理操作

(1)查看複製集狀態:

rs.status();     # 查看整體複製集狀態
rs.isMaster();   #  查看當前是否是主節點

(2)添加刪除節點

rs.add("ip:port");     #  新增從節點
rs.addArb("ip:port"); #  新增仲裁節點
rs.remove("ip:port"); #  刪除一個節點

注:

添加特殊節點時,

  1>可以在搭建過程中設置特殊節點

  2>可以通過修改配置的方式將普通從節點設置爲特殊節點

  /*找到需要改爲延遲性同步的數組號*/;

(3)配置延時節點(一般延時節點也配置成hidden

cfg=rs.conf() 
cfg.members[2].priority=0cfg.members[2].slaveDelay=120cfg.members[2].hidden=true

     注:這裏的2是rs.conf()顯示的順序(除主庫之外),非ID

重寫複製集配置

rs.reconfig(cfg)

   也可將延時節點配置爲arbiter節點

cfg.members[2].arbiterOnly=true

配置成功後,通過以下命令查詢配置後的屬性

rs.conf();

1.4.8 副本集其他操作命令

查看副本集的配置信息

my_repl:PRIMARY> rs.config()

查看副本集各成員的狀態

my_repl:PRIMARY> rs.status()

1.4.8.1  副本集角色切換(不要人爲隨便操作)

rs.stepDown()
rs.freeze(300)  # 鎖定從,使其不會轉變成主庫,freeze()和stepDown單位都是秒。
rs.slaveOk()    # 設置副本節點可讀:在副本節點執行

   插入數據

> use app
switched to db app
app> db.createCollection('a')
{ "ok" : 0, "errmsg" : "not master", "code" : 10107 }

查看副本節點

> rs.printSlaveReplicationInfo()
source: 192.168.1.22:27017
    syncedTo: Thu May 26 2016 10:28:56 GMT+0800 (CST)    0 secs (0 hrs) behind the primary

MongoDB分片(Sharding)技術

  分片(sharding)是MongoDB用來將大型集合分割到不同服務器(或者說一個集羣)上所採用的方法。儘管分片起源於關係型數據庫分區,但MongoDB分片完全又是另一回事。

  和MySQL分區方案相比,MongoDB的最大區別在於它幾乎能自動完成所有事情,只要告訴MongoDB要分配數據,它就能自動維護數據在不同服務器之間的均衡。

2.1 MongoDB分片介紹

2.1.1 分片的目的

  高數據量和吞吐量的數據庫應用會對單機的性能造成較大壓力,大的查詢量會將單機的CPU耗盡,大的數據量對單機的存儲壓力較大,最終會耗盡系統的內存而將壓力轉移到磁盤IO上。

  爲了解決這些問題,有兩個基本的方法: 垂直擴展和水平擴展。

    垂直擴展:增加更多的CPU和存儲資源來擴展容量。

    水平擴展:將數據集分佈在多個服務器上。水平擴展即分片。

2.1.2 分片設計思想

  分片爲應對高吞吐量與大數據量提供了方法。使用分片減少了每個分片需要處理的請求數,因此,通過水平擴展,集羣可以提高自己的存儲容量和吞吐量。舉例來說,當插入一條數據時,應用只需要訪問存儲這條數據的分片.

  使用分片減少了每個分片存儲的數據。

  例如,如果數據庫1tb的數據集,並有4個分片,然後每個分片可能僅持有256 GB的數據。如果有40個分片,那麼每個切分可能只有25GB的數據。

2.1.3 分片機制提供瞭如下三種優勢

1.對集羣進行抽象,讓集羣“不可見”

  MongoDB自帶了一個叫做mongos的專有路由進程。mongos就是掌握統一路口的路由器,其會將客戶端發來的請求準確無誤的路由到集羣中的一個或者一組服務器上,同時會把接收到的響應拼裝起來發回到客戶端。

2.保證集羣總是可讀寫

  MongoDB通過多種途徑來確保集羣的可用性和可靠性。將MongoDB的分片和複製功能結合使用,在確保數據分片到多臺服務器的同時,也確保了每分數據都有相應的備份,這樣就可以確保有服務器換掉時,其他的從庫可以立即接替壞掉的部分繼續工作。

3.使集羣易於擴展

  當系統需要更多的空間和資源的時候,MongoDB使我們可以按需方便的擴充系統容量。

2.1.4 分片集羣架構

組件

說明

Config Server

存儲集羣所有節點、分片數據路由信息。默認需要配置3個Config Server節點。

Mongos

提供對外應用訪問,所有操作均通過mongos執行。一般有多個mongos節點。數據遷移和數據自動平衡。

Mongod

存儲應用數據記錄。一般有多個Mongod節點,達到數據分片目的。

 

分片集羣的構造

 (1)mongos :數據路由,和客戶端打交道的模塊。mongos本身沒有任何數據,他也不知道該怎麼處理這數據,去找config server

(2)config server:所有存、取數據的方式,所有shard節點的信息,分片功能的一些配置信息。可以理解爲真實數據的元數據。

 (3)shard:真正的數據存儲位置,以chunk爲單位存數據。

  Mongos本身並不持久化數據,Sharded cluster所有的元數據都會存儲到Config Server,而用戶的數據會議分散存儲到各個shard。Mongos啓動後,會從配置服務器加載元數據,開始提供服務,將用戶的請求正確路由到對應的碎片。

Mongos的路由功能

  當數據寫入時,MongoDB Cluster根據分片鍵設計寫入數據。

  當外部語句發起數據查詢時,MongoDB根據數據分佈自動路由至指定節點返回數據。

2.2 集羣中數據分佈

2.2.1 Chunk是什麼

  在一個shard server內部,MongoDB還是會把數據分爲chunks,每個chunk代表這個shard server內部一部分數據。chunk的產生,會有以下兩個用途:

  Splitting當一個chunk的大小超過配置中的chunk size時,MongoDB的後臺進程會把這個chunk切分成更小的chunk,從而避免chunk過大的情況

  Balancing在MongoDB中,balancer是一個後臺進程,負責chunk的遷移,從而均衡各個shard server的負載,系統初始1個chunk,chunk size默認值64M,生產庫上選擇適合業務的chunk size是最好的。ongoDB會自動拆分和遷移chunks。

分片集羣的數據分佈(shard節點)

(1)使用chunk來存儲數據

(2)進羣搭建完成之後,默認開啓一個chunk,大小是64M,

(3)存儲需求超過64M,chunk會進行分裂,如果單位時間存儲需求很大,設置更大的chunk

(4)chunk會被自動均衡遷移。

2.2.2 chunksize的選擇

  適合業務的chunksize是最好的。

  chunk的分裂和遷移非常消耗IO資源;chunk分裂的時機:在插入和更新,讀數據不會分裂。

  chunksize的選擇:

  小的chunksize:數據均衡是遷移速度快,數據分佈更均勻。數據分裂頻繁,路由節點消耗更多資源。大的chunksize:數據分裂少。數據塊移動集中消耗IO資源。通常100-200M

2.2.3 chunk分裂及遷移

  隨着數據的增長,其中的數據大小超過了配置的chunk size,默認是64M,則這個chunk就會分裂成兩個。數據的增長會讓chunk分裂得越來越多。

 

  這時候,各個shard 上的chunk數量就會不平衡。這時候,mongos中的一個組件balancer  就會執行自動平衡。把chunk從chunk數量最多的shard節點挪動到數量最少的節點。

 

chunkSize 對分裂及遷移的影響

  MongoDB 默認的 chunkSize 爲64MB,如無特殊需求,建議保持默認值;chunkSize 會直接影響到 chunk 分裂、遷移的行爲。

  chunkSize 越小,chunk 分裂及遷移越多,數據分佈越均衡;反之,chunkSize 越大,chunk 分裂及遷移會更少,但可能導致數據分佈不均。

  chunkSize 太小,容易出現 jumbo chunk(即shardKey 的某個取值出現頻率很高,這些文檔只能放到一個 chunk 裏,無法再分裂)而無法遷移;chunkSize 越大,則可能出現 chunk 內文檔數太多(chunk 內文檔數不能超過 250000 )而無法遷移。

  chunk 自動分裂只會在數據寫入時觸發,所以如果將 chunkSize 改小,系統需要一定的時間來將 chunk 分裂到指定的大小。

  chunk 只會分裂,不會合並,所以即使將 chunkSize 改大,現有的 chunk 數量不會減少,但 chunk 大小會隨着寫入不斷增長,直到達到目標大小。

2.3 數據區分

2.3.1 分片鍵shard key

  MongoDB中數據的分片是、以集合爲基本單位的,集合中的數據通過片鍵(Shard key)被分成多部分。其實片鍵就是在集合中選一個鍵,用該鍵的值作爲數據拆分的依據。

  所以一個好的片鍵對分片至關重要。片鍵必須是一個索引,通過sh.shardCollection加會自動創建索引(前提是此集合不存在的情況下)。一個自增的片鍵對寫入和數據均勻分佈就不是很好,因爲自增的片鍵總會在一個分片上寫入,後續達到某個閥值可能會寫到別的分片。但是按照片鍵查詢會非常高效。

  隨機片鍵對數據的均勻分佈效果很好。注意儘量避免在多個分片上進行查詢。在所有分片上查詢,mongos會對結果進行歸併排序。

  對集合進行分片時,你需要選擇一個片鍵,片鍵是每條記錄都必須包含的,且建立了索引的單個字段或複合字段,MongoDB按照片鍵將數據劃分到不同的數據塊中,並將數據塊均衡地分佈到所有分片中。

  爲了按照片鍵劃分數據塊,MongoDB使用基於範圍的分片方式或者 基於哈希的分片方式。

注意:

分片鍵是不可變。

分片鍵必須有索引。

分片鍵大小限制512bytes。

分片鍵用於路由查詢。

MongoDB不接受已進行collection級分片的collection上插入無分片

鍵的文檔(也不支持空值插入)

2.3.2 以範圍爲基礎的分片Sharded Cluster

  Sharded Cluster支持將單個集合的數據分散存儲在多shard上,用戶可以指定根據集合內文檔的某個字段即shard key來進行範圍分片(range sharding)。

 

  對於基於範圍的分片,MongoDB按照片鍵的範圍把數據分成不同部分。

  假設有一個數字的片鍵:想象一個從負無窮到正無窮的直線,每一個片鍵的值都在直線上畫了一個點。MongoDB把這條直線劃分爲更短的不重疊的片段,並稱之爲數據塊,每個數據塊包含了片鍵在一定範圍內的數據。在使用片鍵做範圍劃分的系統中,擁有”相近”片鍵的文檔很可能存儲在同一個數據塊中,因此也會存儲在同一個分片中。

2.3.3 基於哈希的分片

  分片過程中利用哈希索引作爲分片的單個鍵,且哈希分片的片鍵只能使用一個字段,而基於哈希片鍵最大的好處就是保證數據在各個節點分佈基本均勻。

 

  對於基於哈希的分片,MongoDB計算一個字段的哈希值,並用這個哈希值來創建數據塊。在使用基於哈希分片的系統中,擁有”相近”片鍵的文檔很可能不會存儲在同一個數據塊中,因此數據的分離性更好一些。

  Hash分片與範圍分片互補,能將文檔隨機的分散到各個chunk,充分的擴展寫能力,彌補了範圍分片的不足,但不能高效的服務範圍查詢,所有的範圍查詢要分發到後端所有的Shard才能找出滿足條件的文檔。

2.3.4 分片鍵選擇建議

1、遞增的sharding key

數據文件挪動小。(優勢)

因爲數據文件遞增,所以會把insert的寫IO永久放在最後一片上,造成最後一片的寫熱點。同時,隨着最後一片的數據量增大,將不斷的發生遷移至之前的片上。

2、隨機的sharding key

數據分佈均勻,insert的寫IO均勻分佈在多個片上。(優勢)

大量的隨機IO,磁盤不堪重荷。

3、混合型key

大方向隨機遞增,小範圍隨機分佈。

爲了防止出現大量的chunk均衡遷移,可能造成的IO壓力。我們需要設置合理分片使用策略(片鍵的選擇、分片算法(range、hash))

分片注意:

   分片鍵是不可變、分片鍵必須有索引、分片鍵大小限制512bytes、分片鍵用於路由查詢。

   MongoDB不接受已進行collection級分片的collection上插入無分片鍵的文檔(也不支持空值插入)

2.4 部署分片集羣

  本集羣的部署基於1.1的複製集搭建完成

2.4.1 環境準備

創建程序所需的目錄

for  i in 17 18 19 20 21 22 23 24 25 26 
  do 
  mkdir -p /mongodb/280$i/conf  
  mkdir -p /mongodb/280$i/data  
  mkdir -p /mongodb/280$i/logdone

2.4.2 shard集羣配置

編輯shard集羣配置文件

cat > /mongodb/28021/conf/mongod.conf <<'EOF'systemLog:
  destination: file
  path: /mongodb/28021/log/mongodb.log   
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28021/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  bindIp: 10.0.0.152
  port: 28021replication:
  oplogSizeMB: 2048
  replSetName: sh1
sharding:
  clusterRole: shardsvr
processManagement: 
  fork: true
EOF

複製shard集羣配置文件

for  i in  22 23 24 25 26  
  do  
   \cp  /mongodb/28021/conf/mongod.conf  /mongodb/280$i/conf/done

修改配置文件端口

for  i in   22 23 24 25 26  
  do 
    sed  -i  "s#28021#280$i#g" /mongodb/280$i/conf/mongod.conf
done

   修改配置文件複製集名稱(replSetName)

for  i in    24 25 26  
  do 
    sed  -i  "s#sh1#sh2#g" /mongodb/280$i/conf/mongod.conf
done

啓動shard集羣

for  i in  21 22 23 24 25 26
  do  
    mongod -f /mongodb/280$i/conf/mongod.conf 
done

配置複製集1

mongo --host 10.0.0.152 --port 28021  admin

  # 配置複製集

config = {_id: 'sh1', members: [
                          {_id: 0, host: '10.0.0.152:28021'},
                          {_id: 1, host: '10.0.0.152:28022'},
                          {_id: 2, host: '10.0.0.152:28023',"arbiterOnly":true}]
           }  
 # 初始化配置
rs.initiate(config)

 配置複製集2

mongo --host 10.0.0.152 --port 28024  admin

  # 配置複製集

config = {_id: 'sh2', members: [
                          {_id: 0, host: '10.0.0.152:28024'},
                          {_id: 1, host: '10.0.0.152:28025'},
                          {_id: 2, host: '10.0.0.152:28026',"arbiterOnly":true}]
           }
# 初始化配置
rs.initiate(config)

2.4.3 config集羣配置

創建主節點配置文件

cat > /mongodb/28018/conf/mongod.conf <<'EOF'systemLog:
  destination: file
  path: /mongodb/28018/log/mongodb.conf
  logAppend: true
storage:
  journal:
    enabled: true
  dbPath: /mongodb/28018/data
  directoryPerDB: true
  #engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true
net:
  bindIp: 10.0.0.152
  port: 28018replication:
  oplogSizeMB: 2048
  replSetName: configReplSet
sharding:
  clusterRole: configsvr
processManagement: 
  fork: true
EOF

將配置文件分發到從節點

for  i in 19 20 
  do  
   \cp  /mongodb/28018/conf/mongod.conf  /mongodb/280$i/conf/done

修改配置文件端口信息

for  i in 19 20  
  do 
    sed  -i  "s#28018#280$i#g" /mongodb/280$i/conf/mongod.conf
done

啓動config server集羣

for  i in  18 19 20 
  do  
    mongod -f /mongodb/280$i/conf/mongod.conf 
done

配置config server複製集

mongo --host 10.0.0.152 --port 28018  admin

# 配置複製集信息

config = {_id: 'configReplSet', members: [
                          {_id: 0, host: '10.0.0.152:28018'},
                          {_id: 1, host: '10.0.0.152:28019'},
                          {_id: 2, host: '10.0.0.152:28020'}]
           }
# 初始化配置
rs.initiate(config)

  注:config server 使用複製集不用有arbiter節點。3.4版本以後config必須爲複製集

2.4.4 mongos節點配置

修改配置文件

cat > /mongodb/28017/conf/mongos.conf <<'EOF'systemLog:
  destination: file
  path: /mongodb/28017/log/mongos.log
  logAppend: true
net:
  bindIp: 10.0.0.152
  port: 28017sharding:
  configDB: configReplSet/10.0.0.152:28108,10.0.0.152:28019,10.0.0.152:28020processManagement: 
  fork: true
EOF

啓動mongos

mongos -f /mongodb/28017/conf/mongos.conf

登陸到mongos

mongo 10.0.0.152:28017/admin

添加分片節點

db.runCommand( { addshard : "sh1/10.0.0.152:28021,10.0.0.152:28022,10.0.0.152:28023",name:"shard1"} )
db.runCommand( { addshard : "sh2/10.0.0.152:28024,10.0.0.152:28025,10.0.0.152:28026",name:"shard2"} )

列出分片

mongos> db.runCommand( { listshards : 1 } )
{
    "shards" : [
        {
            "_id" : "shard2",
            "host" : "sh2/10.0.0.152:28024,10.0.0.152:28025"
        },
        {
            "_id" : "shard1",
            "host" : "sh1/10.0.0.152:28021,10.0.0.152:28022"
        }    ],
    "ok" : 1}

整體狀態查看

mongos> sh.status();

   至此MongoDB的分片集羣就搭建完成。

2.4.5 數據庫分片配置

激活數據庫分片功能

語法:( { enablesharding : "數據庫名稱" } )

mongos> db.runCommand( { enablesharding : "test" } )

指定分片建對集合分片,範圍片鍵–創建索引

mongos> use test 
mongos> db.vast.ensureIndex( { id: 1 } )
mongos> use admin
mongos> db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )

集合分片驗證

mongos> use test
mongos> for(i=0;i<20000;i++){ db.vast1.insert({"id":i,"name":"clsn","age":70,"date":new Date()}); }
mongos> db.vast.stats()

    插入數據的條數儘量大些,能夠看出更好的效果。

2.5 分片集羣的操作

2.5.1 不同分片鍵的配置

範圍片鍵

admin> sh.shardCollection("數據庫名稱.集合名稱",key : {分片鍵: 1}  )
或
admin> db.runCommand( { shardcollection : "數據庫名稱.集合名稱",key : {分片鍵: 1} } )

eg:

admin > sh.shardCollection("test.vast",key : {id: 1}  )
或
admin> db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )

哈希片鍵

admin > sh.shardCollection( "數據庫名.集合名", { 片鍵: "hashed" } )

創建哈希索引

admin> db.vast.ensureIndex( { a: "hashed" } )
admin > sh.shardCollection( "test.vast", { a: "hashed" } )

2.5.2 分片集羣的操作

判斷是否Shard集羣

admin> db.runCommand({ isdbgrid : 1})

列出所有分片信息

admin> db.runCommand({ listshards : 1})

列出開啓分片的數據庫

admin> use config
config> db.databases.find( { "partitioned": true } )
config> db.databases.find() //列出所有數據庫分片情況

查看分片的片鍵

config> db.collections.find()
{
    "_id" : "test.vast",
    "lastmodEpoch" : ObjectId("58a599f19c898bbfb818b63c"),
    "lastmod" : ISODate("1970-02-19T17:02:47.296Z"),
    "dropped" : false,
    "key" : {
        "id" : 1
    },
    "unique" : false
}

查看分片的詳細信息

admin> db.printShardingStatus()
或
admin> sh.status()

刪除分片節點

sh.getBalancerState()
mongos> db.runCommand( { removeShard: "shard2" } )

2.6 balance操作

  查看mongo集羣是否開啓了 balance 狀態

mongos> sh.getBalancerState()
true

  當然你也可以通過在路由節點mongos上執行sh.status() 查看balance狀態。

  如果balance開啓,查看是否正在有數據的遷移

連接mongo集羣的路由節點

mongos> sh.isBalancerRunning()
false

2.6.1 設置balance 窗口

(1)連接mongo集羣的路由節點

(2)切換到配置節點

     use config

(3)確定balance 開啓中

     sh.getBalancerState()

   如果未開啓,執行命令

   sh.setBalancerState( true )

(4)修改balance 窗口的時間

db.settings.update(
   { _id: "balancer" },
   { $set: { activeWindow : { start : "<start-time>", stop : "<stop-time>" } } },
   { upsert: true }
)

eg:

db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "00:00", stop : "5:00" } } }, true )

  當你設置了activeWindow,就不能用sh.startBalancer() 啓動balance

NOTE

The balancer window must be sufficient to complete the migration of all data inserted during the day.

As data insert rates can change based on activity and usage patterns, it is important to ensure that the balancing window you select will be sufficient to support the needs of your deployment.

(5)刪除balance 窗口

use config
db.settings.update({ _id : "balancer" }, { $unset : { activeWindow : true } })

2.6.2 關閉balance

  默認balance 的運行可以在任何時間,只遷移需要遷移的chunk,如果要關閉balance運行,停止一段時間可以用下列方法:

(1) 連接到路由mongos節點

(2) 停止balance

      sh.stopBalancer()

(3) 查看balance狀態

  sh.getBalancerState()

(4)停止balance 後,沒有遷移進程正在遷移,可以執行下列命令

use configwhile( sh.isBalancerRunning() ) {          print("waiting...");
          sleep(1000);
}

2.6.3 重新打開balance

如果你關閉了balance,準備重新打開balance

(1) 連接到路由mongos節點

(2) 打開balance

        sh.setBalancerState(true)

如果驅動沒有命令  sh.startBalancer(),可以用下列命令

use config
db.settings.update( { _id: "balancer" }, { $set : { stopped: false } } , { upsert: true } )

2.6.4 關於集合的balance

關閉某個集合的balance

sh.disableBalancing("students.grades")

打開某個集合的balance

sh.enableBalancing("students.grades")

確定某個集合的balance是開啓或者關閉

db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;

2.6.5 問題解決

mongodb在做自動分片平衡的時候,或引起數據庫響應的緩慢,可以通過禁用自動平衡以及設置自動平衡進行的時間來解決這一問題。

(1)禁用分片的自動平衡

// connect to mongos> use config> db.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );

(2)自定義 自動平衡進行的時間段

// connect to mongos> use config> db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "21:00", stop : "9:00" } } }, true )

2.7 參考文獻

[1]  https://www.jianshu.com/p/ddcc3643aec9

[2]  https://docs.mongodb.com/manual/replication/

[3]  https://docs.mongodb.com/manual/core/replica-set-architecture-three-members/

[4]  http://www.mongoing.com/archives/2155

[5]  https://docs.mongodb.com/manual/sharding/

[6]  http://www.ywnds.com/?p=3476

[7]  https://yq.aliyun.com/articles/32434






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章