部署模型
可複製集
可複製集是跨多個MongDB服務器(節點)分佈和維護數據的方法。mongoDB可以把數據從一個節點複製到其他節點並在修改時進行同步,集羣中的節點配置爲自動同步數據;舊方法叫做主從複製,mongoDB 3.0以後推薦使用可複製集;
爲什麼要用可複製集?它有什麼重要性?
避免數據丟失,保障數據安全,提高系統安全性;
(最少3節點,最大50節點)
自動化災備機制,主節點宕機後通過選舉產生新主機;提高系統健壯性;
(7個選舉節點上限)
讀寫分離,負載均衡,提高系統性能;
生產環境推薦的部署模式;
可複製集架構以及原理
oplog( 操作日誌) :保存操作記錄、時間戳
數據同步:從節點與主節點保持長輪詢;1.從節點查詢本機oplog最新時間戳;2.查詢主節點oplog於此時間戳的所有文檔;3.加載這些文檔,並根據log執行寫操作;
阻塞複製: 與writeconcern相關,不需要同步到從節點的策略(如: acknowledgedUnacknowledged 、w1),數據同步都是異步的,其他情況都是同步;
心跳機制:成員之間會每2s 進行一次心跳檢測(ping操作),發現故障後進行選舉和故障轉移;
選舉制度:主節點故障後,其餘節點根據優先級和bully算法選舉出新的主節點,在選出主節點之前,集羣服務是隻讀的
可複製集的搭建過程
1. 安裝好3個以上節點的mongoDB;
2. 配置mongodb.conf,增加跟複製相關的配置如下:
replication:
replSetName: configRS //集羣名稱
oplogSizeMB: 50 //oplog集合大小
3. 在primary節點上運行可複製集的初始化命令,初始化可複製集,命令如下:
//複製集初始化,在主節點上執行,ip禁止使用localhost
rs.initiate({
_id: "configRS",
version: 1,
members: [{ _id: 0, host : "192.168.1.142:27017" }]});
rs.add("192.168.1.142:27018");//有幾個節點就執行幾次方法
rs.add("192.168.1.142:27019");//有幾個節點就執行幾次方法
4. 在每個節點運行rs.status()或isMaster()命令查看複製集狀態;
5. 測試數據複製集效果;
6. 測試故障失效轉移效果;
Tips:
只能在主節點查詢數據,但如果
想在副節點查詢到數據需運行
rs.slaveOk(); //每個節點都運行一次 確保java代碼能操作mondodb
代碼連接複製集
MongoDB 複製集裏Primary 節點是不固定的, 不固定的, 不固定的!所以生產環境千萬不要直連Primary, 千萬不要直連Primary, 千萬不要直連Primary !重要的事情說3 遍!
java原生驅動開發
List<ServerAddress> asList = Arrays.asList(
new ServerAddress("192.168.1.142", 27018),
new ServerAddress("192.168.1.142", 27017),
new ServerAddress("192.168.1.142", 27019));
client = new MongoClient(asList);
Spring配置開發
<mongo:mongo-client replica-set="192.168.1.142:27017,192.168.1.142:27018,192.168.1.142:27017">
</mongo:mongo-client>
配置Tips:
1. 關注Write Concern參數的設置,默認值1可以滿足大多數場景的需求。W值大於1可以提高數據的可靠持久化,但會降低寫性能。
2. 在options裏添加readPreference=secondaryPreferred並打開rs.slaveOk()即可實現讀寫分離,讀請求優先到Secondary節點,從而實現讀寫分離的功能
分片集羣
分片是把大型數據集進行分區成更小的可管理的片,這些數據片分散到不同的mongoDB節點,這些節點組成了分片集羣。
爲什麼要用分片集羣?
數據海量增長,需要更大的讀寫吞吐量 → 存儲分佈式
單臺服務器內存、cpu等資源是有瓶頸的 → 負載分佈式
Tips: 分片集羣是個雙刃劍,在提高系統可擴展性和性能的同時,增大了系統的複雜性,所以在實施之前請確定是必須的。
什麼是分片?
數據庫?集合?文檔?mongoDB分片集羣推薦的模式是:分片集合,它是一種基於分片鍵的邏輯對文檔進行分組,分片鍵的選擇對分片非常重要,分片鍵一旦確定,mongoDB對數據的分片對應用是透明的;
Tips:隨着數據量的的增大,分片會分割和遷移,以滿足數據的均勻分佈。
請求分流:通過路由節點將請求分發到對應的分片和塊中;
數據分流:內部提供平衡器保證數據的均勻分佈,數據平均分佈式請求平均分佈的前提;
塊的拆分:3.4版本塊的最大容量爲64M或者10w的數據,當到達這個閾值,觸發塊的拆分,一分爲二;
塊的遷移:爲保證數據在分片節點服務器分片節點服務器均勻分佈,塊會在節點之間遷移。一般相差8個分塊的時候觸發;
分片集羣架構圖與組件
分片:在集羣中唯一存儲數據的位置,可以是單個mongo服務器,也可以是可複製集,每個分區上存儲部分數據;生產環境推薦使用可複製集
mongos路由:由於分片之存儲部分數據,需要mongos路由將讀寫操作路由到對應的分區上;mongos提供了單點連接集羣的方式,輕量級、非持久化所以通常mongos和應用部署在同一臺服務器上;
配置服務器:存儲集羣的元數據,元數據包括:數據庫、集合、分片的範圍位置以及跨片數據分割和遷移的日誌信息;mongos啓動時會從配置服務器讀取元數據信息在內存中;配置服務器最低3臺
分片搭建過程
配置步驟:
1. 分片服務器配置:給27020、27021以及複製集(27017、27018、27019)的配置文件增加:
sharding:
clusterRole: shardsvr
2. config服務器配置:給複製集(27022、27023、27024)的配置文件增加:
sharding:
clusterRole: configsvr
3. 啓動mongos路由如下:
./mongos --configdb shardingConfig/192.168.1.142:27022,192.168.1.142:27023, 192.168.1.142:27024
--port 27025 -- logpath=/usr/local/apache/mongoDB/sharding/rounter/
mongodb-rounter1/logs/mongodb.log
……
課堂筆記
一.複製集初始化
rs.initiate({
_id: "configRS",
version: 1,
members: [{ _id: 0, host : "192.168.1.142:27017" }]});
rs.add("192.168.1.142:27018");//有幾個節點就執行幾次方法
rs.add("192.168.1.142:27019");//有幾個節點就執行幾次方法
二.分片config複製集初始化
rs.initiate({
_id: "shardingConfig",
version: 1,
members: [{ _id: 0, host : "192.168.1.142:27023" }]});
rs.add("192.168.1.142:27022");//有幾個節點就執行幾次方法
rs.add("192.168.1.142:27024");//有幾個節點就執行幾次方法
三.分片配置步驟
1.分片服務器配置:給27020、27021以及複製集(27017、27018、27019)的配置文件增加:
sharding:
clusterRole: shardsvr
2.config服務器配置:給複製集(27022、27023、27024)的配置文件增加:
sharding:
clusterRole: configsvr
3.啓動mongos路由如下:
./mongos --configdb shardingConfig/192.168.1.142:27022,192.168.1.142:27023,192.168.1.142:27024 --port 27025 --logpath=/usr/local/apache/mongoDB/sharding/rounter/mongodb-rounter1/logs/mongodb.log
4.配置sharding
1)連接mongos: mongo --port 27025
2)增加分區:
use admin;
sh.addShard("192.168.1.142:27020");
sh.addShard("192.168.1.142:27021");
//configRS這個是複製集的名稱
sh.addShard("configRS/192.168.1.142:27017,192.168.1.142:27018,192.168.1.142:27019");
3)通過sh.status()或圖形化工具查看分片結果
4)對lison數據庫啓用分片:sh.enableSharding("lison")
5)對ordersTest集合進行分片,分片鍵爲{"useCode":1,"_id":1}
sh.shardCollection("lison.orders",{"useCode":1,"_id":1});
分片注意點與建議
分片注意點:
熱點 :某些分片鍵會導致所有的讀或者寫請求都操作在單個數據塊或者分片上,導致單個分片服務器嚴重不堪重負。自增長的分片鍵容易導致寫熱點問題;
不可分割數據塊:過於粗粒度的分片鍵可能導致許多文檔使用相同的分片鍵,這意味着這些文檔不能被分割爲多個數據塊,限制了mongoDB均勻分佈數據的能力;
查詢障礙:分片鍵與查詢沒有關聯,造成糟糕的查詢性能。
建議:
不要使用自增長的字段作爲分片鍵,避免熱點問題;
不能使用粗粒度的分片鍵,避免數據塊無法分割;
不能使用完全隨機的分片鍵值,造成查詢性能低下;
使用與常用查詢相關的字段作爲分片鍵,而且包含唯一字段(如業務主鍵,id等);
索引對於分區同樣重要,每個分片集合上要有同樣的索引,分片鍵默認成爲索引;分片集合只允許在id和分片鍵上創建唯一索引;
最佳實踐
1. 儘量選取穩定新版本64位的mongodb;
2. 數據模式設計;提倡單文檔設計,將關聯關係作爲內嵌文檔或者內嵌數組;當關聯數據量較大時,考慮通過表關聯實現,dbref或者自定義實現關聯;
3. 避免使用skip跳過大量數據;(1)通過查詢條件儘量縮小數據範圍;(2)利用上一次的結果作爲條件來查詢下一頁的結果;
4. 避免單獨使用不適用索引的查詢符($ne、$nin、$where等)
5. 根據業務場景,選擇合適的寫入策略,在數據安全和性能之間找到平衡點;
6. 索引建議很重要;
7. 生產環境中建議打開profile,便於優化系統性能;
8. 生產環境中建議打開auth模式,保障系統安全;
9. 不要將mongoDB和其他服務部署在同一臺機器上(mongodb佔用的最大內存是可以配置的);
10. 單機一定要開啓journal日誌,數據量不太大的業務場景中,推薦多機器使用副本集,並開啓讀寫分離;
11. 分片鍵的注意事項
mongodb.conf
storage:
dbPath: "/usr/local/apache/mongoDB/sharding/replication/primary/data"
journal:
enabled: true
directoryPerDB: true
engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 1
journalCompressor: snappy
directoryForIndexes: false
collectionConfig:
blockCompressor: snappy
indexConfig:
prefixCompression: true
systemLog:
destination: file
path: "/usr/local/apache/mongoDB/sharding/replication/primary/logs/mongodb.logs"
net:
port: 27017
http:
RESTInterfaceEnabled: true
processManagement:
fork: false
replication:
replSetName: configRS
oplogSizeMB: 50
sharding:
clusterRole: shardsvr
start-sharding-mongodb.sh 啓動腳本(測試的mongodb都在同一臺機器上的)
nohup ./replication/primary/bin/mongod -f ./replication/primary/bin/mongodb.conf >./logs/primary.log 2>&1 &
nohup ./replication/secondary1/bin/mongod -f ./replication/secondary1/bin/mongodb.conf >./logs/secondary1.log 2>&1 &
nohup ./replication/secondary2/bin/mongod -f ./replication/secondary2/bin/mongodb.conf >./logs/secondary2.log 2>&1 &
nohup ./mongodb-node1/bin/mongod -f ./mongodb-node1/bin/mongodb.conf >./logs/mongodb-node1.log 2>&1 &
nohup ./mongodb-node2/bin/mongod -f ./mongodb-node2/bin/mongodb.conf >./logs/mongodb-node2.log 2>&1 &
nohup ./config/mongodb-config1/bin/mongod -f ./config/mongodb-config1/bin/mongodb.conf >./logs/config1.log 2>&1 &
nohup ./config/mongodb-config2/bin/mongod -f ./config/mongodb-config2/bin/mongodb.conf >./logs/config2.log 2>&1 &
nohup ./config/mongodb-config3/bin/mongod -f ./config/mongodb-config3/bin/mongodb.conf >./logs/config3.log 2>&1 &
nohup ./rounter/mongodb-rounter1/bin/mongos --configdb shardingConfig/192.168.1.142:27022,192.168.1.142:27023,192.168.1.142:27024 --port 27025 --logpath=/usr/local/apache/mongoDB/sharding/rounter/mongodb-rounter1/logs/mongodb.log >./logs/rounter.log 2>&1 &