1.分片
分片是什么?分片就是將數據存儲在多個機器上。當數據集超過單台服務器的容量,服務器的內存,磁盤IO都會有問題,即超過單台服務器的性能瓶頸。此時有兩種解決方案,垂直擴展和水平擴展(分片)。
垂直擴展就是增加CPU,增加容量,但高性能系統的CPU和容量不成比例,這樣擴展成本大,並且有上限。
水平擴展分片,將數據分發到多個服務器,每個服務器是一個單獨的數據庫,各個服務器加起來組成一個邏輯數據庫,把寫壓力和操作分流到不同服務器,提高容量和吞吐量。
MongoDB的文檔是無模式的,不固定結構,因此只能進行水平分片。當塊超過指定大小或者文檔數超過最大文檔數,MongoDB嘗試分割這個塊,若分割成功,把它標記為一個大塊避免重復分割。拆分塊的關鍵就是片鍵,下面介紹常見片鍵的種類。
2.片鍵種類
片鍵是文檔的一個屬性字段或者一個復合索引字段,一旦建立不能改變。片鍵是分片拆分數據的關鍵,片鍵的選擇直接影響集群的性能。
MongoDB首先根據片鍵划分塊chunks當塊超過指定大小(默認64M),然后把塊分到其他的分片上,片鍵類型主要有以下幾種:
注意:片鍵也是查詢時常用的一個索引。
(1) 遞增片鍵
這類片鍵比較常見,比如使用時間戳,日期,自增的主鍵,ObjectId,_id等,此類片鍵的寫入操作集中在一個分片服務器上,寫入不具有分散性,這會導致單台服務器壓力較大,但分割比較容易,這台服務器可能會成為性能瓶頸。
遞增片鍵的創建,對foo數據庫的bar集合使用timestamp時間戳分片
mongos> use foo mongos> db.bar.ensureIndex({"timestamp":1}) mongos> sh.enableSharding("foo") { "ok" : 1 } mongos> sh.shardCollection("foo.bar",{"timestamp":1}) { "collectionsharded" : "foo.bar", "ok" : 1 }
(2) 哈希片鍵
使用一個哈希索引字段作為片鍵,優點是使數據在各節點分布比較均勻,數據寫入可隨機分發到每個分片服務器上,把寫入的壓力分散到了各個服務器上。但是讀也是隨機的,可能會命中更多的分片,一般具有隨機性的片鍵(如密碼,哈希,MD5)查詢隔離性能比較差。
哈希片鍵的創建,對GridFS的chunks集合使用files_id哈希分片
mongos> db.bar.ensureIndex({"files_id":"hashed"}) mongos> sh.enableSharding("foo") { "ok" : 1 } mongos> sh.shardCollection("foo.fs.chunks",{"files_id":"hashed"}) { "collectionsharded" : " foo.fs.chunks ", "ok" : 1 }
(3) 組合片鍵
數據庫中沒有比較合適的片鍵供選擇,或者是打算使用的片鍵基數太小(即變化少如星期只有7天可變化),可以選另一個字段使用組合片鍵,甚至可以添加冗余字段來組合。一般是粗粒度+細粒度進行組合。
組合片鍵的創建,對GridFS的chunks集合使用files_id和n組合分片
mongos> sh.enableSharding("foo") { "ok" : 1 } mongos> sh.shardCollection("foo.fs.chunks",{"files_id":1, "n":1}) { "collectionsharded" : " foo.fs.chunks ", "ok" : 1 }
(4) 標簽分片
數據存儲在指定的分片服務器上,可以為分片添加tag標簽,然后指定相應的tag,比如讓10.*.*.*(T)出現在shard0000上,11.*.*.*(Q)出現在shard0001或shard0002上,就可以使用tag讓均衡器指定分發。
標簽分片的創建
mongos > sh.addShardTag("shard0000", "T") mongos > sh.addShardTag("shard0001", "Q") mongos > sh.addShardTag("shard0002", "Q") mongos> sh.addTagRange("foo.ips",{ "ip": "010.000.000.000 ", … , "ip": "011.000.000.000 "}}, "T") mongos> sh.addTagRange("foo.ips",{ "ip": "011.000.000.000 ", … , "ip": "012.000.000.000 "}}, "Q")
3.片鍵選擇策略
大致了解了片鍵的種類,那么怎么選擇片鍵呢?無非從兩個方面考慮,數據的查詢和寫入,最好的效果就是數據查詢時能命中更少的分片,數據寫入時能夠隨機的寫入每個分片,關鍵在於如何權衡性能和負載。
如何選擇片鍵主要從下面幾個問題考慮:
(1)首先確定一個經常性查詢的字段
(2)找到影響這些操作性能的關鍵點
(3)如果選的字段基數比較小,添加一個粒度細的字段
怎么選擇,如何權衡,跟具體的業務以及數據類型都有關系,具體問題具體分析。