不要總是依賴機器 MongoDB擴展彰顯分片功夫

2020-12-16 CSDN技術社區

Johannes Brandstettercs目前是omSysto GmbH開發運營總監,曾擔任1&1 IT經理;致力於MongoDB、Hadoop、AWS上的項目研究。

縱觀最領先的應用程式建模和基礎設施最佳實現的設計,很容易的發現一個問題:如果需要性能的快速增長並適應從0到千萬請求的自由縮放,只有一條路可走 —— 橫向擴展(Scale Out)!

擴展通常是描述給系統添加更多資源的方法。需要從兩個方面區別:

縱向擴展(Scale vertically/up)

縱向擴展意味著給系統中單個節點增加資源,代表性的添加有單計算機的CPU或者內存提升。

橫向擴展(Scale horizontally/out)

橫向擴展意味著增加系統中節點的數目,比如說給一個分布式軟體應用程式中添加計算機。舉個簡單的例子,將Web伺服器系統中的伺服器從1個提升到3個。

使用MongoDB,你可以根據你的需求從兩個方面去擴展:專注讀操作或是寫操作的提升。

10gen告訴了我們一些擴展選項:

「自帶橫向擴展能力,MongoDB允許用戶快速的建立和提高他們的應用程式。通過自動分片,你可以輕鬆的將數據分配到不同的節點上。副本集提供高可靠性,跨數據中心實現節點故障自動轉移和恢復。」

聽起來不錯,事實上呢?現在開始著手把2400萬條數據導入由6個節點組成的MongoDB集群,這裡使用的是自動分片:

從上圖看結果並不是很好,呈現出很不均勻的寫入性能。假專注於單個節點的性能,情況比上面看起來更加的糟糕:

分別點擊查看大圖

這裡不僅要看到所有節點上不均勻的寫入速度,還要看到節點間每秒寫入操作的巨大差別。有一瞬間Node2達到 4000 insert/s的,而那個時刻node5隻有 740 insert/s !

為什麼會這樣?我們使用mongoimport監視了整個導入過程發現:開始的一段時間內一切運行的很好,我們的集群也提供了一個很好的吞吐量;但是隨著時間的推移,速度在逐漸的減緩。而通過mongostat,我們不難發現:有時候幾秒內許多節點並沒有分配到任何數據。

想了解原因,我們必須要看一下MongoDB的分片機制。這裡不得不看一下3個基本組件:

1. MongoDB Sharding Router(mongos)

所有通往集群的連接都由mongos選擇,分片對應用層來說是完全透明的 —— 通過Transparent Query Routing進行路由。

2. Mongo Config Server

決定元數據中某個部分該分配到哪個對應的節點上。

3. Mongo Shard Node

用來支撐數據的普通mongod進程。

那麼要把數據儲存到這樣的集群中,你必須去做元數據查詢來核對當前的數據該寫到哪個節點上。然而即使每次寫入前去決定目標節點會產生一定的開銷,這裡的性能損失也不該來的如此之大。

但是現實就是這麼殘酷!這裡要提起的就是Mongo Config Server,也就是必須要告訴MongoDB哪個範圍的數據需要被用來分片。這就是傳說中的「shard key」!同樣如果你在shard key上做了個錯誤的決定,將會引起一系列的麻煩。當然為了簡潔明了,這裡選擇一個我們認為很適合我們數據類型的shard key。

那麼MongoDB現在做的就是在內部把數據放入所謂的「chunk」 —— 很像固定大小的data bucket。這樣一來每個chunk中都包含了一定範圍的數據並且只是一定容量的數據(默認64MB)。當我們把數據導入資料庫,這些chunk將會被注入數據,一旦數據裝滿就會被MongoDB分割。這樣一來必定會發生下面兩種情況:

  • 新的元數據必須被寫入配置好的伺服器
  • Balancer必須考慮某個chunk是否要轉到另一個節點上

現在我們就有必要關注一下第二點了!因為我們並沒有告訴MongoDB任何shard key相關或者是怎麼分布的,MongoDB在分片前則必須進行最好的預估然後嘗試將數據平均的分配到分片中。它通過在任何給定時間內保持所有節點上chunk數量相同這一策略來保障數據的平均分配。在MongoDB 2.2中,新遷移閾值被引進並成功的將平衡集群帶來的影響降到最低。然而Mongo同樣不知道shard key的範圍和分布,那麼就很可能發生熱點區域 —— 很大一部分的數據被寫入了同一個分片,因此也只在同一個節點上。

既然我們知道了問題的所在,我們是否能夠做點什麼?

數據預分割

想做數據預分割必須對你將要導入的數據有充分的認識,所以取代讓MongoDB完成chunk的選擇你需要親自動手。取決於你shard key的選擇,你既可以使用一個腳本生成相關的命令(一個不錯的用例)也可以使用MongoDB文檔提供的方法。無論如何你都將完成對MongoDB chunk分配位置的告知:

  1. db.runCommand( { split : "mydb.mycollection" , middle : { shardkey : value } } ); 

當然你還可以強制MongoDB給chunk分配相應的節點。同樣這取決於你的用例及應用程式對數據的讀取方式。這裡需要注意的是保留數據的局部性。

增加chunk大小

文檔中有具體的chunk大小說明:

1. 小的chunk以頻繁遷移為代價獲取數據更均勻的分布,這樣會給Query Routing Layer增加更多的開銷。

2. 大的chunk會顯著的減少遷移,不管是從網絡設計還是從內部Query Routing Layer開銷上都會帶來收益。當然這些收益是以潛在的數據分布不均為代價。

而為了能讓MongoDB能運行的足夠快,這裡把chunk的大小提升為1GB。當然這是建立在對自己數據的了解上,所以務必讓chunk的大小來的更有價值。

關閉Balancer

既然我們已經給chunk指定了具體節點,並且不希望在這過程中有新chunk的建立;我們可以使用以下的命令來關閉Balancer:

1.

  1. use config 

2.

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

選擇正確的shard key

Shard key是節點分布的核心。詳情點擊這裡獲得shard key相關的建議。在MongoDB 2.4中還支持MongoDB自主選擇哈希shard key的選項。

通過這些努力,導入情況如下:

上圖為集群中一個節點上的速率。當然還是有一些縫隙,因為數據不是絕對均與的進入。但總的來這是一個很大的提升,整個集群上的導入速度達到每秒4608次插入;現在導入速度只受到節點間網絡接口的限制。

總結

天下沒有免費的午餐!想獲得卓越的性能,就必須親力親為。

原文連結:Scaling MongoDB – Know your Sharding Kung Fu (編譯/仲浩 王旭東/審校)

歡迎關注@CSDN雲計算微博,了解更多雲信息。

本文為CSDN編譯整理,未經允許不得轉載。如需轉載請聯繫market@csdn.net

相關焦點

  • MongoDB 不得不知的 12 個知識點
    全部搭建完之後,把新的從節點升級為主節點,再把老機器剔除出集群。不過如果數據量太大,而且平時數據更改很頻繁的話,初始化同步的過程可能Oplog不夠用。方案1先升級到3.4版本,這個版本在初始化同步的時候會抓取oplog方案2停機一臺從節點,物理複製到區域網中心機器,當從節點啟動這臺從節點配置一個大oplog,然後遷移目標端的從節點從這臺oplog從節點同步8、MongoDB的水平擴展是什麼原理?
  • MongoDB 如何上手和避坑?
    全部搭建完之後,把新的從節點升級為主節點,再把老機器剔除出集群。不過如果數據量太大,而且平時數據更改很頻繁的話,初始化同步的過程可能Oplog不夠用。方案1先升級到3.4版本,這個版本在初始化同步的時候會抓取oplog方案2停機一臺從節點,物理複製到區域網中心機器,當從節點啟動這臺從節點配置一個大oplog,然後遷移目標端的從節點從這臺oplog從節點同步8、MongoDB的水平擴展是什麼原理?
  • MongoDB 常見問題:MongoDB診斷
    如果一臺機器包含多個MongoDB實例,則您應減小設置以容納其他[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 實例。
  • MongoDB安裝筆記
    準備工作3.1 本地化如果是新環境,我們需要設置時區以保證時間顯示正確timedatectl set-timezone Asia/Shanghai3.2 安裝wget如果環境裡沒有wget,通過yum安裝一下3.3 安裝依賴包yum -y install libaio
  • Oppo百萬級高並發mongodb集群性能數十倍提升優化實踐
    該集群採用mongodb天然的分片模式架構,數據均衡的分布於各個分片中,添加片鍵啟用分片功能後實現完美的負載均衡。集群每個節點流量監控如下圖所示:此外,查看該機器的內存,可以看到內存總大小為190G,其中已經使用110G左右,幾乎是mongod的存儲引起佔用,這樣會造成內核態的page cache減少,大量寫入的時候內核cache不足就會引起磁碟缺頁中斷。
  • 阿里P8精心整理MongoDB+RabbitMQ+Memcached面試題,100%拿offer
    三、mongodbmongodb是一個基於分布式文件存儲的資料庫,由C++語言編寫。它旨在為WEB應用提供可擴展的高性能數據存儲解決方案,最大的特點是支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係資料庫單表查詢的絕大部分功能,而且還支持對數據建立索引。
  • pyspark操作MongoDB
    有幾點需要注意的:不要安裝最新的pyspark版本,請安裝`pip3 install pyspark==2.3.2`
  • mall整合Mongodb實現文檔操作
    Mongodb的安裝和使用1.下載Mongodb安裝包,下載地址:https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.2.21-signed.msi2.選擇安裝路徑進行安裝
  • Reactive-MongoDB異步Java Driver解讀
    二、理解 Reactive (響應式)響應式(Reactive)是一種異步的、面向數據流的開發方式,最早是來自於.NET 平臺上的 Reactive Extensions 庫,隨後被擴展為各種程式語言的實現。在著名的 Reactive Manifesto(響應式宣言) 中,對 Reactive 定義了四個特徵:
  • MongoDB-CRUD&運維工具介紹以及授權認證
    2.MongoDB 不支持多文檔事務(mongodb4.0 開始支持 ACID)。但是 MongoDB 確實在一個文檔上提供了原子操作。儘管集合中的文檔通常都是相同的,但是 MongoDB 中的集合不需要指定 schema。3.MongoDB 不支持 SQL 但是支持自己的豐富的查詢語言。4.在 MongoDB 中,存儲在集合中的每個文檔都需要一個唯一的 _id 欄位,作為主鍵。
  • 一文讀懂MongoDB,從理論到實踐
    文檔是一個鍵值對組成的數據結構,類似JSON,欄位的值可以是數組或者字典(可以理解為嵌套的文檔),例如MongoDB主打的特性包括高性能支持嵌套的文檔,從而減少了資料庫的I/O支持在嵌套的文檔或數組中創建索引豐富的查詢語言高可用Primary故障後自動切換到Secondary提供數據冗餘水平擴展
  • MongoDB 2.0.6 發布,分布式文檔資料庫
    文件存儲格式為BSON(一種JSON的擴展)可通過網絡訪問所謂「面向集合」(Collenction-Orented),意思是數據被分組存儲在數據集中,被稱為一個集合(Collenction)。每個 集合在資料庫中都有一個唯一的標識名,並且可以包含無限數目的文檔。
  • MongoDB核心貢獻者:不是MongoDB不行,而是你不懂!
    在同一個Replica Set中使用兩臺機器是很有誘惑的,它比3臺機器來的便宜並且也是RDBMS的標準行事風格。但是到了MongoDB這裡,同一個Replica Set中的成員數量只能是奇數個。假如你使用了偶數個成員,那麼當主節點發生故障時那麼其它的節點都會變成只讀。發生這種情況是因為剩下待選節點的數目不滿足票選主節點的規定。
  • 不容忽視:MongoDB的JavaScript性能
    【IT168 技術】mongodb使用javascript做shell, mongodb的db.eval可以提供給數據驅動與這種javascript shell類似的js接口。
  • 當MongoDB遇見Spark
    userid進行分組開發Maven dependency配置這裡用的是mongo-spark-connector_2.11 的2.0.0版本和spark的spark-core_2.11的2.0.2版本:    <dependency>        <groupId>org.mongodb.spark
  • MongoDB應用案例:使用MongoDB存儲商品分類信息
    ., aspect_ratio: "1.66:1" }, }所有商品都擁有一些共同的基本信息,特定的商品可以根據需要擴展獨有的內容,非常方便; 基於上述模型,MongoDB 也能很好的服務各類查詢。*hacker.*', '$options':'i'}}).sort({'details.issue_date', -1})可建立如下索引來加速查詢db.products.createIndex({ type: 1, details.issue_date: -1, title: 1 })擴展當單個節點無法滿足海量商品信息存儲的需求時,就需要使用
  • mongodb的文檔查詢命令find
    具體表現為:db.col.find().pretty()find和sql的類比1.查詢所有的結果sql:select * from t_usermongodb:db.user.find()2.查詢指定的列sql:select name,age from t_usermongodb:db.user.find({},{'name':1,'age':1})
  • 好程式設計師前端:MongoDB資料庫全套教程(精華版 含源碼)
    旨在為WEB應用提供可擴展的高性能數據存儲解決方案。MongoDB是一個介於關係資料庫和非關係資料庫之間的產品,是非關係資料庫當中功能最豐富,最像關係資料庫的。它支持的數據結構非常鬆散,是類似json的bson格式,因此可以存儲比較複雜的數據類型。
  • 淺談GPU虛擬化技術(四)- GPU分片虛擬化
    讓各位久等了,阿里小二這就開始上新菜:「GPU分片虛擬化」。  對於「分片」的理解,相信大家已經不陌生了。  GPU分片虛擬化框架  GPU分片虛擬化的方案被NVIDIA與Intel兩家GPU廠家所採用。NVIDIA GRID vGPU系列與Intel的GVT-g(XenGT or KVMGT)。
  • MongoDB學習筆記整理,請趕緊收藏起來
    mongodb是最近幾年最火的nosql資料庫,在很多大型企業應用廣泛,今天就一起學習它的用法。花了一周時間,整理下面的學習記錄,希望對大家有所幫助。mongodb1. mongodb的安裝,windows 10可以安裝,一般作為服務都是安裝在Linux伺服器上。