Mongodb復制集和分片
1、復制集
MongoDB為了保證數據的完整性,提出了復制集的概念(replica set),它通過數據的冗余備份備份的方式,在多個服務器上存儲數據副本,避免了單點故障的問題,提高了數據的可用性,保證了數據的安全性,同時還允許從硬件故障和服務中斷中恢復數據。
1.1 復制集成員
MongoDB的復制集是由一組mongod實例所組成的,并提供了數據冗余與高可用性。復制集中的成員有以下幾種:
Primary:主節點,負責接收所有的寫操作,通知從節點的數據變動情況。
Secondaries:從節點,響應主節點的數據變動情況,保持其數據集與主節點的一致。
arbiter:仲裁節點,仲裁節點其本身并不包含數據集。但是,一旦當前的主節點不可用時,投票節點就會參與到新的主節點選舉的投票中。
備注:當節點數目為奇數時,可以不需要仲裁節點。節點數目為偶數個時,需要部署一個仲裁節點,否則偶數個節點,當主節點掛了后,可能會出現兩個從節點得票相同的情況,無法選舉出主節點。
主節點是復制集成員中唯一能夠接收寫操作的節點,并記錄操作日志(oplog)。然后從節點會根據操作日志來同步自己節點的數據保持與主節點一致。集群中所有的成員都會發送心跳(Heartbeat,其實就是ping)給對方,感知彼此之間是否一直在線。
1.2 操作日志
操作日志(oplog)oplog是capped Collection,因為oplog的特點(不能太多把磁盤填滿了,固定大小)需要,MongoDB才發明了capped Collection(the oplog is actually the reason capped collections were invented),oplog位于local庫中。復制集中的所有成員在local庫中都能找到這local.oplog.rs這個集合。
在64位版本中,不管當前MongoDB的數據存儲引擎是什么,oplog的默認大小都是192MB[l1] 。有時候為了應付更大的數據量,啟動時可以使用oplogSizeMB參數來指定操作日志集合的大小。修改操作日志大小必須要重啟復制集,并且要將復制集主節點變更為從節點后才能重啟,這樣做的目的是為了保持數據集中的數據一致。重啟后,可以重新制定oplogSizeMB參數大小。切換到local數據庫后,可以使用rs.printReplicationInfo()來查看當前操作日志的信息。
1.3數據同步
為了保證從節點的數據實時同步,MongoDB主從節點數據同步由兩部構成:初始化同步和實時備份。當復制集添加新的成員時,初始化同步保證了從節點的數據能夠從復制集的其他節點完整的復制過來;當復制集的數據量不停增長時,實時備份保證了急群眾各個節點的數據一致性。
備注:經過實踐發現,MongoDB下的local庫下的集合并不會參與數據同步。
1.4復制集部署
1.4.1部署主節點
a)啟動主節點mongod進程
mongod --replSet replication_db_set --dbpath ./replication_db_primary --bind_ip 10.171.60.150 --port 27017
b)使用mongo連接主節點,初始化復制集
mongo 10.171.60.150:27017
> rs.initiate()
初始化后,當前節點會成為主節點,如下所示:
> replication_db_set:PRIMARY>
1.4.2部署從節點
a)啟動從節點mongod
mongod --replSet replication_db_set --dbpath ./replication_db_second --bind_ip 10.171.60.150 --port 27018
b)使用mongo連接主節點,添加從節點
replication_db_set:PRIMARY> rs.add("10.171.60.150:27018")
這時候使用mongo連接從節點,可以發現命令提示符變成了:replication_db_set:SECONDARY>
1.4.3添加仲裁節點
a)啟動仲裁節點mongod
mongod --replSet replication_db_set --dbpath ./replication_db_second --bind_ip 10.171.60.150 --port 27019
b)使用mongo連接主節點,添加仲裁節點
replication_db_set:PRIMARY> rs.addArb("10.171.60.150:27019")
2、分片
隨著MongoDB存儲的數據量不斷的增長,CPU、內存和磁盤IO的負載將會越來越高,從而導致性能下降。為了解決這個問題,MongoDB提出了分片(Sharding)的概念。分片的基本思想就是把集合切割成若干小的數據塊塊,這些數據塊分布的灑在集群中各個主機上。分片對于應用而言其實是屏蔽的,應用不必關心數據時如何存儲的,因為在分片模式下,MongoDB會使用路由進程(Mongos進程)來管理分片數據的分布,所以應用只需要范圍路由進程就可以了。MongoDB只支持集合(collection)級別的分片,并需要從集合中選取一個鍵來作為數據拆分的依據,這個鍵即為片鍵。片鍵這個概念后續會詳細介紹。
2.1分片集群成員
Shard:分片是存儲了一個集合部分數據的MongoDB實例,每個分片是單獨的mongod或者是復制集(replica set)。實際應用場景中,所有的分片都應該是復制集。
mongos:mongos是數據庫集群請求的路由,所有的請求都通過mongos進行。它負責把對應的數據請求請求轉發到對應的分片服務器上。實際應用場景中,分片集群可以考慮部署多個mongos作為請求的入口,防止其中一個掛掉所有的mongodb請求都沒有辦法操作。
Config Servers:配置服務器,存儲所有數據庫元信息:路由(mongos)、分片(shard)的配置。mongos本身沒有物理存儲分片服務器和數據路由信息,只能存儲在配置服務器上。mongos第一次啟動或者關掉重啟就會從配置服務器加載配置信息,配置服務器信息變化會通知到所有的路由更新自己的狀態。實際應用場景中,,通常會部署多個配置服務器,因為它存儲了分片路由的元數據,就算其中一臺意外宕機,只要還有配置服務器正常工作, mongodb分片集群就不會掛掉。
2.2片鍵和數據塊
MongoDB會選擇文檔中的一個或多個Field來作為片鍵(Shard key),根據片鍵的值來分割集合中的文檔,形成一個個的數據塊(Chunk),然后再將這個數據塊平均分配到集群中的各個分片上。一個數據塊存放片鍵的一個區間范圍的數據。選擇一個好的分片字段非常重要,否則就會遭遇到不能被拆分的大Chunk。
2.2.1基于片鍵值范圍的分片
基于范圍的分片,MongoDB按照片鍵的范圍把數據分成不同部分。就如同坐標軸中的X軸一樣,MongoDB會根據片鍵來劃分一定的數據范圍,這個范圍內的數據就是數據庫(Chunk)。
2.2.2基于片鍵哈希的分片
基于哈希的分片,MongoDB計算一個片鍵的哈希值,并用這個哈希值來創建數據塊。在使用基于哈希分片的系統中,擁有“相近”片鍵的文檔很可能不會存儲在同一個數據塊中,因此數據的分散性更好一些。
2.2.3范圍和哈希分片方式對比
基于范圍的分片方式提供了更高效的范圍查詢,給定一個片鍵的范圍,分發路由可以很簡單地確定哪個數據塊存儲了請求需要的數據,并將請求轉發到相應的分片中。不過基于范圍的分片會導致數據在分布不均衡。如果片鍵所在的字段是線性增長的,一定時間內的所有請求都會落到某個固定的數據塊中,最終導致分布在同一個分片中。在這種情況下,一小部分分片承載了集群大部分的數據形成了數據傾斜。
與此相比,基于哈希的分片方式以范圍查詢性能的損失為代價,保證了集群中數據的均衡。哈希值的隨機性使數據隨機分布在每個數據塊中,因此也隨機分布在不同分片中。但是也正由于隨機性,一個范圍查詢很難確定應該請求哪些分片,通常為了返回需要的結果,需要請求所有分片。
2.3數據傾斜
新數據的加入或者新分片的加入可能會導致集群中數據的傾斜,即表現為有些分片保存的數據塊數目顯著地大于其他分片保存的數據塊數。作為片鍵的Field值如果是單調遞增或者遞減的話,入庫時MongoDB會將這些文檔劃分到同一個Chunk中,如此就會失去分布式的優勢,集群所有的讀寫操作都會集中在這個分片上。
2.3.1數據塊的切分
MongoDB數據塊默認大小為64MB,可以通過連接到配置服務器,通過db.settings.save( { _id:"chunksize", value:
} )命令來修改數據塊的大小。修改數據塊大小時要注意以下幾點:
1數據塊大小較小時可以使得分片間的數據更均衡,但是會造成頻繁的遷移,會增加mongos路由的負載。
2數據塊大小較大時會使得均衡較少,這從網絡傳輸與mongos的角度來說更高效,但是,這種高效是通過數據不均衡的加重為代價的。大部分應用場景下,可以稍微犧牲一點均衡,來避免集群中數據塊頻繁地分裂和遷移。
2.3.2數據塊分裂
分裂是MongoDB避免數據塊過度增長的一種方式。當數據塊的大小超過配置大小時,數據塊就會根據片鍵分裂成多個數據塊。但是分裂會導致整個集群中每個分片的數據塊數不一致,新的數據插入或者更新時,會造成整個集群的數據負載不均衡。這個時候需要遷移數據塊來保證集群的負載均衡。
2.3.3數據塊遷移
隨著數據的增長,集群中的數據塊會分裂得越來越多。這時候,各個分片上的數據塊數量就會不平衡。這時候,路由mongos中的一個組件balancer就會執行自動平衡。把數據塊從數量最多的分片節點挪動到數量最少的節點。
2.3.4不可切分的數據塊
不可切分的數據塊一般是由于片鍵的選擇不合理導致的,片鍵對應的值的變化范圍太小,導致切分的數據塊對應的范圍很小或者就只有一個值,這樣的話就會造成集群中一個分片只對應了一個數據塊。應該選取值范圍變化較大的Field作為片鍵,或者使用組合Field作為片鍵。
2.4分片集群部署
在部署集群分片時,所有的集群成員分片、mongos路由和配置服務器都要使用冗余備份,避免單點故障。其中分片節點和配置服務器節點以復制集(replica set)方式實現冗余備份;mongos路由可以使用多個實例方式實現冗余備份。如下示例展示了如何部署分片集群。
2.4.1部署配置服務器
mongod --dbpath /mongodb_workspace/sharding_db/sharding_config_db --bind_ip 10.171.60.150 --port 17020
備注:這里簡單實例只啟動了一個配置服務器實例,并且未使用復制集冗余備份,會存在單點故障的問題。
2.4.2部署mongos路由
mongos.exe --configdb 10.171.60.150:17020 --port 17021
備注:這里啟動了一個路由,一般情況下推薦在不同的機器上部署多個mongos路由。依賴的配置服務器這里也只部署了一個,如果10.171.60.150:17020未采用復制集方式部署,會存在單點故障問題,可以同時啟動多個配置服務器,在啟動mongos路由時,指定多個配置服務器,中間以”,”分隔。
2.4.3部署Shard分片
a)部署分片
mongod --dbpath /mongodb_workspace/sharding_db/sharding_db_1 --bind_ip 10.171.60.150 --port 17022
mongod --dbpath /mongodb_workspace/sharding_db/sharding_db_2 --bind_ip 10.171.60.150 --port 17023
b)注冊分片
使用mongo命令連接到mongos路由
mongo 10.171.60.150: 17021
在命令提示符中添加分片到mongos路由
mongos> sh.addShard("10.171.60.150:17022")
mongos> sh.addShard("10.171.60.150:17023")
備注:這里部署的分片沒有使用復制集方式部署,在實際應用場景中,對應的每個分片應當使用復制集方式復制,避免故障問題。使用復制集方式部署時,向mongos路由注冊信息時,應加上復制集名稱并跟上復制集主節點的ip和端口。例如“replication_db_set/10.171.60.150:27017”, replication_db_set為復制集名稱,10.171.60.150:27017為復制集主節點實例。
2.4.4開啟分片功能
分片集群部署完成之后并不知道如何分片,也不知道對哪個數據庫進行分片,更不知道對哪個集合進行分片。這個時候需要手動指定分片的數據庫和集合。
a)為指定的數據塊開啟分片功能
連接到mongos路由
mongo 10.171.60.150: 17021
在命令提示符中執行如下命令,開啟數據塊分片功能,其中
為開始分片功能的數據塊名稱
mongos> sh.enableSharding("
")
b)為指定的集合開啟分片功能
連接到mongos路由
mongo 10.171.60.150: 17021
mongos>sh.shardCollection("
.
",{"
":1})
備注:開啟集合分片功能需要指定分片的片鍵。如果該集合已經存在,需要確認分片的片鍵是否已經構建過索引,如果沒有,需要構建索引后才能進行分片。如果該集合不存在,則可以直接指定片鍵進行分片。如上
表示已經支持分片的數據庫,
表示該數據庫下一個待分片的集合,
為片鍵
我自己新建了一個Replication Set,發現默認大小5622.878319740295MB,并未做任何修改。
轉載請注明出處:華為云博客 https://portal.hwclouds.com/blogs
MongoDB TCP/IP 存儲
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。