天天看點

MongoDB之分片叢集(Sharding)MongoDB之分片叢集(Sharding)

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的分片叢集介紹完了。