1. 程式人生 > >MongoDB副本集學習(三):效能和優化相關

MongoDB副本集學習(三):效能和優化相關

Read Preferences/讀寫分離

有時候為了考慮應用程式的效能或響應性,為了提高讀取操作的吞吐率,一個常見的措施就是進行讀寫分離,MongoDB副本集對讀寫分離的支援是通過Read Preferences特性進行支援的,這個特性非常複雜和靈活。以下幾種應用場景可能會考慮對副本集進行讀寫分離:

1)操作不影響前端應用程式,比如備份或者報表;

2)在一個物理上分佈的副本叢集中,為了減少應用程式的延遲,可能會優先選擇離應用程式更近的secondary節點而不是遠在千里之外機房的主節點;

3)故障發生時候能夠提供一個優雅的降級。副本集primary節點宕機後再選出新的primary節點這段時間內(10秒或更長時間)能夠依然響應客戶端應用的讀請求;

4)應用能夠容忍一定程度的資料不一致性。

Read References:

應用程式驅動通過read reference來設定如何對副本集進行讀取操作,預設的,客戶端驅動所有的讀操作都是直接訪問primary節點的,從而保證了資料的嚴格一致性。

但有時為了緩解主節點的壓力,我們可能需要直接從secondary節點讀取,只需要保證最終一致性就可以了。

MongoDB 2.0之後支援五種的read preference模式:

primary:預設,只從主節點上進行讀取操作;

primaryPreferred:在絕大部分的情形都是從主節點上讀取資料的,只有當主節點不可用的時候,比如在進行failover的10秒或更長的時間內會從secondary節點讀取資料。

警告:2.2版本之前的MongoDB對Read Preference支援的還不完全,如果客戶端驅動採用primaryPreferred實際上讀取操作都會被路由到secondary節點。

secondary:只從secondary節點上進行讀取操作,存在的問題是secondary節點的資料會比primary節點資料“舊”。

secondaryPreferred:優先從secondary節點進行讀取操作;

nearest:既有可能從primary,也有可能從secondary節點讀取,這個決策是通過一個叫member selection過程處理的。

MongoDB允許在不同的粒度上指定這些模式:連線、資料庫、集合甚至單次的操作。不同語言的驅動基本都支援這些粒度。

OpLog

oplog是一種特殊的capped collection,用來滾動的儲存MongoDB中所有資料操作的日誌。副本集中secondary節點非同步的從primary節點同步oplog然後重新執行它記錄的操作,以此達到了資料同步的作用。這就要求oplog必須是冪等的,也就是重複執行相同的oplog記錄得到的資料結構必須是相同的。

事實上副本集中所有節點之間都相互進行heartbeat來維持聯絡,任何節點都能從其它節點複製oplog。

capped collection是MongoDB中一種提供高效能插入、讀取和刪除操作的固定大小集合。當集合被填滿的時候,新的插入的文件會覆蓋老的文件。因為oplog是capped collection所以指定它的大小非常重要。如果太小那麼老的文件很快就被覆蓋了,那麼宕機的節點就很容易出現無法同步資料的結果,但也不是越大越好,MongoDB在初始化副本集的時候都會有一個預設的oplog大小:

  • 在64位的Linux,Solaris,FreeBSD以及Windows系統上,MongoDB會分配磁碟剩餘空間的5%作為oplog的大小,如果這部分小於1GB則分配1GB的空間。
  • 在64的OS X系統上會分配183MB。
  • 在32位的系統上則只分配48MB。

首先生產環境使用MongoDB毫無疑問必須的是64為作業系統。其次大多數情況下預設的大小是比較適合的。舉個例子,如果oplog大小為空閒磁碟的5%,它在24H內能被填滿,也就是說secondary節點可以停止複製oplog達24H後仍然能夠catch up上primary節點。而且通常的MongoDB副本集的操作量要比這低得多。

oplog資料結構

oplog的資料結構如下所示:

{ ts : ..., op: ..., ns: ..., o: ... o2: ...  }

  • ts: 8位元組的時間戳,由4位元組unix timestamp + 4位元組自增計數表示。這個值很重要,在選舉(如master宕機時)新primary時,會選擇ts最大的那個secondary作為新primary。
  • op:1位元組的操作型別,例如i表示insert,d表示delete。
  • ns:操作所在的namespace。
  • o:操作所對應的document,即當前操作的內容(比如更新操作時要更新的的欄位和值)
  • o2: 在執行更新操作時的where條件,僅限於update時才有該屬性

其中op有以下幾個值:

  • "i": insert
  • "u": update
  • "d": delete
  • "c": db cmd
  • "db":聲明當前資料庫 (其中ns 被設定成為=>資料庫名稱+ '.')
  • "n":  no op,即空操作,其會定期執行以確保時效性

檢視oplog大小

1.    rs0:PRIMARY> db.printReplicationInfo() 
2.    configured oplog size:   1793.209765625MB
3.    log length start to end: 12.643999999854714secs (0hrs)
4.    oplog first event time:  Sat Jan 17 1970 06:22:38 GMT+0800 (CST)
5.    oplog last event time:   Sat Jan 17 1970 06:22:51 GMT+0800 (CST)
6.    now:                     Sat Aug 17 2013 18:02:12 GMT+0800 (CST)

以我之前搭建的副本集為例,oplog的大小是1793MB,其中持有的資料時間區間只有12秒。

修改oplog大小

可以在啟動mongod的時候指定--oplogSize,單位MB:

7.    ./bin/mongod --fork --dbpath data/rs0-0/ --logpath log/rs0-0/rs0-0.log --rest --replSet rs0 --oplogSize 500 --port 37017

在現有的副本集中修改oplog的大小是相當麻煩的而且影響副本集效能,因此我們最好是預先根據應用的情況評估好oplog的大小:如果應用程式是讀多寫少,那麼預設的大小已經足夠了。如果你的應用下面幾種場景很多可能考慮需要更大的oplog:

  • 在同一個時刻更新多個文件:oplog為了維持冪等性必須將mutil-updates翻譯成一個個獨立的操作,這會用去大量的oplog空間,但資料庫中的資料量卻沒有相對稱的增加。
  • 多文件同時更新從1.1.3就有的特性,在mongo shell執行類似如下的命令,第四個引數必須制定為true:
  • db.test.update({foo: "bar"}, {$set: {test: "success!"}}, false, true);
  • 在插入時同時刪除相同大小資料:和上面的結果一樣在資料量沒有增加的情況下卻消耗了大量的oplog空間。
  • 大量的In-Place更新操作:In-Place更新是指更新文件中原有的部分,但並不增加文件的大小。

上面三點總結起來就是消耗了大量的oplog但是資料量卻沒有等量的增加

資料同步

資料滯後:

前面已經提到MongoDB副本集中secondary節點是通過oplog來同步primary節點資料的,那具體的細節是怎麼樣的?在說資料如何同步之間先介紹一下replication lag,因為存在資料同步那必然存在一定程度的落後。這個問題對於整個MongoDB副本集的部署是至關重要的。

1.    rs0:PRIMARY> db.printSlaveReplicationInfo()
2.    source:   192.168.129.129:37019
3.         syncedTo: Thu Aug 15 2013 20:59:45 GMT+0800 (CST)
4.             = 172971 secs ago (48.05hrs)
5.    source:   192.168.129.129:37020
6.         syncedTo: Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
7.             = 1376744556 secs ago (382429.04hrs)

當前叢集的狀況是,37017埠是primary節點,37019和37020是secondary節點,其中37020已經宕機,可以看到37019同步資料是在兩天前(因為這兩天我沒有對副本集有任何資料操作),而宕機的節點顯示的同步時間是一個很早時間點。

現在重新啟動37020後再執行命令:

1.    rs0:PRIMARY> db.printSlaveReplicationInfo()
2.    source:   192.168.129.129:37019
3.         syncedTo: Thu Aug 15 2013 20:59:45 GMT+0800 (CST)
4.             = 175566 secs ago (48.77hrs)
5.    source:   192.168.129.129:37020
6.         syncedTo: Thu Aug 15 2013 20:59:45 GMT+0800 (CST)
7.             = 175566 secs ago (48.77hrs)

可以看到兩個secondary節點的同步時間是一致的,我們向叢集中插入幾條資料後再執行db.printSlaveReplicationInfo():

1.    rs0:PRIMARY> db.test.insert({"name":"zhanjindong","age":23})
2.    rs0:PRIMARY> db.printSlaveReplicationInfo()
3.    source:   192.168.129.129:37019
4.         syncedTo: Sat Aug 17 2013 21:48:31 GMT+0800 (CST)
5.             = 6 secs ago (0hrs)
6.    source:   192.168.129.129:37020
7.         syncedTo: Sat Aug 17 2013 21:48:31 GMT+0800 (CST)
8.             = 6 secs ago (0hrs)

可以看到很快就引發了primary和secondary之間的資料同步操作。

“滯後”是不可避免的,需要做的就是儘可能減小這種滯後,主要涉及到以下幾點:

  • 網路延遲:這是所有分散式系統都存在的問題。我們能做的就是儘可能減小副本集節點之間的網路延遲。
  • 磁碟吞吐量:secondary節點上資料刷入磁碟的速度比primary節點上慢的話會導致secondary節點很難跟上primary節點的節奏。
  • 併發:併發大的情況下,primary節點上的一些耗時操作會阻塞secondary節點的複製操作,導致複製操作跟不上主節點的寫入負荷。解決方法是通過設定操作的write concern(參看這裡:http://docs.mongodb.org/manual/core/write-concern/#replica-set-write-concern)預設的副本集中寫入操作只關心primary節點,但是可以指定寫入操作同時傳播到其他secondary節點,代價就是嚴重影響叢集的併發性。
    • 注意:而且這裡還存在一個問題如果,如果寫入操作關心的某個節點宕機了,那麼操作將會一直被阻塞直到節點恢復。
  • 適當的write concern:我們為了提高叢集寫操作的吞吐量經常會將writer concern設定為unacknowledged write concern,這導致primary節點的寫操作很快而secondary節點複製操作跟不上。解決方法和第三點是類似的就是在效能和一致性之間做權衡。

資料同步:

副本集中資料同步有兩個階段。

初始化(initial sync):這個過程發生在當副本集中建立一個新的資料庫或其中某個節點剛從宕機中恢復,或者向副本集中新增新的成員的時候,預設的,副本集中的節點會從離它最近的節點複製oplog來同步資料,這個最近的節點可以是primary也可以是擁有最新oplog副本的secondary節點。這可以防止兩個secondary節點之間相互進行同步操作。

複製(replication):在初始化後這個操作會一直持續的進行著,以保持各個secondary節點之間的資料同步。

在MongoDB2.0以後的版本中,一旦初始化中確定了一個同步的目標節點後,只有當和同步節點之間的連線斷開或連線過程中產生異常才可能會導致同步目標的變動,並且具有就近原則。考慮兩種場景:

  • 1) 有兩個secondary節點在一個機房,primary在另外一個機房。假設幾乎在同一時間啟動這三個例項(之前都沒有資料和oplog),那麼兩個secondary節點應該都是從primary節點同步資料,因為他們之前見都不會擁有比對方更新的oplog。如果重啟其中一個secondary,那麼它的同步目標將會變成另一個secondary,因為就近原則。
  • 2) 如果有一個primary和一個secondary分別在不同的機房,那麼在之前secondary所在的機房中向副本集中新加一個節點時,那麼新節點必然是從原先的那個secondary節點同步資料的。

在2.2版本以後,資料同步增加了一些額外的行為:

  • 1) secondary節點只有當叢集中沒有其他選擇的時候才會從delayed節點同步資料;
  • 2) secondary節點絕不會從hidden節點同步資料;
  • 3) 當一個節點新加入副本集中會有一個recovering過程,在這段時間內secondary不會進行資料同步操作;
  • 4) 當一個節點從另一個節點同步資料的時候,需要保證兩個節點的local.system.replset.members[n].buildIndexes值是一樣的,要不都是false,要不都是true。

:buildIndexes指定副本集中成員是否可以建立索引(某些情況下比如沒有讀操作或者為了提高寫效能可以省略索引的建立)。當然即使該值為false,MongoDB還是可以在_id上建立索引以為複製操作服務。

重新資料同步

有時當secondary節點落後太多無法追趕上primary節點的時候,這時候可能需要考慮重新同步資料(Resync data)。

有兩種方法一種是指定一個空的目錄重新啟動落後的節點,這很簡單,但是資料量大的情況下回花費很長的時間。另一種方法是基於另一個節點的資料作為“種子”進行重新同步,關於這兩種方法在後面向一個現有副本集中新增成員一節會有詳細說明。

Elction

在以下幾種情景發生的時候,副本集通過“選舉”來決定副本集中的primary節點:

  • 當第一次初始化一個副本集的時候;
  • primary幾點steps down的時候,出現這種情況可能是因為執行了replSetStepDown命令,或者是叢集中出現了更適合當primary的節點,比如當primary節點和叢集中其他大部分節點無法通訊的時候,當primary steps down的時候,它會關閉所有客戶端的連線。
  • 當叢集中一個secondary節點無法和primary節點建立連線的時候也會導致一次election發生。
  • 一次failover。
  • 執行rs.conf()命令。

 

在一次選舉中包括hidden節點、仲裁者甚至正處於recovering狀態的節點都具有“投票權”。預設配置中所有參與選舉的節點具有相等的權利,當然在一些特定情況下,應明確的指定某些secondary會優先成為primary,比如一個遠在千里之外異地機房的節點就不應該成為primary節點,選舉的權重通過設定priority來調節,預設該值都是1,在前面簡單副本集的搭建中已經介紹過了如何修改該值。

叢集中任何一個節點都可以否決選舉,即使它是non-voting member:

  • 如果發起選舉的節點不具有選舉權(priority為0的成員);
  • 發起選舉的節點資料落後太多;
  • 發起選舉的節點的priority值比叢集中其他某一個節點的小;
  • 如果當前的primary節點比發起選舉的節點擁有更新或同等新的資料(也就“optime”值相等或更大)。
  • 當前的primary節點會否決,如果它擁有比發起選舉的節點更新或相同新的資料。

首先獲取最多選票的成員(實際上要超過半數)才會成為primary節點,這也說明了為什麼當有兩個節點的叢集中primary節點宕機後,剩下的只能成為secondary,當primary宕掉,此時副本集只剩下一個secondary,它只有1票,不超過總節點數的半數,它不會選舉自己為primary。

索引

……

最近太忙,有時間再整理。

相關推薦

MongoDB副本學習()效能優化相關

Read Preferences/讀寫分離 有時候為了考慮應用程式的效能或響應性,為了提高讀取操作的吞吐率,一個常見的措施就是進行讀寫分離,MongoDB副本集對讀寫分離的支援是通過Read Preferences特性進行支援的,這個特性非常複雜和靈活。以下幾種應用場景可能會考慮對副本集進行讀寫分離: 1

MYSQL學習筆記日期時間函數

div content minute name top fonts table hmm 指定 MYSQL學習筆記三:日期和時間函數 1. 獲取當前日期的函數和獲取當前時間的函數 /*獲取當前日期的函數和獲取當前時間的函數。將日期以‘YYYY-MM-DD‘或者’YYYYM

dbms_lob包學習筆記之instrsubstr存儲過程

hello 字節數 TE bms HERE substring 成功 其中 oracle instr和substr存儲過程,分析內部大對象的內容 instr函數與substr函數 instr函數用於從指定的位置開始,從大型對象中查找第N個與模式匹配

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

HI!,你好,我是zane,zanePerfor是一款最近我開發的一個前端效能監控平臺,現在支援web瀏覽器端和微信小程式段。 我定義為一款完整,高效能,高可用的前端效能監控系統,這是未來會達到的目的,現今的架構也基本支援了高可用,高效能的部署。實際上還不夠,在很多地方還有優化的空間,我會持續的

mongodb副本簡單介紹建立

mongodb副本集介紹 MongoDB副本集早期是沒有這個概念的,早期MongoDB是使用master-slave模式,一主一從和MySQL功能類似,當主庫宕機後,從庫不能自動切換成主 目前版本已經不再使用master-slave模式了,改為使用副本集,這種模式下有一個主(primary),多個從角

MongoDB副本配置資料遷移實戰

MongoDB副本集配置和資料遷移實戰 https://gitee.com/et/ops/blob/master/MongoDB副本集配置和資料遷移實戰.md 環境:Ubuntu 16.04, MongoDB 3.6 基本概念 MongoDB 的副本集就是

05 MongoDB副本 MongoDB文件管理

Top NSD NOSQL DAY05 1 案例1:配置MongoDB副本集 1.1 問題 具體要求: 準備3臺mongodb伺服器 配置副本集服務 驗證副本集配置 1.2 方案 準備三臺虛擬機器,配置mongodb副本集,ip分別為192.158.4.5

MongoDB實戰系列之四mongodb副本部署

簡述:副本集合(Replica Sets),是一個基於主/從複製機制的複製功能,但增加了自動故障轉移和恢復特性。一個叢集最多可以支援7個伺服器,並且任意節點都可以是主節點。所有的寫操作都被分發到主節點,而讀操作可以在任何節點上進行。 環境:CentOS 5.5 x64

Python學習筆記輸入輸出

        首先,登入        >>>是Python直譯器的提示符輸出1輸出字串,使用print(),在括號中加上字串,多個字串用逗號“,”隔開,每個字串用單引號包住注意:print()會依次列印每個字串,遇到逗號“,”會輸出一個空格2,print

MyBatis學習SqlMapConfig.xml屬性sql片段

SqlMapConfig.xml 1、properties屬性 將資料庫連線引數單獨配置在db.properties中,只需在SqlMapConfig.xml中載入db.properties的屬性值。在SqlMapConfig.xml中就不需要對資料庫連線引數硬編碼。 將

zabbix使用Python實現監控MongoDB副本狀態

python zabbix mongodb pymongo 公司有 Windows 和 Linux 服務器,都搭建了 MongoDB 副本集,並且都要在 zabbix 平臺中實現監控。Linux 系統直接使用 shell 腳本即可實現,但是 Windows 系統的不太好實現,我這裏使用

WPF學習TextBlockLabel的區別

padding eight 前景 繼承 man ont blog led use TextBlock和Label都是用來顯示少量數據的。好多文章對Label存在的描述都是它允許使用"快速獲取"。"快速獲取"就是允許你用Alt加上其它的按鍵快速和UI界面的某個控件交互,比如你

mongodb 副本搭建

mongodb 搭建 副本集 排錯 mongodb的副本集模式較早前的master-slave模式有了很大的改進,由於之前的master-slave模式不支持主機宕機之後切換到從機,已經逐漸被淘汰。而現在官方推薦的副本集模式,支持多個節點並存,當主節點宕機後從權重最高的副節點開始,依次切換為主

mongodb副本的內部機制(借鑒lanceyan.com)

proc 導致 功能 來看 href 開始 既然 不想 for 針對mongodb的內部機制提出以下幾個引導性的問題: 副本集故障轉移,主節點是如何選舉的?能否手動幹涉下架某一臺主節點。 官方說副本集數量最好是奇數,為什麽? mongodb副本集是如何同步的?如果同步不及

mongodb副本搭建

god 不可 status cin prim conf 負載 mongo 角色 筆記內容:mongodb副本集搭建筆記日期:2018-01-09 21.33 mongodb副本集介紹 21.34 mongodb副本集搭建 21.35 mongodb副本集測試 2

MongoDB副本的搭建

tom parent 搭建 sof mongodb disable 轉換 gpa kernel 參考博文:https://www.jianshu.com/p/ca620842868a 一、安裝準備1、修改系統配置#關閉selinux、firewall#修改/etc/secu

Mongodb副本群搭建

組件 std gap logs monit plog replicat nat 安裝mongodb 一、環境準備 1.1.主機信息(機器配置要求見硬件及開發標準規範文檔V1.0) 序號 主機名 IP 1 DB_01 10.202.105.52

MongoDB副本的常用操作及原理

Mongodb 大數據 雲計算下面的操作主要分為兩個部分: 修改節點狀態 主要包括: 將Primary節點降級為Secondary節點凍結Secondary節點強制Secondary節點進入維護模式2.?修改副本集的配置 添加節點刪除節點將Secondary節點設置為延遲備份節點將Secondary節點設

MongoDB副本

MongoDBMongoDB副本集 早期版本使用master-slave,一主一從和Mysql類似,但slave在此架構中為只讀,當主庫宕機後,從庫不能自動切換為主 目前已經淘汰master-slave模式,改為副本集,這種模式下有一個主(primary),和多個從(secondary),只讀。支持給它們設

JavaWeb學習筆記ServletConfig()ServletContext()

通過 metadata ips rac oid enume 節點 接口 init ServletConfig()和ServletContext() 1.Serv