1. 程式人生 > >MongoDB復制集

MongoDB復制集

mongo 副本集 db

MongoDB目前的高可用架構主要有主從、復制集、以及分片,單純的主從技術幾乎被淘汰,整個穩定性以及可靠性方面復制集要比主從好,所以現在更多的會去使用復制集。在接下來的實踐過程中,我們將通過多實例的方法實現復制集。以及會解析搭建過程中遇到的困難問題。

一、基礎環境與規劃

操作系統:CentOS 6.7

MongoDB版本:3.4.5

實例部署情況:

主機IP數據目錄日誌文件端口
127.0.0.1/data/mongoDB/data/m17/data/mongoDB/logs/mongo17.txt28017
127.0.0.1/data/mongoDB/data/m18/data/mongoDB/logs/mongo18.txt28018
127.0.0.1/data/mongoDB/data/m19data/mongoDB/logs/mongo19.txt28019

由於在同一臺主機上面部署,所以就不需要考慮防火墻的配置與管理。大多數生產環境都有專業的硬件防火墻(思科、華為)等廠商的硬件防火墻設備,部分的公有雲也是有一些防火墻的產品,所以Iptables在生產環境中應該能起到錦上添花的作用,在整個過程中不考慮這一塊。

二、副本集原理與優化

2.1 副本集原理

技術分享

復制集(Replica Set),就是有自動故障恢復功能的主從集群。主從結構和復制集最明顯的區別是副本集沒有固定的主節點,當節點故障時,能選舉新的主節點,大大的提升了整個系統中數據存儲的穩定性;整個集群選舉出一個主節點,當主節點不能正常工作時,會選舉出另一個節點為主節點,

技術分享

復制集總會有一個活躍節點(Primary)和一個或者多個備份節點(Secondary),副本集中還可以有一個角色是仲裁者(Arbiter),它並不保存數據

。仲裁節點使用最小的資源並且不要求硬件設備,不能將Arbiter部署在同一個數據集節點中,可以部署在其他應用服務器或者監視服務器中,也可部署在單獨的虛擬機中。為了確保復制集中有奇數的投票成員(包括primary),需要添加仲裁節點做為投票,否則primary不能運行時不會自動切換primary。

在比較早的版本例如MongoDB2.6中,復制集中參與選舉的數據節點(包括primary)只能有7個 可以通過更改數據節點屬性的方法將復制集的數據節點增加到12個,但是其余的5個為非投票成員(Non-Voting Members)非投票成員是副本集中數據的備份副本,不參與投票,但可以被投票或成為主節點。當我們的復制集超過11個時,可以使用傳統的主從方法 數量不限制。


技術分享

技術分享

2.2 復制集的特點

復制集的特點

  • 數據一致性 使得多個進程/服務器在某個方面保持相同 異步同步(受磁盤、網絡、數據大小影響)

  • 主是唯一 只有1臺主能進行讀寫,其余的只能讀,同時主不是固定的 ,不像MySQL具有雙主架構,

  • 大多數原則 集群存活節點小於或等於二分之一時集群不可寫 只可讀

  • Secondary節點不支持寫入 MySQL從庫的readonly對具有super權限的賬戶無效

  • 相比傳統的主從結構 復制集可以自動容災

  • 不支持類似MYSQL只從中只同步部分庫的功能

  • 副本集之間的復制是通過oplog日誌現實的.備份節點通過查詢這個集合就可以知道需要進行復制的操作

  • oplog是節點中local庫中的一個固定的集合,在默認情況下oplog初始化大小為空閑磁盤的5%.oplog是capped collection,所以當oplog的空間被占滿時,會覆蓋最初寫入的日誌.

  • 通過改變oplog文檔的大小直接改變local所占磁盤空間的大小.可以在配置文件中設置oplogSize參數來指定oplog文檔的大小,例如oplogSize=1024單位默認為M 每個local文檔在磁盤空間的空間都為2G,設置不足2G的,初始化依然為2G大小,例如上面oplogSize=1024,但創建的local.01大小依然為2G.

  • 如果備份節點不幸掛掉,由於復制過程中是先寫數據,再寫oplog,這樣重新啟動時,可能會重復復制操作.但mongodb在設計過程中已經考慮過這個問題.當 oplog中同一個操作執行多次的時候,只執行一次.

  • 如果備節點的同步速度遠遠跟不上主節點的oplog寫入的數據,並且主節點的oplog被覆蓋.這樣,可能就無法同步那些被覆蓋的數據(出現這種情況,暫時還無法解決,只能通過備份主節點的數據,然後再重新同步).

  • 每個成員通過心跳去查看其他節點的狀態,每隔2秒鐘就有一次心跳檢測.

  • 當主節點宕機之後,各個節點通過選舉的方式來選擇下一個主節點

2.3 復制集的實現步驟

  1. 規劃端口、數據目錄、日誌目錄等可以將其定制成配置文件;

  2. 為了安全需要準備其驗證 (auth 驗證和keyFile驗證)

    auth驗證與keyFile驗證的區別:auth更多的是實現單機版或者單實例的驗證,這是MongoDB常見的安全加固方式之一,開啟驗證,對不同的庫和用戶做授權管理,而keyFile主要是用來集群之間不同示例之間的驗證,主要有以下特點

    keyFile特點:

基於base 64編碼集 僅能識別[a-z A-Z + /]等內容,(傳說中的 沒具體的測試

長度最好小於 1000byte

權限問題 允許的最大的權限是600 所以在安裝、配置、啟動等環節需要註意所有者和所屬組。

報錯解決:
mongod   -f  conf/29017.cnf  #啟動
about to fork child process, waiting until server is ready for connections.
forked process: 2681
ERROR: child process failed, exited with error number 1
查看日誌:
2017-06-01T00:10:39.307+0800 I CONTROL  [main] ***** SERVER RESTARTED *****
2017-06-01T00:10:39.490+0800 I ACCESS   [main] permissions on /datamongo/key/.keyFile are too open

發現權限太大,導致不能正常啟動,將keyFile的權限更改為600解決。

keyFile文件中時忽略空格、制表符、換行符的 以下內容可以等同

This name  docker     thisnamedocker

生成keyFile的方法推薦

openssl rand -base 64 N(字節數)

[[email protected] log]# openssl   rand  -base64   7
8ZNRiPFguw==
[[email protected] log]# openssl   rand  -base64   10
IAcXv1pLK67/qw==
[[email protected] log]# openssl   rand  -base64   12
LhhGR4GPk0dlTsLz
[[email protected] log]# openssl   rand  -base64    512
VgC2wexhxefk3F1P1fnSNJcsp/wwnG3bugoccgLLupvLSSZGRa73PMl4ju+35uWf
45WAMiTZ2emIp2Wg6qdQLD3n2OdhZ6zF49VtpOal8Pok6hfVvq+Kr6FuEwI6Vrcu
fa/XnnUCr69WIjILRkqIgfJZE3N+J3QExZBWFX28zoBlEoyjusEIQfP3Fod+XiIF
EWENFlvAKNUFLts13ad9g3PornXvFsyqf1AH8rf1y+I9VbiHDHYNMpNBXtfk+Sh+
E8mG4IH2/FfSvLsn4fdYSZ3ZnD2Tfogk9Jhk6zdqO+drm0Yf6WL4cxMAHhKWdbps
FAyjmis3sltWloshwqt4q+xtAo4JSYnT4Bo9MF8tyIb4ZZ2S6xIEjUV+FBELYGJO
AVz6F39bHU0qeuWNL8wMHb8YCXaNzrY/a9OFP3ZaaeGz6fUH6ZZJe3T5OE2IB+eF
3vQZrSF/0bBG3hM5E6ziTIp9+HF4c1+Ltq5bMdLaKioEvc3kAFq0q34JlFxjC4/m
aXasERqcvznLWb+3zXYbJiPpqxlOevEToXOGgmdkzAUrz5+g8IihPeOizO5iugt4
wwgki2ktnmU1l+wPqHPDUdW2/Hpvgdd5aHweDyu7Mc1OFAcvg53abxca2qi5g3Iu
1lVI12FDvSjRFO7bmM34rKxIgFuaiH4kQUmP+unLLSo=
[[email protected] log]# openssl   rand  -base64    512 >.keyFile
[[email protected] log]#

根據上面內容識別方法生成的文件中的“=”號是不能被識別的,要對其特殊處理,

3、啟動副本集

在啟動時,我們可以給mongd帶好多的參數,但是這樣比較麻煩,每次啟動都要制定很多的參數,建議我們寫配置文件;

#MOngoDB config 
port=27017                         #啟動監聽端口
dbpath=/data/mongoDB/data/m17     #數據存儲目錄
logpath=/data/mongoDB/logs/mongo17.txt   #日誌文件目錄
logappend=true                #日誌以追加的方式寫入
pidfilepath=/datamongo/data/m17/27017.pid  
fork=true                       #以後臺運行開啟
oplogSize=1024                #初始化oplog的大小為1024M 
replSet=BOOL                    #副本集名稱為BOOL  很重要的參數 必須統一
keyFile=/datamongo/key/.keyFile    #keyFile驗證文件的位置
setParameter=enableLocalhostAuthBypass=1  #避免在沒有創建用戶之前的 開啟驗證的權限問題

setParameter=enableLocalhostAuthBypass=1 該參數設置的特點

  • MongoDB實例中,沒有任何用戶時,才能生效

  • 僅允許本機(localhost)登錄,不能使用IP登錄(包括127.0.0.1)

  • 在實例創建用創建的第一個用戶後失效

  • 實例創建的第一個用戶 必須屬於admin庫 並且該用戶必須具有創建其他用戶的權限

4、初始化副本集

隨意進入其中的一個服務,進入admin庫對其初始化,

use  admin
var   conf=({_id:"BOOL",
members:[
{"_id":0,host:"127.0.0.1:27017",priority:1},
{"_id":0,host:"127.0.0.1:27018",priority:2},
{"_id":0,host:"127.0.0.1:27019",priority:3}
]
})
rs.initiate(conf)
執行OK

註意:

priority是個可選的參數,該參數可以決定該副本集中的節點成為primary節點的優先級,數字越大,優先級越高,在我們不同的主機之間存在性能差異時,我們可以合理的使用該參數,當不想讓某一個節點永遠不能成為primary節點時,就可以將priority參數設置成0



附件:

初始化腳本

#/bin/bash
################################describtion########################
#date 2017-07-08
#author  peng
#mail:[email protected]

HOST_IP=127.0.0.1
DATA_DIR=/data/mongoDB/data/
LOGS_DIR=/data/mongoDB/logs/
MONGOD_PATH= /home/mongodb/mongodb/mongodb-3.4.5/bin/
NA=DB2




mkdir  -p  ${DATA_DIR}m17     ${DATA_DIR}m18   ${DATA_DIR}m19  ${LOGS_DIR}


${MONGOD_PATH}mongod   --dbpath ${DATA_DIR}m17 --logpath  ${LOGS_DIR}logs1   --port  28017 --smallfiles  --replSet ${NA} --fork
${MONGOD_PATH}mongod   --dbpath ${DATA_DIR}m18 --logpath  ${LOGS_DIR}logs2   --port  28018 --smallfiles  --replSet ${NA} --fork
${MONGOD_PATH}mongod   --dbpath ${DATA_DIR}m19 --logpath  ${LOGS_DIR}logs3   --port  28019 --smallfiles  --replSet ${NA} --fork


${MONGOD_PATH}mongo --port 28017  <<EOF
use admin
var db2config={
_id:"DB2",
members:[
{_id:0,host:"${HOST_IP}:28017"},
{_id:1,host:"${HOST_IP}:28018"},
{_id:2,host:"${HOST_IP}:28019"}
]

}
rs.initiate(db2config);

註意事項:

在我們復制集設置了keyFile驗證後,我們初始化之後,在priamary節點想查看一下都有那些庫,發現權限不夠,這時我們就考慮創建用戶

 mongo   127.0.0.1:29017/admin
MongoDB shell version v3.4.5
connecting to: mongodb://127.0.0.1:29017/admin
MongoDB server version: 3.4.5
BOOL:PRIMARY> show  dbs
2017-06-01T01:27:04.487+0800 E QUERY    [thread1] Error: listDatabases failed:{
        "ok" : 0,
        "errmsg" : "not authorized on admin to execute command { listDatabases: 1.0 }",
        "code" : 13,
        "codeName" : "Unauthorized"
} :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/mongo.js:62:1
[email protected]/mongo/shell/utils.js:769:19
[email protected]/mongo/shell/utils.js:659:15
@(shellhelp2):1:1


這時我們可以創建一個用戶,多次測試 復制集在未創建用戶時,將setParameter=enableLocalhostAuthBypass=1
參數註釋後重啟,直接可以到admin庫創建用戶
db.createUser(
...  {user:"root",
...  pwd:"123123",
... roles:[
... {role:"root",db:"admin"}
...  ]
...   }
... )
Successfully added user: {
        "user" : "root",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ]
}


參考文檔

http://blog.csdn.net/leftfist/article/details/39583585

http://blog.csdn.net/kk185800961/article/details/45791903

本文出自 “堅持夢想” 博客,轉載請與作者聯系!

MongoDB復制集