MongoDB之分片叢集(Sharding)
一、基本概念
分片(sharding)是一個通過多台機器配置設定資料的方法。MongoDB使用分片支援大資料集和高吞吐量的操作。大資料集和高吞吐量的資料庫系統挑戰着單一服務的性能。例如:高查詢率将耗盡CPU的性能。大于系統RAM的工作集将給磁盤的IO很大的壓力。
應對系統的增長有兩個方法:垂直擴充和水準擴充。
垂直擴充的方法是提升單一服務的性能,例如:使用一個更強的CPU,或更多的記憶體,或提升大量的存儲空間。可用技術的局限性将限制單一服務的工作負載。另外基于雲的提供者也有硬體配置的上限。是以,垂直擴充是有上限的。
水準擴充的方法是将系統的資料集配置設定到多個服務上,添加額外的服務可以提升系統的能力。一個單獨機器的性能和速度可以不是很高,每台機器處理整個工作負載的一個子集,潛在地相比一個單一的高速度、高性能的服務,提供了更好的性能。擴充部署的能力僅僅需要添加額外的需要的服務,這比添加高檔的硬體要便宜不少。
1.1分片叢集
MongoDB 的分片叢集由下面的幾個元件組成:
- 分片(shard):每個分片包含了分片資料的一個子集,每個分片可以作為一個副本集部署。
- mongos:mongos扮演者查詢路由的角色,提供着用戶端應用和分片叢集的接口。
- config servers:配置服務存儲着叢集的中繼資料和配置設定,MongoDB3.4以後,配置服務必須部署成副本集。
下圖描述了分片叢集中,各個元件的互動
image1
mongodb在collection級别對資料進行分片,配置設定collection資料到叢集中的每一個分片。
1.2分片主鍵(shard keys)
為了在集合中配置設定文檔,MongoDB使用分片主鍵分割集合。分片主鍵由不重複的字段或者字段集合組成。
對一個集合分片時,你要選擇分片主鍵,分片主鍵在分片以後不能修改。一個分片集合隻有一個分片主鍵。
為了對非空的集合進行分片,集合必須有一個以分片主鍵開頭的索引。對于空集合,如果集合對于分片主鍵沒有一個合适的索引,MongoDB将建立索引。
分片主鍵的選擇将影響分片叢集的性能、效果和擴充能力。一個最佳的硬體和基礎設施的叢集的瓶頸取決于分片主鍵的選擇。分片主鍵的選擇将影響你的叢集使用的分片政策。
1.3區塊(chunks)
MongoDB分割分片資料到區塊,每一個區塊包含基于分片主鍵的左閉右開的區間範圍。在分片叢集中,MongoDB通過分片遷移區塊,使用分片叢集權衡器。權衡器視圖完成一個公平的區塊平衡,通過叢集中所有的分片。
1.4分片的優點
MongoDB通過叢集中的分片配置設定讀和寫的工作負載,允許每個分片處理叢集中的一部分操作,讀和寫的工作負載可以通過添加分片進行橫向擴充。包含分片主鍵或者組合主鍵字首的查詢,mongos可以定位這個查詢到特定的分片或者分片子集上。這種定位操作比廣播到所有分片要高效的多。
叢集中的分片存儲整個資料中的一部分,随着資料的增長,增加額外的分片可以增加叢集的存儲能力。
即使叢集中的一個或多個分片不可用,叢集也可以繼續執行一部分讀寫操作。在當機期間,不可用的分片上的資料是不能夠處理的,可用分片上的讀寫操作是可以被成功處理的。在生産環境,每一個分片将被部署成副本集,提供可增長的備援和高可用。
1.5 分片之前的考慮
分片叢集的基礎需求和複雜性需要小心的計劃、執行和維護。謹慎地考慮分片主鍵是確定叢集性能和效率所必須的。在分片之後,你不能改變分片的主鍵,也不能使集合不分片。如果查詢不包含分片主鍵或者組合主鍵的字首,mongos将執行廣播操作,查詢所有分片,這些查詢将執行很長時間。
1.6分片和不分片集合
一個資料庫可以有分片集合和不分片集合的混合,分片集合通過叢集中的分片進行分割和配置設定,不分片集合将存儲在基礎分片中。每個資料庫都有一個自己的基礎分片。
image2
1.7 連接配接分片叢集
你必須連接配接mongos路由和集合中的集合進行互動。這包含分片和不分片的集合。用戶端絕不可能連接配接一個單獨的分片進行操作。你可以像連接配接mongod一樣連接配接mongos,他們是一樣的。
image3
1.8分片政策
MongoDB支援兩種分片政策進行資料分片。
Hash分片
Hash分片是計算一個分片主鍵的hash值,每一個區塊将配置設定一個範圍的hash值。
image4
當分片主鍵中的一個範圍被“關閉”,他們的hash值不可能在相同的區塊中。基于hash值分布的資料促使了更多的資料分布,特别是分片主鍵單調變化的資料集。
Hash分布意味着基于分片主鍵的範圍查詢很少可能命中一個單一的分片,導緻了更多的廣播操作。
範圍分片
範圍分片是基于分片主鍵的值切分資料,每一個區塊将會配置設定到一個範圍。
image5
分片主鍵的範圍被“關閉”,他們也很有可能落在相同的區塊中。這使得mongos可以路由操作到請求資料的分片上。範圍分片的效率取決于分片主鍵的選擇,欠考慮的分片主鍵将導緻資料分布不均勻。這将取消一些分片的益處,還可以導緻性能瓶頸。
二、分片叢集的搭建
由于測試機有限,這裡我們隻展示最簡單的分片搭建,即一個分片、一個配置服務、一個路由。
image6
首先,我們啟動配置服務,配置服務的mongodb的配置檔案如下:
sharding:
clusterRole: configsvr
replication:
replSetName: "rs"
net:
bindIp: 192.168.2.233
clusterRole設定成configsvr,表名這個mongod是配置服務;副本集的名字叫做“rs”。
./bin/mongod --config conf/mongod.conf
然後,我們通過mongo shell連接配接這個mongod執行個體。
mongo --host 192.168.2.233 --port 27019
值得注意的是,配置服務啟動時,預設的端口是27019,本人一開始并沒有注意到,一直連接配接27017,連接配接不上,最後才發現端口不對。然後添加副本集。
rs.initiate()
傳回如下:
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "192.168.2.233:27019",
"ok" : 1,
"operationTime" : Timestamp(1519283130, 1),
"$gleStats" : {
"lastOpTime" : Timestamp(1519283130, 1),
"electionId" : ObjectId("000000000000000000000000")
},
"$clusterTime" : {
"clusterTime" : Timestamp(1519283130, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
當出現ok=1時,說明添加成功了。
其次,我們啟動shard執行個體。配置檔案的内容如下:
sharding:
clusterRole: shardsvr
replication:
replSetName: "rs0"
net:
bindIp: 192.168.2.234
clusterRole配置shardsvr,說明這個執行個體是shard執行個體。副本集的名字我們叫做“rs0”,差別于配置服務的“rs”。啟動mongod執行個體
./bin/mongod --config conf/mongod.conf
通過mongo shell連接配接這個執行個體
./bin/mongo --host 192.168.2.234 --port 27018
注意shard的執行個體啟動時端口預設為27018。然後初始化副本集
rs.initiate()
傳回結果如下:
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "192.168.2.234:27018",
"ok" : 1
}
最後啟動mongos執行個體,配置檔案内容如下:
sharding:
configDB: rs/192.168.2.233:27019
net:
bindIp: 192.168.2.235
configDB是配置服務副本集的名字,格式如下:副本集名稱/ip:端口。啟動mongos執行個體
./bin/mongos --config conf/mongod.conf
注意這裡的指令是mongos,而不是之前的mongod。通過mongo shell連接配接這個執行個體
./bin/mongo --host 192.168.2.235 --port 27017
這裡的端口是mongodb的預設端口27017。向叢集中添加分片
sh.addShard( "rs0/192.168.2.234:27018")
分片的格式為:副本集名稱/ip:端口。然後添加分片的資料庫
sh.enableSharding("<database>")
配置分片的集合和主鍵
sh.shardCollection("<database>.<collection>", { <key> : <direction> } )
<key>為主鍵字段的名字。
<direction>為以下3種:
- “1”:主鍵值正向周遊;
- “-1”:主鍵值反向周遊;
- “hashed”:主鍵hash值
至此,MongoDB的分片叢集介紹完了。