MongoDB 分片鍵的選擇與案例

来源:https://www.cnblogs.com/chenmh/archive/2018/05/31/8954584.html
-Advertisement-
Play Games

MongoDB版本:3.6 一、分片鍵類別 1.升序片鍵 升序片鍵例如:日期時間欄位、自增欄位。 2.隨機分發片鍵 隨機分發片鍵例如:用戶名、郵件名、UUID、MD5值或者是其它的一些沒有規律的值的列。 3.基於位置的片鍵 基於位置的片鍵例如:IP、經緯度、居住地址等。 二、分片策略 1.範圍分片 ...


MongoDB版本:3.6 

一、分片鍵類別

1.升序片鍵

升序片鍵例如:日期時間欄位、自增欄位。

2.隨機分發片鍵

隨機分發片鍵例如:用戶名、郵件名、UUID、MD5值或者是其它的一些沒有規律的值的列。

3.基於位置的片鍵

基於位置的片鍵例如:IP、經緯度、居住地址等。

二、分片策略

1.範圍分片

創建分片時,只在主分片上創建了一個塊{ "username" : { "$minKey" : 1 } } -->> { "username" : { "$maxKey" : 1 } } on : rs-a Timestamp(1, 0)。

 

至少得3個不同的值才會進行塊切分,相同的值只會在一個分片塊中。比如對一個name欄位進行範圍分區,如果一直往name欄位插入"a",那麼它會一直存儲主分片的{ "username" : { "$minKey" : 1 } } -->> { "username" : { "$maxKey" : 1 } }中,直到name出現三個不同的值,比如“a”,“b”,“c”這個時候就會進行分片。當然這隻是測試,現實中不會對這種粗粒度的欄位單獨做分片。

2.hashed分片

創建分片時,預設在每個分片上創建了兩個數據塊。但是當前每個塊上面是沒有數據的。

 

3.組合分片

組合分片是比較好的一種分片的選擇,好的組合分片可以同時解決熱點和隨機讀IO問題。例如:

sh.shardCollection("test.bbbb",{"username":1,"_id":1});

4.標簽分片

比如對於一些日誌非查詢文檔,可以通過標簽將其只插入到某個分片中。例如

sh.addTagRange("test.log",{ "_id" : { "$minKey" : 1 }  }, { "_id" : { "$maxKey" : 1 } },"tag_rs-a");

可以在config庫中的tag文檔中查看設置的標簽信息。

use config

db.tags.find();

三、標簽

可以通過標簽將特定範圍的數據在指定的分片中。

 

將{ "_id" : 18000 } -->> { "_id" : 26000 }範圍的數據保存到rs-a的分片上,這部分數據跨越了兩個數據塊。

1.為分片指定tag

sh.addShardTag("rs-a","tag_rs-a");

sh.addShardTag("rs-b","tag_rs-b");

sh.addShardTag("rs-c","tag_rs-c");

2.創建規則

sh.addTagRange("test.person",{ "_id" : 18000 }, { "_id" : 26000 },"tag_rs-a");

數據{ "_id" : 18000 } -->> { "_id" : 26000 }已經被移動到了rs-a分片上。

四、分片案例

分片策略沒有絕對的好壞,針對不同的業務場景選擇不同的分片策略。

1.分片情景

1.所有的分片讀寫都均勻。

2.數據訪問均勻,而不是隨機性的訪問;由於新數據都是先在記憶體中創建,儘量避免需要從磁碟訪問新數據。

3.儘量避免由於數據塊的數據移動導致數據從磁碟載入到記憶體中從而導致熱數據被清理出記憶體。

4.組合欄位分片可能會是理想的分片方案。

 

分片鍵公式:{coarseLocality:1,search:1}

coarseLocality:應該是一個大粒度的局部欄位。比如MONTH月份升序欄位。

search:是一個經常用來查找的欄位。

2.分片案例

案例1.使用日期欄位、自增欄位、時間戳分片的問題

有一個網站瀏覽記錄表,表中有一個createtime欄位用來記錄每天記錄的插入時間。

對於這類文檔不太適合使用createtime欄位作為分片欄位,因為讀寫可能都會集中在最新的分片上。使用自增欄位也存在同樣的問題

案例2.大粒度欄位分片問題

有一個五大洲的用戶文檔表,表中有一個continent欄位存儲用戶所在洲。

如果使用continent作為分片欄位會存在以下幾個問題:

1.分片的粒度太大了,會導致最後每一個分片的數據都非常的大而且沒有再分的可能。而且也有可能會導致磁碟空間不夠的情況。

2.可能會導致某個分片在某個時間點的訪問量遠遠大於其他分片。

案例3:使用月份和用戶名進行組合分片

有一個用戶操作記錄集合,業務需要查詢用戶最近一個月操作記錄。集合有month,userName鍵

使用{month:1,userName:1}分片情景如下:

month保證熱數據優於記憶體。

userName:保證數據的隨機性,避免集中過熱問題。

存在的問題:對於新文檔由於很多月份還不存在,會導致新數據都是往最後一個分片上面插入數據,存在熱讀寫問題,最後通過均衡器對數據塊進行移動。

數據測試

sh.shardCollection("test.news",{"month":1,"username":1 });

----插入1月數據10萬記錄

for(var i=0;i<100000;i++){db.news.insert({"_id":i,"month":"1","username":Math.random(),"createdate":new Date()})}

 

----插入2月數據10萬記錄

for(var i=100000;i<200000;i++){ db.news.insert({"_id":i,"month":"2","username":Math.random(),"createdate":new Date()})}

新數據往一直往最末尾的分片(rs-a)上插,因為這個時候"month":2在最大的分片上。{ "month" : "1", "username" : 0.9258836896982892 } -->> { "month" : { "$maxKey" : 1 }, "username" : { "$maxKey" : 1 } } on : rs-a Timestamp(3, 1)

 

數據插入完之後均衡器將rs-c上的一個塊分給了rs-a

----插入全部月份數據。

for(var a=1;a<13;a++)
{
for(var i=0;i<20000;i++){ db.news.insert({"month":a,"username":Math.random(),"createdate":new Date()})}
}

 

保證每個月的數據都均勻的分佈到不同的分片上,並且隨著時間的推移舊的數據可能就不會被使用也不會被移動。

註意:這個案例比較特殊,因為對於日誌集合比較舊的數據基本上是不會被查詢的,所以藉助了month鍵作為了分片鍵保證了熱數據優先存儲於記憶體,對於整張表都是熱數據比如登入用戶集合就不適合這種分片方式,hashed會更適合。

案例4:使用隊列

隊列不僅在容災中非常的有用,而且在常規的突發流量下也非常的有用。隊列可以吸收短時間內爆發的大量請求。也可以把隊列反過來用,即緩存MongoDB返回的結果。

比如:RabbitMQ

案例5:使用用戶名和創建時間進行組合分片

用戶名:保證數據的隨機性,避免熱點問題

創建時間:保證單個數據塊過大問題

五、設計集合註意事項

1.集合的鍵數量應該是固定的,包括嵌套文檔的數量都應該提前規劃好。

2.儘量都是做原子更新,而不是某個鍵的值受其它鍵值更新的影響。比如num1,num2,total如果num鍵的值是經常會被更新的那麼這種設計就不好,因為total也要對應跟著變,而mongodb本身計算能力就很弱。

 

 

 

 

 

 

備註:

    作者:pursuer.chen

    博客:http://www.cnblogs.com/chenmh

本站點所有隨筆都是原創,歡迎大家轉載;但轉載時必須註明文章來源,且在文章開頭明顯處給明鏈接,否則保留追究責任的權利。

《歡迎交流討論》

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.1 學習之初 1.2 約定 1.3 認識Linux 1.4 安裝虛擬機 1.5 安裝centos7 學習子初: 學習課程的目的什麼 (提升自己拿高薪) 學習完課程做什麼職位(系統運維) 學習完課程在哪個城市發展(鄭州) 1給自己設定目標: 何時學完:(5月28日到10月1日) 何時跳槽 第一份薪 ...
  • 1.輸出變數 : 若想輸出$符號,需要加入轉義符號 2.命令替換 將命令的輸出賦值給變數的方法 這個方法命令可以生成以日期命名的獨一無二的文件 生成了一個新的文件 使用命令替換的方法會創建一個子shell ...
  • 準備工作 linux軟體:Zookeeper-3.4.12.tar.gz 四台centos系統虛擬機,主機名為:s101~s104 一、本地模式搭建(s101上安裝) 1、解壓軟體壓縮包:解壓到根目錄的soft目錄下(註:soft是自己創建的文件夾,用於存放各類軟體) tar -xzvf zooke ...
  • Linux的文件許可權如: 777;666等,其實只要在相應的文件上加上UID的許可權,就可以用到加許可權人的身份去運行這個文件。所以我們只需要將bash複製出來到另一個地方,然後用root加上UID許可權,只要用戶運行此Shell就可以用用root的身份來執行任何文件了 一個文件都有一個所有者, 表示該文 ...
  • redhat支持多種安裝方式:光碟安裝,硬碟安裝和網路安裝等,可以根據個人的實際情況來選擇。我在這裡選擇的是光碟安裝的方式安裝RHEL6.9.(以下簡稱6.9) 1.首先準備好6.9的光碟鏡像,在安裝好的VMware里點擊創建新的虛擬機進入虛擬機創建嚮導 我在這裡選擇的是自定義。單擊下一步 這裡保持 ...
  • 自從建立了這個賬號後寫了一篇,好幾年沒來了,今天來看看,順便分享一下. 昨天晚上想玩玩zookeeper集群,在vb里複製了一臺主機,可怎麼也無法獲取IP,經研究,終於還是解決了. 1.複製主機時勾選 重新初始化所有網上的mac地址,並選擇完全複製. 2.啟動複製的主機 3. 編輯/etc/udev ...
  • VDP是一個基於磁碟的備份和恢復解決方案,可靠且易於部署。VDP這一經過更新的備份設備完全取代了VMware原有的備份架構。而且VDP與VMware vCenter Server 完全集成,可以對備份作業執行有效的集中式管理。 一、實驗拓撲圖 二、實驗目標 通過部署VDP,實現虛擬機的備份和還原。 ...
  • eFUSE是i.MXRT里一塊特殊的存儲區域,用於存放全部晶元配置信息,其中有一部分配置信息和Boot相關。這塊特殊存儲區域並不在ARM的4G system address空間里,需要用特殊的方式去訪問(讀/寫),如何訪問eFUSE是本篇文章的重點。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...