Mongodb Manual閱讀筆記:CH9 Sharding


9.分片(Sharding)

Mongodb Manual閱讀筆記:CH2 Mongodb CRUD 操作
Mongodb Manual閱讀筆記:CH3 數據模型(Data Models)
Mongodb Manual閱讀筆記:CH4 管理
Mongodb Manual閱讀筆記:CH5 安全性
Mongodb Manual閱讀筆記:CH6 聚合
Mongodb Manual閱讀筆記:CH7 索引
Mongodb Manual閱讀筆記:CH8 復制集
Mongodb Manual閱讀筆記:CH9 Sharding

 

隨着數據增長,shard是多機器處理數據存儲的方式。shard是橫向擴展的解決方案。

9.分片(Sharding)1

9.1 Sharding說明... 1

9.1.1 Shard的目的... 1

9.1.2 Mongodb中的Shard. 1

9.1.3數據分區... 1

9.1.3.1 Shard Keys. 1

9.1.3.2 Range分區... 1

9.1.3.3 Hash分區... 1

9.1.3.4 Range分區和Hash分區的性能區別... 1

9.1.4 維護數據均衡發布... 1

9.1.4.1 分離(Splitting)1

9.1.4.2均衡(Balancing)1

9.1.4.3 增加和刪除Shard. 1

9.2 Sharding 概述... 1

9.2.1 Shard集群組件... 1

9.2.1.1 Shards. 1

9.2.1.2 Config服務... 1

9.2.2 Shard集群體系結構... 1

9.2.2.1 Shard集群要求... 1

9.2.2.2生產環境集群結構... 1

9.2.2.3測試環境的體系結構... 1

9.2.3 Shard集群特性... 1

9.2.3.1 Shard Key. 1

9.2.3.2 Shard集群高可用性... 1

9.2.3.3 Shard集群查詢路由... 1

9.2.4 Shard機制... 1

9.2.4.1 Shard Collection均衡... 1

9.2.4.2 ShardChunk遷移... 1

9.2.4.3 Shard集群下Chunk的分離... 1

9.2.4.4 Shard Key索引... 1

9.2.4.5Shard集群元數據... 1

9.3 Shard集群教程... 1

9.3.1 Shard集群部署教程... 1

9.3.1.1部署shard集群... 1

9.3.1.2考慮Shard Key. 1

9.3.1.3使用Hash Shard Key. 1

9.3.1.4 Shard集群的認證... 1

9.3.1.5添加Shard到集群... 1

9.3.1.6為生產環境部署3Config服務... 1

9.3.1.7把復制集轉化為shard集群... 1

9.3.1.8shard集群轉化為復制集... 1

9.3.2 Shard集群維護教程... 1

9.3.2.1查看集群配置... 1

9.3.2.2使用相同的hostname遷移config. 1

9.3.2.3在不同HostName之前遷移config. 1

9.3.2.4替換一個Config服務... 1

9.3.2.5遷移集群到不同的硬件環境... 1

9.3.2.6備份集群元數據... 1

9.3.2.7配置均衡器進程行為... 1

9.3.2.8管理均衡器... 1

9.3.2.9刪除Shard集群中的Shard. 1

9.3.3 Shard集群的數據管理... 1

9.3.3.1創建Chunks. 1

9.3.3.2 Split Chunk. 1

9.3.3.3遷移Chunk. 1

9.3.3.4修改Chunk的大小... 1

9.3.3.5 Tag意向Sharding. 1

9.3.3.6管理Shard Tag. 1

9.3.3.7 shard集群強制唯一鍵... 1

9.3.3.8 Shard GridFS數據存儲... 1

9.3.4 Shard集群Troubleshoot. 1

9.3.4.1 Config數據庫錯誤字符串... 1

9.3.4.2 因為老的config數據導致游標錯誤... 1

9.3.4.3在移動config服務避免下線... 1

9.4 Shard Reference. 1

 

9.1 Sharding說明

9.1.1 Shard的目的

當數據庫數據增大,應用程序高吞吐量會對單服務的能力進行挑戰。查詢過大cpu使用過大,數據過大要要求存儲能力,working set 過大要求RAMIO能力。

為了解決這個問題,有2個基本的方案:水平擴展,垂直擴展。

水平擴展:添加更多的cpu,存儲資源來這更加處理能力。大cpu大內存的設備價格會遠遠大於小設備。

Sharding:是一種水平擴展,把數據分片到各個設備上。每個分片都是一個獨立的數據庫。

sharding處理大數據,大吞吐量的好處:

1.減少了在每個shard上的操作

2.減少了每個shard上的數據保存量。

9.1.2 Mongodb中的Shard

shard集群由以下幾個組件:shardquery routersconfig server

Shard:用來存儲數據。提供高可用和數據一致性,在生產環境下一個shard是一個復制集

Query Routers:或者mongos實例,是客戶端的接口然后在合適的shard中型操作然后返回數據。對於shard集群可以包含多余一個router來分流客戶端請求。一個客戶端發送請求到一個router,大多數shard集群由很多query router

Config Server:保存集群元數據,query router根據config server上的元數據來決定路由到哪個shard

9.1.3數據分區

mongodb分發數據或者分配是在collection級別的,同歸shard keycollection進行分片。

9.1.3.1 Shard Keys

Shard Keys必須每個文檔都有,並且要不是索引的字段,要不是組合索引的字段。mongodbshard key划分為chunks,然后發布這些chunk到各個shard。可以使用range分區也可以是hash分區。

9.1.3.2 Range分區

Mongodb通過shard key把數據分為若干個區間。給定一個Rangekey近的理論上在同一個文檔上。

9.1.3.3 Hash分區

hash分區是根據文檔中的字段計算hash,然后使用這些hash來創建chunk。那么即使shard key值相近也可能不在同一個chunk中。

9.1.3.4 Range分區和Hash分區的性能區別

對於Range分區,區間查詢更加有效,路由可以很容易的決定哪些chunk可以覆蓋這些查詢,然后路由到想要的shard上。

Range分區會導致數據不均勻,會否定shard帶來的好處,會導致大量數據堆積在同一個shard上,弱化了shard的優勢。

Hash分區確保了數據的均勻分布,但是對於區間查詢就不可用對一些shard進行炒作,會對所有shard產生影響。

9.1.4 維護數據均衡發布

新增的數據或者新增的服務會導致數據發布不均衡。有一些chunk會包含比其他chunk大的多的數據,或者比其他chunk的數據更加重要。

9.1.4.1 分離(Splitting)

Splitting是一個后台進程,不讓chunk變得太大,當chunk超過閥值是就會splits,split會影響元數據,split不會遷移也不會影響shard

9.1.4.2均衡(Balancing)

均衡器也是后台進程用來管理chunk遷移。

當發布數據不均衡的時候,均衡器會從多的shard遷移到小的shard.

1.chunk遷移的時候,目標shard會獲取chunk上的所有文檔。

2.然后目標shard獲取在遷移過程中所有的修改

3.最后shard修改config中相應的location

4.然后刪除源中的chunk。但是要遷移大於1chunk的時候,不會先刪除,而是進入下一個chunk的遷移。

9.1.4.3 增加和刪除Shard

增加和刪除shard,都要遷移chunk

9.2 Sharding 概述

9.2.1 Shard集群組件

Shard集群有一下幾個組件:

Shard:一個shard是一個mongodb實例,保存了collection數據的一個子集,Shard是單實例,也可以是復制集。

Config Server:每個config server是一個mongod實例,保存了元數據。

Routing Instances:路由是mongos實例,路由從應用程序到shard的讀寫。應用程序不能直接路由到shard

9.2.1.1 Shards

Shard可以是復制集也可以是一個實例,保存了shard集群的部分數據。通常shard是一個復制集,復制集為每個shard提供了冗余和可用性。

Primary Shard

每個數據庫都有一個primary shard用來保存非shard collection

 

可以使用movePrimary命令來修改shard primary 數據庫。當部署新的shard集群時,第一個shard會變成primary

Shard狀態

使用sh.status()來查看shard狀態。

9.2.1.2 Config服務

Config服務比較特殊,保存了shard集群內的所有的元數據。Config服務之間使用二階段提交的方式來保證一致性和可靠性。Config服務不能使用復制集,所有config服務必須是可用的,來保證元數據的修改。

一般生產環境需要3config服務。當只有一個config 服務,出現單點故障后,config數據被恢復之前是不能訪問集群的。

Config數據庫

Config服務把元數據存放在config數據庫中,mongos會緩存這些數據,來路由數據庫操作。

Config服務的讀寫

只有在一下情況下會寫config 服務:

1.在已存在的chunk上創建split

2.shard之前遷移chunk

再有在一下情況下會讀config服務:

1.mongos第一次啟動

2.遷移chunk后,mongos更新自己的cache

Config服務可用性

當有3config 服務其中1個或2個不可用的時候,集群的元數據變為只讀,可以讀數據,但是不能遷移chunk或者創建split

如果3config服務都不可用,如果不重啟mongos那么任然可以使用集群,如果在config服務可用之前mongos重啟了,mongos就不能再路由。

當沒有元數據的時候集群變得不可操作,所以保持一個可用的完好的config十分重要。備份起到一個很關鍵作用。Config服務的數據和整個集群比很小,負荷也少,並且config服務並不要求一直可用來支持shard集群。

shard集群使用的config服務修改了名字或者地址,需要重啟每一個mongodmongos,為了避免這種情況,可以使用CNAME來唯一標示衣蛾ocnfig服務。

 

9.2.2 Shard集群體系結構

介紹:shard集群要求,生產環境shard集群結構體系,shard集群測試環境的結構體系。

9.2.2.1 Shard集群要求

Shard是很給力的功能,但shard集群有很多設備的要求,增加了整體部署的復雜性。

對於某些情況來說shard是唯一的解決方法:

1.數據集超過了單個實例處理的能力

2.數據集需要的內存超過了單個實例可以提供的內存

3.大量寫的需求,使用其他方法無法解決。

如果沒有以上的情況,使用shard只會影響整體的復雜性。

Shard的部署比較花時間,如果系統已經到達了處理能力的邊界,再部署shard肯定會影響應用程序的使用。

Shard的部署應該在設計數據結構的時候就應該考慮。

數據量需求

集群會管理大量的數據,數據以chunk為單位進行管理,chunk的大小默認是64MB,當shard之間chunk不均衡的時候(超過了閥值),均衡器會在shard之間遷移chunk知道均衡為止。對於小的collection來說shard是不合算的,光增加了復雜性,除非有寫入性能的要求。Chunk默認大小64MB,是可以配置的

9.2.2.2生產環境集群結構

在生產環境下,要保證數據冗余和系統高可用。

組件

Config Server:3Config Server,每個config server有獨立的設備,一個shard獨占使用config。也就是說config 不能被shard集群共享。

Shards:2個以上的shard,這些shard要求是復制集

Query Rounters(mongos):一個或多個mongosmongos用來路由,一般是每個應用程序服務都有一個mongos實例。

當然,可以在mongos和應用程序之間使用代理和負載均衡,這種情況下使用client affinity來配置負載均衡,這樣同一個鏈接可以一直使用同一個mongos

9.2.2.3測試環境的體系結構

測試環境下:1config server1個以上shard,一個mongos實例。

9.2.3 Shard集群特性

介紹:shard keyshard集群高可用性,shard集群路由

9.2.3.1 Shard Key

Shard key確定了collection的數據分布,shard key是索引字段,或者是組合索引字段。

Mongodb使用shard key來切分collection,每個區間或者chunk,不能重疊。然后mongodb分發這些chunks

Hash過的Shard key

也就是說shard key 可以是一個hash值。

選擇字段的時候最好,字段有很高的選擇性(相同值數量很少)Hash key在單調遞增的字段上也很不錯比如objectid或者時間戳。

如果在一個空的collection上使用hash作為shard keymongodb會自動創建和遷移chunk,所以每個shard會有2chunk,當然這個可以通過shardCollection命令中的numInitChunks參數來控制,也可以通過split命令手動創建chunk

Shard key對集群的影響

Shard key通過確定數據的分區和mongos對集群的有效操作來影響性能。

寫能力擴展shard key會增加寫入的性能,以下objectid為例。

Mongodb為每個文檔創建一個objectid,但是有個問題是,是單調增長的,所有的插入都會在一個chunk上一個shard上,那么這個shard寫入能力就是整個集群的寫入能力。

只有當單調的增加為shard key的很少有插入,這樣對性能的影響比較少。

通常使用shard key需要一點隨機性。可以讓集群擴展寫能力。但同時這樣的shard key不能提供查詢隔離,這個也是shard key重要特性之一。

查詢mongos提供了應用程序到shard集群的接口,mongos接受應用程序的請求,使用config server的元數據進行路由,路由到有相應數據的mongod。當mongos路由所有查詢操作時,shard key會對查詢有很大的影響。

查詢隔離:在shard環境中,最快的查詢是通過shard key 和元數據被路由到一個shard上的查詢。對不包含shard key 過濾的查詢會被路由到所有的shard會比較慢。若shard key是組合的,查詢對shard key 前綴進行過濾,那么可以被路由到某些shard

Shard key的選擇:

1.查詢中最常用到的字段

2.哪些操作對性能有很高的依賴

如果一個字段選擇度很差,那么就再加個字段提高選擇度。

排序:在shard環境下,mongos執行合並排序法來排序從shard中出來的結果

9.2.3.2 Shard集群高可用性

在生產環境下,不能產生單點故障

應用程序或者mongos不可用

如果每個應用程序服務都有自己的mongos,當不可用時,其他的應用可以使用自己的mongosMongos自己不保存數據,重啟后不會有數據丟失。

一個shard不可用

Shard級別,復制集提供了可用性,如果primary變得不可用,復制集就會投票生成另一個primary。如果是secondary不可用不影響使用。如果系統變得不可恢復,那么增加新的成員來彌補冗余。

復制集所有成員不可用

如果整個復制集不可用,shard內的數據也變得不可用,但是其他shard的數據還是可用的。就有可能讀寫到其他成員。所有要能夠處理這部分數據,調查清楚問題並恢復。

一個以上Config 數據庫不可用

如果有3個不同的config數據,config 數據庫之間是使用二階段提交的。整個集群還是可用的,但是chunk遷移,chunk分離。如果所有config不可用,那么整個集群就不可用。

重命名Config服務和集群可用性

如果連接到config的名字和地址被修改,必須重啟所有的mongodmongos。使用CNAMEDNS)可以完成換服務器,但是可以不修改連接字符串。

Shard key和集群可用性

選擇Shard Key要考慮:

1.保證mongod可以均勻的分布數據

2.可以擴展寫能力

3.保證mongos在大多數查詢上可以查詢隔離,也就是路由到指定的mongod

跟多:

1.每個shard應該是一個復制集

2.如果可以隔離大多數操作,shard不可用,只會影響部分數據。

3.如果每個操作都要發布到整個集群,當一個shard不可用會導致整個集群不可用。

9.2.3.3 Shard集群查詢路由

Shard對應用程序來說是透明的。Mongos緩存了config的數據,進行路由工作。一般的做法mongos都是在應用程序服務器上,也可以在shard上或者其他專用設備上。

路由進程

Mongos使用一下過程路由到結果:

決定哪些Shard接收查詢

1.確定哪些shard必須接收查詢

2.在這些shard上創建游標。

如果查詢中使用shard key或者shard key前綴過濾可以只查詢shard的子集。

Mongos如何處理查詢Modifiers

如果查詢的結果不要求是排序的,mongos會打開一個游標然后循環shard上來的結果。如果指定了排序,那么把排序給shardmongosshard基礎上執行合並排序。如果有limit會把limit傳給shard,再在結果上limit。若有skip那么不會傳,如果有limitskip那么會傳limit,傳給shardlimit的個數為skip個數加上limit的個數。

診斷到Mongos的連接

如果連接到的是mongos,使用ismaster命令會返回:

{

"ismaster":true,

"msg":"isdbgrid",

"maxBsonObjectSize":16777216,

"ok":1

}

其中msgisdbgrid,如果連接到的是mongod不會包含isdbgrid

廣播操作和目標操作

shard集群中操作有2:

1.會廣播到所有shard的操作,如remove

2.以一部分shard為目標的操作,如insert

Shard和非Shard數據

Shard是在collection級別的,可以在多個數據庫的多個collectionshard。不管集群的結構,所有的查詢和操作都使用mongos路由到數據中心。

9.2.4 Shard機制

介紹,shard collection均衡,chunk遷移,chunk splitShard key所有,shard集群元數據。

9.2.4.1 Shard Collection均衡

Mongodb使用均衡器來平衡shard之間的數據。當一個shard的數據過多,均衡器會啟動分發給其他shard

集群均衡器

均衡器是用來均衡shard之間的數據量,默認均衡器是開啟的。

任何mongos實例都可以啟動均衡流程。當均衡器被激活,mongos要修改config數據庫中的lock collection,獲得鎖。

均衡器一旦啟動,只有當chunk均衡的時候才會停止。

Chunk遷移會導致負荷上升,影響應用的性能。有2個方法減少影響:

1.一次只遷移一個chunk

2.或者只有當最大chunks個數和最小chunks個數只差超過一個閥值。

當然也可以臨時關閉均衡器

遷移閥值

Number of Chunks

Migration Threshold

Fewer than 20

2

21-80

4

Greater than 80

8

一旦均衡器啟動只有當2shardchunk差為2或者遷移失敗才會停止。

Shard 大小

默認mongodb會試圖占滿所有的可用空間,為了保證還有性能和空間繼續擴展,要監視磁盤可用空間和磁盤性能。

當添加shard的時候可以設置shard最大大小。可以方式shard往里面移動數據。

9.2.4.2 ShardChunk遷移

Chunk遷移

Chunk遷移可以:1.手動遷移,2.自動遷移(通過均衡器)

所有的遷移都是一下過程:

1.均衡器發送moveChunk命令道源shard

2.Shard使用內部的moveChunk命令。源Shard負責處理寫入

3.目標Shard開始復制數據

4.接受到之后一個文檔之后,目標sahrd開始同步,保證被修改的文檔可以被同步過來

5.當都被同步完成,目標shard連接到config數據庫,修改集群元數據

6.當修改完元數據,並沒有游標,刪除chunk上的文檔。

若要進行另外一個chunk遷移,不用等待當前chunk刪除完成,直接進行。

Chunk遷移隊列

為了讓遷移速度更快,均衡器並不會等待當前遷移刪除chunk,就啟動下一個遷移。

Chunk遷移寫注意

刪除chunk的時候等待發布到secondary,會導致遷移速度下降,但是保證了大量chunk遷移的時候集群的可用性。具體看chunk遷移修改復制集行為

9.2.4.3 Shard集群下Chunk的分離

Chunk的大小超過了指定的chunk大小,mongos會把這個chunk分成2

Chunk大小

默認Chunk的大小為64MB,也可以通過配置增加減少chunk的大小。

1.小的chunk大小,會讓數據更加平均,但是遷移量變大,成本增加。

2.大的chunk會讓遷移變少,但是數據不均衡。

限制

Chunk大小的修改也會影響chunk分離。

1.自動分離只會發生在插入和修改

2.分離不能被undoen,如果增加了chunk的大小,chunk只有在insertupdate的時候增長才會變成新的大小。

9.2.4.4 Shard Key索引

所有的shard collection都要有個索引用於shard key,如果沒有文檔沒有索引,shardCollection命令會在shard key上創建索引。如果已經有文檔了,那么要在shardCollection之前創建好索引。

Shard key不能是multikey索引。

如果shard collectionzipcodeshard key可以使用如下方法來替換索引:

1.創建一個索引zipcode,username

2.刪除zipcode這個索引

刪除了最后一個可用索引之后,可以重新在shard key創建索引來恢復。

9.2.4.5Shard集群元數據

Config服務保存了集群的元數據,元數據反映了狀態和shard數據集和系統的組合。mongos實例緩存了這些數據並使用它來路由讀寫操作。config數據庫包含了以下collection

·changelog

·chunks

·collections

·databases

·lockpings

·locks

·mongos

·settings

·shards

·version

9.3 Shard集群教程

主要介紹如何管理shard集群

9.3.1 Shard集群部署教程

部署shard集群,考慮shard key,使用hash shard key分片collectionshard集群驗證,添加shard到集群,為生產環境部署3config server,把復制集轉化為shard集群,把shard轉化為復制集。

9.3.1.1部署shard集群

啟動Config服務

config服務是保存了集群元數據的mongod,啟動的時候標記configsvr,每個config保存了一份完整的集群元數據。

生產環境下最好在不同的服務器上部署3config服務。

1.config服務創建數據文件夾

mkdir /data/configdb

2.啟動mongod服務

mongod --configsvr --dbpath <path> --port <port>

默認端口是27019,當然可以通過--port來指定端口。

啟動mongos實例

mongos是很輕量的不要求數據文件夾。默認端口是27017。啟動mongos的時候需要指定config服務,可以在命令行也可以在配置文件下。最好給每個config服務一個DNS,這樣換服務器的時候就不會有下線時間。

mongos --configdb cfg0.example.net:27019,cfg1.example.net:27019,cfg2.example.net:27019

每個mongos啟動的時候必須要有相同的configdb配置字符串。

增加Shard到集群中

shard可以是復制集也可以是單個實例,對於生產環境應該要求都是復制集。

1.使用mongo連接到mongos

mongo --host mongos0.example.net --port 27017

2.使用sh.addShard添加shard到集群

添加一個復制集,添加一個成員就可以了,以前的版本要添加所有的成員。

sh.addShard("rs1/mongodb0.example.net:27017")

添加一個單實例shard

sh.addShard("mongodb0.example.net:27017")

啟動數據庫中的Shard

在真正shard collection之前要先啟用數據庫的shard

1.連接到mongos

mongo --host mongos0.example.net --port 27017

2.使用sh.enableShard()命令對數據庫啟用shard

sh.enableSharding("<database>")

也可以使用命令:db.runCommand({enableSharding:<database>})

啟動CollectionShard

1.確定shard key

2.如果collection已經有數據庫的要先在shard key上創建索引使用ensureIndex(),如果是空的,Mongodb會通過sh.shardCollection創建。

3.使用sh.shardCollection() shard一個collection

sh.shardCollection("<database>.<collection>",shard-key-pattern)

shard-key-pattern表示shard key

如:

sh.shardCollection("records.people",{"zipcode":1,"name":1})

sh.shardCollection("people.addresses",{"state":1,"_id":1})

sh.shardCollection("assets.chairs",{"type":1,"_id":1})

db.alerts.ensureIndex({_id:"hashed"})

sh.shardCollection("events.alerts",{"_id":"hashed"})

9.3.1.2考慮Shard Key

選擇Shard Key

以下是幫助你找到合適的shard key的策略:

1.在應用程序層先計算好理想的shard key,然后保存到文檔中

2.使用組合shard key使用,前綴來提高寫能力和讀隔離

3.在這些情況下,不好的shard key 並沒有很大的影響:有限的寫入,預期的數據大小,應用程序查詢方式。

4.使用hash shard key,選一個選擇度高的然后創建hahs索引。然后使用這個hash索引為shard key的值。

考慮Shard Key的選擇性shard key的選擇對性能,選擇度,集群的功能影響重大。

創建一個易切分(divisible)的shard key

一個易切分的shard keymongodb分發數據比較簡單,如果只有有限的幾個值會讓chunk無法分割。

創建一個高隨機的shard key

一個高隨機的shard key不會讓任何一個shard變成瓶頸,並且可以在集群中發布寫操作(不會只寫入到一個shard)。

對於一個shard創建一個shard key

一個shard一個shard key可以讓mongos直接從一個shard上返回結果,但是shard key必須最為主要的過濾條件。使用高隨機的shard key 很難再指定的shard 上操作。

使用組合shard key

當存在在collection中的字段都不是最優的key,那么選擇多個字段作為組合shard key會更加的理想。

基數(cardinality 選擇性類似)

基數決定了這個系統中可以分為幾個chunks

1.如果用state作為shard key,因為state少會造成集群不均衡有以下影響:

         a.不能分離chunks因為這個chunk都是同一個shard key,遷移這些chunk變得無比困難。很難讓集群均衡。

         b.如果固定了chunks的個數,那么就不能超過這個個數了。

2.zipcode字段作為shard key

         這個字段選擇度高但是也有可能照成un-splittable的情況,有些用戶很多,有些卻很少。

3.考慮手機號碼作為shard key

         手機號碼是高基數(和選擇度一樣)的,所有的用戶都有自己的手機號碼並且是唯一的。

高基數可以保證數據均衡,但是不能保證查詢隔離和合適的寫擴展。

9.3.1.3使用Hash Shard Key

Hash Shard Key是使用Hash索引的字段

Shard Collection

使用shard keyshard collection

sh.shardCollection( "records.active", { a:"hashed" } )

使用ahash值作為shard key

指定初始化Chunks

如果使用hash shard keyshard空的collectionmongodb會自動創建和遷移空的chunks。每個shard2chunks。可以使用shardCollectionnumInitialChunks來控制初始化collectionchunk個數。

Mongodb hash索引會截斷float小數點后面的值,再計算。

9.3.1.4 Shard集群的認證

使用—keyfile來控制集群內組件的互通,keyfile都一樣,內容可以隨意

過程

1.創建key file保存認證信息

2.通過以下方式啟用驗證:

         a.在配置文件中:keyFile = /srv/mongodb/keyfile

         b.在命令行上配置—keyfile

3.添加第一個管理員,創建一個管理員

9.3.1.5添加Shard到集群

shard增加到集群的時候要保證,集群有足夠的能力來遷移數據。

添加一個shard 到集群

1.使用mongo連接到mongos

mongo --host mongos0.example.net --port 27017

2.使用sh.addShard增加shard

添加一個復制集,添加一個成員就可以了,以前的版本要添加所有的成員。

sh.addShard("rs1/mongodb0.example.net:27017")

添加一個單實例shard

sh.addShard("mongodb0.example.net:27017")

9.3.1.6為生產環境部署3Config服務

這個過程是把只有單個config的測試環境轉變為3config服務的生產環境。

1.關閉所有mongodb進程

2.復制dbpath下的所有文件到其他config服務

rsync -az /data/configdb mongo-config1.example.net:/data/configdb

rsync -az /data/configdb mongo-config2.example.net:/data/configdb

3.啟動所有3config server

mongod --configsvr

4.重啟所有的mongodmongos

9.3.1.7把復制集轉化為shard集群

概述

這個過程是把3成員的復制集轉為2shard的集群,每個shard3成員的復制集。

1.創建選擇一個3成員的復制集,插入一些數據到collection

2.啟動config數據庫,並且創建一個單shard的集群

3.創建第二個復制集

4.把第二個復制集添加到這個集群上

5.在需要shardcollection進行shard

過程

使用測試數據部署復制集:使用下面的順序來部署復制集

1.為復制集創建文件夾。

mkdir -p /data/example/firstset1 /data/example/firstset2 /data/example/firstset3

2.啟動3mongod實例

mongod --dbpath /data/example/firstset1 --port 10001 --replSet firstset --oplogSize 700 --rest

mongod --dbpath /data/example/firstset2 --port 10002 --replSet firstset --oplogSize 700 --rest

mongod --dbpath /data/example/firstset3 --port 10003 --replSet firstset --oplogSize 700 --rest

3.使用mongo打開一個shell

4.通過以下命令來初始化復制集

db.runCommand({"replSetInitiate":

                    {"_id":"firstset", "members": [{"_id":1, "host":"localhost:10001"},

                                                      {"_id":2, "host":"localhost:10002"},

                                                      {"_id":3, "host":"localhost:10003"}

             ]}})

{

"info":"Config now saved locally.  Should come online in about a minute.",

"ok":1

}

5.使用一下代碼插入測試數據

use test

switched to db test

people = ["Marc", "Bill", "George", "Eliot", "Matt", "Trey", "Tracy", "Greg", "Steve", "Kristina", "Katie", "Jeff"];

for(var i=0; i<1000000; i++){

                             name = people[Math.floor(Math.random()*people.length)];

                             user_id = i;

boolean= [true, false][Math.floor(Math.random()*2)];

                             added_at =newDate();

                             number =Math.floor(Math.random()*10001);

                             db.test_collection.save({"name":name, "user_id":user_id, "boolean":boolean, "added_at":added_at, "number":number });

                            }

部署Shard基礎設施:這個過程創建了3config數據庫

1.config服務創建文件夾

mkdir -p /data/example/config1 /data/example/config2 /data/example/config3

2.啟動config數據庫

mongod --configsvr --dbpath /data/example/config1 --port 20001

mongod --configsvr --dbpath /data/example/config2 --port 20002

mongod --configsvr --dbpath /data/example/config3 --port 20003

3.啟動mongos實例

mongos --configdb localhost:20001,localhost:20002,localhost:20003 --port 27017 --chunkSize 1

--chunkSize表示chunk的大小這里是1MB

4.添加第一個shard

         a.連接到mongos

         mongo localhost:27017/admin

         b.增加使用addShard增加sahrd

         db.runCommand( { addShard :"firstset/localhost:10001,localhost:10002,localhost:10003" } )

         c.返回一下信息說明添加成功

         { "shardAdded":"firstset", "ok":1 }

部署第二個復制集:下面的過程部署第二個復制集

1.創建復制集文件夾

  • /data/example/secondset1
  • /data/example/secondset2
  • /data/example/secondset3

2.啟動3mongod實例

mongod --dbpath /data/example/secondset1 --port 10004 --replSet secondset --oplogSize 700 --rest

mongod --dbpath /data/example/secondset2 --port 10005 --replSet secondset --oplogSize 700 --rest

mongod --dbpath /data/example/secondset3 --port 10006 --replSet secondset --oplogSize 700 --rest

3.連接到mongos

mongo localhost:10004/admin

4.初始化第二個復制集

db.runCommand({"replSetInitiate":

                    {"_id":"secondset",

"members": [{"_id":1, "host":"localhost:10004"},

                                  {"_id":2, "host":"localhost:10005"},

                                  {"_id":3, "host":"localhost:10006"}

             ]}})

 

{

"info":"Config now saved locally.  Should come online in about a minute.",

"ok":1

}

5.把復制集增加到集群

use admin

db.runCommand( { addShard :"secondset/localhost:10004,localhost:10005,localhost:10006" } )

是不是只寫一個成員就可以了

6.驗證shard成員,使用listShards命令

db.runCommand({listShards:1})

{

"shards": [

              {

"_id":"firstset",

"host":"firstset/localhost:10001,localhost:10003,localhost:10002"

              },

              {

"_id":"secondset",

"host":"secondset/localhost:10004,localhost:10006,localhost:10005"

              }

      ],

"ok":1

}

啟動Shardmongodb必須要再數據庫和collection級別啟動shard

在數據庫級別啟動Shard:使用enableSharding命令啟動數據庫

db.runCommand( { enableSharding :"test" } )

{ "ok":1 }

在索引上創建Shard KeyMongodb使用shard key來發發布數據到shard,一旦決定之后你不能修改shard key。好的shard key

1.可以均衡的分發數據

2.經常被同時訪問的文檔會被放在連續的chunk

3.在活動的shard中有效的分發

Shard key一般的選擇是復合索引,hash或者主鍵。Shard key的選擇還是和數據,應用程序結構和使用方式有關。

Shard Collection

use admin

db.runCommand( { shardCollection :"test.test_collection", key : {"number":1} })

{ "collectionsharded":"test.test_collection", "ok":1 }

之后均衡器會均衡chunk,可以在test下的db.stats()或者db.printShardIngStatus()查看是否在同步。

9.3.1.8shard集群轉化為復制集

把一個有復制集的集群轉為復制集

這個例子是,集群只有一個shard復制集,用以下方法把shard轉為復制集

1.配置應用程序連接到primary成員

2.如果啟動的時候有shardsrv選項,那么刪除這個選項。

把集群轉為復制集

1.創建一個新的復制集,保證這個復制集的性能能夠達到要求。

2.停止所有的寫入。通過重新配置應用程序或者停止所有mongos

3.使用mongodumpmongorestore備份恢復數據到新的復制集

4.配置應用程序連接到新的復制集

9.3.2 Shard集群維護教程

查看集群配置,使用相同的名字遷移config服務,使用不同的名字遷移config服務,替換ocnfig服務,遷移shard到不同的硬件,備份元數據,配置均衡器,管理均衡器,刪除shard

9.3.2.1查看集群配置

查看shard可用的數據庫

通過在config數據庫對databases collection的查詢

use config

db.databases.find( { "partitioned":true } )

查看所有的shard

使用listShards命令查看

use admin

db.runCommand( { listShards :1 } )

查看集群的細節

使用db.printShardingStatus,sh.status查看集群的細節

Sh.status返回一下:

Sharding version顯示shard元數據版本

Shards顯示了shard的列表

Database顯示了集群中的所有數據庫

Chunks信息顯示了每個shard有幾個chunk

9.3.2.2使用相同的hostname遷移config

config遷移到同名的系統。如果要遷移所有的config那么每個都執行一下過程:

1.關閉這個config server,會影響config數據,只讀

2.修改dns指向新的系統

3.復制老的config的數據到新的系統上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.然后以config服務啟動mongod

mongod --configsvr

當第三個config啟動集群的元數據有可以被寫入(可以遷移chunksplit chunk

9.3.2.3在不同HostName之前遷移config

這個過程遷移config服務到一個新的不同名的服務器,這樣會修改config的主機名,還會導致下線時間和集群內的所有進程重啟。

如果要遷移所有config,依次按一下過程執行:

1.關閉均衡器

2.關閉config服務,會導致config數據只讀

3.復制老的config的數據到新的系統上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.然后以config服務啟動mongod

mongod --configsvr

5.關閉所有mongodb進程,包括:shardmongod或者復制集,提供config服務的mongodmongos實例。

6.重啟所有提供shard服務器的mongod

7.更新mongosconfigdb設置

8.重啟mongos

9.重啟均衡器

9.3.2.4替換一個Config服務

這個過程是替換不可用的config服務。這個過程假設替換過程中,hostname不就被修改。

1.關閉均衡器(是否可以不關閉,是為了讓元數據不可寫,但是如果config已經出現不可用,沒有必要。

2.提供一個新的系統和之前的設備有一樣的hostname

3.關閉其中一個config服務,復制數據到新的設備上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.啟動之前是好的config服務

5.啟動新的config服務

mongod --configsvr

6.啟動均衡器

9.3.2.5遷移集群到不同的硬件環境

這個過程是啟動shard集群到一個新的環境下。沒有宕機時間,遷移狀況下可讀寫。

如果集群下有單節點shard那么先把這個mongod轉變為復制集可以讓你的集群一直在可用狀態下。

關閉均衡器

關閉均衡器來停止chunk遷移,在整個過程中不要有元數據寫入,若均衡器已經啟動了遷移,那么先等待均衡器遷移完,在執行這個過程。sh.stopBalancer()來關閉均衡器。然后可以使用sh.getBalancerStatue()來查看均衡器狀態。

遷移config服務

mongosconfigdb配置的字符串,從最后一個開始遷移。不要重命名config服務。

1.關閉config服務,元數據變成只讀

2.修改DNS指向新的設備

3.復制數據到新的設備上

rsync -az /data/configdb/ mongodb.config2.example.net:/data/configdb

4.然后以config服務啟動mongod

mongod --configsvr

重啟mongos實例

如果configdb修改是遷移的一部分,那么就需要在修改configdb之前關閉mongos。避免出現configdb字符串不一樣的沖突。

如果configdb保持不變,只要順序的遷移就可以了:

1.關閉mongos實例,使用shutdown命令,如果configdb字符串要修改,要關閉所有mongos實例。

2.如果config服務hostname修改,更新所有mongosconfigdb字符串。

3.重啟mongos實例確保已經更新了configdb

遷移Shard

使用一下過程遷移shard

遷移一個復制集:為了遷移整個集群,就需要遷移shard,要遷移shard,就要遷移secondary

如果是2vote的集群那么要加一個仲裁,遷移結束后可以把仲裁刪掉。

遷移復制集的一個成員

1.關閉mongod,確保感覺關閉,可以使用shutdown命令

2.啟動數據文件夾到新的設備上

3.在新的設備上重啟mongod

4.連接到集群的當前primary

5.如果hostname被修改,使用rs.reconfig()重新配置。

cfg=rs.conf()

cfg.members[2].host="pocatello.example.net:27017"

rs.reconfig(cfg)

6.確認復制集配置,rs.config()

7.等待成員恢復,使用rs.status()查看狀態

遷移Shard復制集中的Primary:遷移過程中,當執行選舉的時候才會讓復制集不可用,不能執行讀寫。但是選舉的過程很快。

1.stepDown primarysecondary上來當primary

2.查看復制集進程,看看是否成功變成secondary,變成secondary之后在執行遷移secondary的步驟。

遷移單實例Shard:單實例shard遷移的時候,先轉化為復制集然后再遷移。

重新啟動均衡器

連接到mongos實例,然后執行sh.setBalancerState(true)

9.3.2.6備份集群元數據

1.關閉均衡器

2.關閉其中一個config

3.備份整個數據文件夾

4.重新啟動config

5.啟動均衡器

9.3.2.7配置均衡器進程行為

均衡器運行在其中一個mongos上,保證chunks在集群中的均衡分布。默認的均衡器的配置已經足夠使用了。管理員也有可以根據應用來重新配置均衡器。

配置均衡器調度窗口

均衡器調度窗口,是均衡器只能在這個窗口時間內調度。

具體看均衡器管理中的均衡器調度窗口刪除均衡器調度窗口

配置默認chunk大小

默認chunk的大小為64MB,當然可以修改chunk的大小,通過修改config數據庫中的settings collection。也可以在mongos啟動是,指定參數--chunkSize來指定chunk的大小。

修改指定Shard的最大存儲大小

最大存儲大小,指定后,如果mapped大小超過了最大存儲大小,均衡器就不會再移入數據這個mapped大小是值所有被映射的數據庫文件的大小。maxsize被保存在config數據庫中的shards collection下。

默認maxsize可以無限大,撐滿所有可用空間為止。這個maxsize可以在添加shard的時候指定也可以手動修改:

1.通過addShard指定,單位MB

db.runCommand( { addshard : "example.net:34008", maxSize : 125 } )

2.修改已存在shardmaxsize

use config

db.shards.update( { _id : "shard0000" }, { $set : { maxSize : 250 } } )

chunk遷移修改復制集行為

2.2.1之后_secondaryThrottle變成moveChunk命令的一個參數。_secondaryThrottle可以讓均衡器在遷移是等待secondary完成。

2.4之后,_secondaryThrottle默認啟動。

當啟動之后,secondary會要求寫注意為{w:2}來保證修改至少被寫入一個secondary

可以通過以下命令來設置_secondaryThrottle

useconfig

db.settings.update(

   {"_id":"balancer"},

   {$set:{"_secondaryThrottle":true}},

   {upsert:true}

)

9.3.2.8管理均衡器

檢查均衡器狀態

使用sh.getBalancerState()查看均衡器狀態

檢查均衡器鎖(查看均衡器是否活動)

為了查看均衡器進程是否活動可以使用以下過程:

1.連接到mongos

2.切換到config

3.查看config中的locks collection查看均衡器是否活動

db.locks.find({_id:"balancer"}).pretty()

輸出:

{   "_id":"balancer",

"process":"mongos0.example.net:1292810611:1804289383",

  "state":2,

     "ts":ObjectId("4d0f872630c42d1978be8a2e"),

   "when":"Mon Dec 20 2010 11:41:10 GMT-0500 (EST)",

    "who":"mongos0.example.net:1292810611:1804289383:Balancer:846930886",

    "why":"doing balance round"}

1.process可以看出均衡器進程運行在mongos0.example.net

2.state狀態為2 說明在活動中,早期的版本為1

均衡器調度窗口

當數據增長很緩慢,並且遷移會影響性能的時候,可以使用調度窗口來限制均衡器的調度。

1.連接到mongos

2.切換到config數據庫

3.使用一下命令來修改調度器窗口

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

如:

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

刪除均衡器調度窗口

使用一下命令來刪除調度窗口

useconfig

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

關閉均衡器

默認均衡器只有在需要均衡數據的時候運行。也可以使用一下過程關閉均衡器:

1.連接到mongos

2.使用命令sh.setBalancerState(false)來關閉均衡器

3.通過sh.getBalancerState()來獲取均衡器狀態

可以用以下代碼驗證關閉后不再有遷移:

useconfig

while(sh.isBalancerRunning()){

          print("waiting...");

          sleep(1000);

}

驅動下,關閉均衡器只能修改settings collection

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

啟動均衡器

1.使用mongo連接到mongos

2.使用以下任意一種語句來啟用:

sh.setBalancerState(true)

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

在備份的時候關閉均衡器

mongodb在遷移時備份會導致數據不一致,所以要在備份時關閉均衡器。可選方法:

1.設置均衡器調度窗口,在窗口外備份

2.手動關閉均衡器

如果關閉均衡器的時候有遷移在處理,那么會先等待遷移完成,然后清理掉之后要遷移的。

要在備份前確認是否有均衡器在運行。

!sh.getBalancerState()&&!sh.isBalancerRunning()

9.3.2.9刪除Shard集群中的Shard

為了刪除shard,必須確認shard中的數據已經被遷移出去了。不要使用一下過程來遷移整個shard集群到一個新的環境。

確保均衡器是啟動的

使用sh.getBalancerState()來查看均衡器是否啟動。

確定要刪除shardhostname

1.使用listShards查看shard

db.adminCommand( { listShards:1 } )

2.使用sh.status()或者db.printShardingStatus()查看shard

shard中刪除chunk

使用removeShard命令來抽取shard中的chunk到其他shard

useadmin

db.runCommand({removeShard:"mongodb0"})

輸出

{

    "msg":"draining started successfully",

    "state":"started",

    "shard":"mongodb0",

    "ok":1

}

檢查遷移狀態

查看遷移狀態可以使用一下命令

useadmin

db.runCommand({removeShard:"mongodb0"})

輸出

{

     "msg":"draining ongoing",

    "state":"ongoing",

    "remaining":{

        "chunks":42,

        "dbs":1

    },

    "ok":1

}

其中remaining文檔顯示了剩下要遷移的chunksdbs表示這個數據庫中primary的數據庫個數。

移動非shard數據

shard環境下,只有primary數據庫有非shardcollection

1.使用一下命令查看,刪除的shard是不是primary

·  sh.status()

·  db.printShardingStatus()

輸出中,databases字段列了所有數據庫和它的primary,以下結果說明products數據庫的primarymongodb0上:

{  "_id":"products",  "partitioned":true,  "primary":"mongodb0"}

2.使用movePrimary命令移動primary

db.runCommand({movePrimary:"products",to:"mongodb1"})

這個命令只有當全部處理完之后才會返回

完成遷移

為了清理所有的元數據和完成遷移,再次使用removeShard命令

useadmin

db.runCommand({removeShard:"mongodb0"})

當完成的時候會返回以下結果:

{

    "msg":"removeshard completed successfully",

    "state":"completed",

    "shard":"mongodb0",

    "ok":1

}

只有完成到這步的時候,你才能完全的關閉這個shard的進程。

9.3.3 Shard集群的數據管理

創建chunksplit chunk,遷移chunk,修改chunk大小,Tag意向Sharding,管理Shard Tag

,強制唯一鍵,Shard GridFS數據存儲。

9.3.3.1創建Chunks

很多情況下shard集群會自動創建和發布chunk,不需要用戶參與,但是有些場景下,Mongodb不能創建豬狗的chunk或者發布數據不夠快,如:

1.shard一個以前只存儲在primarycollection

2.想要提取大量數據到集群中,這種提取會導致不均衡,特別是單向增長或者單向遞減的數據,會插入到單個chunk中。

這些操作時資源密集型有以下幾個理由:

1.chunk遷移是把chunk里面的數據從這個shard復制到另外一個shard

2.mongodb一次只遷移一個chunk

3.mongodb只會在插入操作后才split

只能在空的collectionsplit,如果在已經有數據的collection會自動split,如果手動split,會導致無法估計chunk個數和大小,會影響數據均衡的行為。

例,可以使用一下代碼來創建chunk

for ( var x=97; x<97+26; x++ ){

  for( var y=97; y<97+26; y+=6 ) {

    var prefix = String.fromCharCode(x) + String.fromCharCode(y);

    db.runCommand( { split : "myapp.users" , middle : { email : prefix } } );

  }

}

9.3.3.2 Split Chunk

如果chunk大小草果chunk sizemongodb會自動的split這個chunk。但是還是會有手動split chunk出現:

1.有大量的數據但是chunk比較少

2.如果想要導入大量的數據,這些數據起初是在單個chunkshard 上的。

mongos認為遷移對未來插入性能有好處,均衡器可能會遷移splitchunk到一個新的shard。均衡器不會中斷手動的split,也不會中斷自動的split

使用sh.status確定當前chunks

使用split命令來split chunk,要不是middle,要不是find也可以使用sh.splitFind()sh.splitAt()

在有某個值的chunk進行平均的split

sh.splitFind( "records.people", { "zipcode":"63109" } )

對指定位置進行split,新的chunk的邊界從指定的值開始。

sh.splitAt( "records.people", { "zipcode":"63109" } )

9.3.3.3遷移Chunk

一般chunk遷移都是自動的,但是以下情況可以考慮自動遷移:

1.split空的collection,然后分發他們

2.如果在均衡窗口內無法遷移chunk

使用moveChunk命令來遷移chunk

db.adminCommand( { moveChunk : "myapp.users",

                   find : {username : "smith"},

                   to : "mongodb-shard3.example.net" } )

把包含shard key smithchunk啟動到mongodb-shard3

可以使用如下命令遷移:

var shServer = [ "sh0.example.net", "sh1.example.net", "sh2.example.net", "sh3.example.net", "sh4.example.net" ];

for ( var x=97; x<97+26; x++ ){

  for( var y=97; y<97+26; y+=6 ) {

    var prefix =String.fromCharCode(x) +String.fromCharCode(y);

    db.adminCommand({moveChunk :"myapp.users", find : {email : prefix}, to : shServer[(y-97)/6]})

  }

}

2.2版本后,會有個_secondaryThrottle參數當為true時,mongodb會保證對chunk的遷移分發到secondary

當出現以下錯誤時是有太多游標打開了這個chunk,要不等待游標關閉,要不干掉游標。

The collection's metadata lock is already taken.

9.3.3.4修改Chunk的大小

如果你注意到,自動遷移超過了硬件的處理能力,就可能想要減少chunk大小。修改chunk大小過程:

1.連接到mongos

2.切換到config數據庫

3.使用save命令來保存chunk大小

db.settings.save( { _id:"chunksize", value: <sizeInMB> } )

修改chunk有一下幾個限制:

1.自動split會在插入或者修改的時候發生

2.如果設置了低的chunk,那么需要時間來split所有的chunk

3.split是不能undone

4.如果增加了chunk的大小,那么只有通過insert,和updatechunk增長到新的大小。

9.3.3.5 Tag意向Sharding

Mongodb支持通過tag標記一組shard key來指明一個shard或者一組shard。可以通過tag做到以下事情:

1.把數據庫隔離到指定的shard

2.保證相關的數據所在的shard 的位置

行為和操作

tag標記了一組shard key。均衡器通過chunkshard key遷移到tag的高值比chunk低值大的shard下。

如果collection中的chunks不均衡,均衡器遷移,均衡器遷移tag區間內的chunk到,關聯到這個tagshard中。

配置tag,關聯到一個或者多個shard之后,集群可能會花一些時間均衡shard中的數據,取決於當前的數據分布。

跨多個tagchunk

一個chunk包含的shard key可能跨多個tag,為了解決這個問題,均衡器可能會把chunk遷移到比chunkshard key小的tag上。

如:有2tag

1.shard key 100-200tag NYC

2.shard key200-300tag SFO

當有一個chunk要遷移shard key150-220,那么會被遷移到NYC,因為150200比到300近。

9.3.3.6管理Shard Tag

標記Shard

使用sh.addShardTag()tag和指定的shard關聯,一個shard可以有多個shard,多個shard也可以有一個tag

sh.addShardTag("shard0000", "NYC")

sh.addShardTag("shard0001", "NYC")

sh.addShardTag("shard0002", "SFO")

sh.addShardTag("shard0002", "NRT")

使用sh.renoveShardTag來刪除關聯

sh.removeShardTag("shard0002", "NRT")

標記Shard Key

使用sh.addTagRange()shard key分配給tag

1.分配2個數組給NYC

2.分配一個數組給SFO

sh.addTagRange("records.users", { zipcode: "10001" }, { zipcode: "10281" }, "NYC")

sh.addTagRange("records.users", { zipcode: "11201" }, { zipcode: "11240" }, "NYC")

sh.addTagRange("records.users", { zipcode: "94102" }, { zipcode: "94135" }, "SFO")

刪除Tag上的Shard key

use config

db.tags.remove({ _id: { ns: "records.users", min: { zipcode: "10001" }}, tag: "NYC" })

查看存在的shard tag

通過sh.status查看被管理到shardtagshardtag被存在config數據庫shards collection下,通過查詢shards collection查看tag

use config

db.shards.find({ tags: "NYC" })

tagshard key組被保存在configtags collection下,sh.status()也顯示了tagshard key

use config

db.tags.find({ tags: "NYC" })

9.3.3.7 shard集群強制唯一鍵

唯一約束是在collection中每個文檔有一個唯一的值。對於shard集群來說,唯一約束不能約束整個shard collection,只能約束本地的collection

如果要保證整個collection的唯一性,有2個選擇:

1.使用shard key 可以的唯一性

2.shard collection創建非shardcollection來約束唯一性。

Shard key唯一性約束

過程:可以在shardCollection中指定unique保證唯一性

db.runCommand( { shardCollection : "test.users" , key : { email : 1 } , unique : true } );

限制

1.只能限制一個字段的唯一性

2.可以使用組合的shard key,只能對組合進行唯一約束

很多情況下,最好的shard key是組合的可以允許讀隔離和寫擴展。

其他字段的唯一約束

若不能創建到shard key,或者需要在多個字段強制唯一性,你就必須創建一個代理collection,這個collection包含了到原始文旦的引用和要唯一的字段。

過程:如果要在email字段保持唯一性

{

  "_id" : ObjectId("...")

  "email" ": "..."

}

_id反應了原始文檔,email是要唯一的字段

如果collectionshard

db.runCommand( { shardCollection : "records.proxy" ,

                 key : { email : 1 } ,

                 unique : true } );

如果不需要shard

db.proxy.ensureIndex( { "email" : 1 }, { unique : true } )

在插入數據時的操作:

db = db.getSiblingDB('records');

 

var primary_id = ObjectId();

 

db.proxy.insert({

   "_id" : primary_id

   "email" : "example@example.net"

})

 

// if: the above operation returns successfully,

// then continue:

 

db.information.insert({

   "_id" : primary_id

   "email": "example@example.net"

   // additional information...

})

考慮

1.你的應用程序必須要能夠抓取插入報錯

2.如果代理collectionshard,只能在要保持唯一性的字段作為shard key唯一

3.在多於1個字段唯一性,你必須為每個字段創建代理collection,如果要再一個collection上創建多個唯一性,那么就不能shard

9.3.3.8 Shard GridFS數據存儲

當要shard一個GridFS存儲,考慮一下幾點:(不知道為啥要對file collection chunk collection進行shard)

File collection
Chunks Collection

9.3.4 Shard集群Troubleshoot

9.3.4.1 Config數據庫錯誤字符串

Mongosconfigdb都要使用同一個字符串,不然會有一下錯誤:

could not initialize sharding on connection

mongos specified a different config database string

9.3.4.2 因為老的config數據導致游標錯誤

如果mongos沒有及時更新元數據的cache

could not initialize cursor across all shards because : stale config detected

9.3.4.3在移動config服務避免下線

使用DNS名稱來減少下線時間,名稱一改所有成員都要重啟。

9.4 Shard Reference

http://docs.mongodb.org/manual/reference/sharding/

也可以看

http://docs.mongodb.org/manual/reference/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM