mongodb集群故障轉移實踐


簡介

NOSQL有這些優勢:

  1. 大數據量,可以通過廉價服務器存儲大量的數據,輕松擺脫傳統mysql單表存儲量級限制。
  2. 高擴展性,Nosql去掉了關系數據庫的關系型特性,很容易橫向擴展,擺脫了以往老是縱向擴展的詬病。
  3. 高性能,Nosql通過簡單的key-value方式獲取數據,非常快速。還有NoSQL的Cache是記錄級的,是一種細粒度的Cache,所以NoSQL在這個層面上來說就要性能高很多。
  4. 靈活的數據模型,NoSQL無需事先為要存儲的數據建立字段,隨時可以存儲自定義的數據格式。而在關系數據庫里,增刪字段是一件非常麻煩的事情。如果是非常大數據量的表,增加字段簡直就是一個噩夢。
  5. 高可用,NoSQL在不太影響性能的情況,就可以方便的實現高可用的架構。比如mongodb通過mongos、mongo分片就可以快速配置出高可用配置。
  6. 支持查詢、聚合、完全索引,包含內部對象
  7. 支持復制和故障轉移、自動恢復
  8. 易擴展

在nosql數據庫里,大部分的查詢都是鍵值對(key、value)的方式。MongoDB是一個介於關系數據庫和非關系數據庫之間的產品,是非關系數據庫當中最像關系數據庫的。支持類似於面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。所以這個非常方便,我們可以用sql操作MongoDB,從關系型數據庫遷移過來,開發人員學習成本會大大減少。如果再對底層的sql API做一層封裝,開發基本可以感覺不到mongodb和關系型數據庫的區別。

  MongoDB是一個基於分布式文件存儲的數據庫。由C++語言編寫;旨在為WEB應用提供可擴展的高性能數據存儲解決方案。

安裝mongodb

安裝環境

操作系統:Centos7.2

mongodb版本: v3.6.1

下載安裝

wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.6.1.tgz
tar zxvf mongodb-linux-x86_64-amazon-3.6.1.tgz 
mv  /root/mongodb-linux-x86_64-amazon-3.6.1 /usr/local/mongodb/

創建數據/日志目錄

mkdir -p /data/mongodb/{data, logs}

mkdir /data/mongodb/data/mongod
touch /data/mongodb/logs/mongo.logs

創建配置文件

mkdir /usr/local/mongodb/config
cd  /usr/local/mongodb/config && touch mongo.conf

配置文件

1. 普通配置文件示例

dbpath=/data/mongodb/data/mongod
logpath=/data/mongodb/logs/mongo.log
logappend=true
replSet=mongo-rs
bind_ip=0.0.0.0
port=27017
fork=true
journal=true

mongodb3.x版本后就是要yaml語法格式的配置文件,下面是yaml配置文件格式如下:
官方yaml配置文件選項參考:https://docs.mongodb.org/manual/reference/configuration-options/#configuration-file
注意:只能使用空格,不支持tab鍵

2.yaml格式配置文件示例

storage:
    dbPath: /data/mongodb/data/mongod
    journal:
        enabled: true
systemLog:
    destination: file
    path: /data/mongodb/logs/mongo.log
    logAppend: true
    logRotate: rename
net:
    bindIp: 0.0.0.0
    port: 27017
processManagement:
    pidFilePath: /var/run/pid/mongodb.pid
    fork: true
replication:
    oplogSizeMB: 20480
    replSetName: mongo-rs

配置文件參數說明

1.基本參數

--quiet     # 安靜輸出
--port arg  # 指定服務端口號,默認端口27017
--bind_ip arg   # 綁定服務IP,若綁定127.0.0.1,則只能本機訪問,不指定默認本地所有IP
--logpath arg   # 指定MongoDB日志文件,注意是指定文件不是目錄
--logappend     # 使用追加的方式寫日志
--pidfilepath arg   # PID File 的完整路徑,如果沒有設置,則沒有PID文件
--keyFile arg   # 集群的私鑰的完整路徑,只對於Replica Set 架構有效
--unixSocketPrefix arg  # UNIX域套接字替代目錄,(默認為 /tmp)
--fork  # 以守護進程的方式運行MongoDB,創建服務器進程
--auth  # 啟用驗證
--cpu   # 定期顯示CPU的CPU利用率和iowait
--dbpath arg    # 指定數據庫路徑
--diaglog arg   # diaglog選項 0=off 1=W 2=R 3=both 7=W+some reads
--directoryperdb    # 設置每個數據庫將被保存在一個單獨的目錄
--journal   # 啟用日志選項,MongoDB的數據操作將會寫入到journal文件夾的文件里
--journalOptions arg    # 啟用日志診斷選項
--ipv6  # 啟用IPv6選項
--jsonp     # 允許JSONP形式通過HTTP訪問(有安全影響)
--maxConns arg  # 最大同時連接數 默認2000
--noauth    # 不啟用驗證
--nohttpinterface   # 關閉http接口,默認關閉27018端口訪問
--noprealloc    # 禁用數據文件預分配(往往影響性能)
--noscripting   # 禁用腳本引擎
--notablescan   # 不允許表掃描
--nounixsocket  # 禁用Unix套接字監聽
--nssize arg (=16)  # 設置信數據庫.ns文件大小(MB)
--objcheck  # 在收到客戶數據,檢查的有效性,
--profile arg   # 檔案參數 0=off 1=slow, 2=all
--quota     # 限制每個數據庫的文件數,設置默認為8
--quotaFiles arg    # number of files allower per db, requires --quota
--rest  # 開啟簡單的rest API
--repair    # 修復所有數據庫run repair on all dbs
--repairpath arg    # 修復庫生成的文件的目錄,默認為目錄名稱dbpath
--slowms arg (=100)     # value of slow for profile and console log
--smallfiles    # 使用較小的默認文件
--syncdelay arg (=60)   # 數據寫入磁盤的時間秒數(0=never,不推薦)
--sysinfo   # 打印一些診斷系統信息
--upgrade   # 如果需要升級數據庫

2.Replicaton 參數

--fastsync  # 從一個dbpath里啟用從庫復制服務,該dbpath的數據庫是主庫的快照,可用於快速啟用同步
--autoresync    # 如果從庫與主庫同步數據差得多,自動重新同步,
--oplogSize arg     # 設置oplog的大小(MB)

3.主/從參數

--master    # 主庫模式
--slave     # 從庫模式
--source arg    # 從庫 端口號
--only arg  # 指定單一的數據庫復制
--slavedelay arg    # 設置從庫同步主庫的延遲時間

4.Replica set(副本集)選項

--replSet arg   # 設置副本集名稱 

Sharding(分片)選項
--configsvr     # 聲明這是一個集群的config服務,默認端口27019,默認目錄/data/configdb
--shardsvr  # 聲明這是一個集群的分片,默認端口27018
--noMoveParanoia    # 關閉偏執為moveChunk數據保存

啟動

mongod --quiet -f /usr/local/mongodb/config/mongo.conf

配置文件里設置里fork:true,所以會在后台啟動,值得注意的是,用到了”–fork”參數就必須啟用”–logpath”參數,如不指定配置文件啟動,如下:

mongod --dbpath=/data/mongodb/data/mongod --fork --logpath=/data/mongodb/logs/mongo.logs

集群搭建

官方不建議再使用主從集群模式,推薦的集群方式是Replica Set(副本集),主從模式其實就是一個單副本的應用,沒有很好的擴展性和容錯性。而副本集具有多個副本保證了容錯性,就算一個副本掛掉了還有很多副本存在,並且解決了上面第一個問題“主節點掛掉了,整個集群內會自動切換”。

副本集的設計結構

由圖可以看到客戶端連接到整個副本集,不關心具體哪一台機器是否掛掉。主服務器負責整個副本集的讀寫,副本集定期同步數據備份,一但主節點掛掉,副本節點就會選舉一個新的主服務器,這一切對於應用服務器不需要關心。

注意

仲裁節點是一種特殊的節點,它本身並不存儲數據,主要的作用是決定哪一個備節點在主節點掛掉之后提升為主節點,所以客戶端不需要連接此節點。這里雖然只有一個備節點,但是仍然需要一個仲裁節點來提升備節點級別。

必須要有仲裁節點,沒仲裁節點的話,主節點掛了備節點還是備節點。

配置步驟

准備三台機器

172.29.142.17172.29.142.18172.28.226.199 仲裁

按照第二步安裝依次在三台機器上安裝並啟動

/usr/local/mongodb/bin/mongod --quiet -f /usr/local/mongodb/config/mongo.conf

初始化集群配置

三台服務啟動並不能表示他們在一個集群,因此需要將集群初始化。連接任意一個節點(不要是仲裁點),執行如下:

rs.initiate({
 _id:"mongo-rs", #集群名稱 
 members:[ {_id:0,host:'172.29.142.18:27017',priority:2}, #主
 {_id:1,host:'172.29.142.17:27017',priority:1}, #備
 {_id:2,host:'172.28.226.199:27017',arbiterOnly:true}]  #仲裁節點
}) 

成功上面會返回OK,然后查看集群狀態,下面是在備節點上執行的

rs.status()

返回集群的名稱和members信息,如:

{
    "set" : "mongo-rs",
    "date" : ISODate("2018-06-26T14:56:08.032Z"),
    "myState" : 2,
    "term" : NumberLong(2),
    "syncingTo" : "172.29.142.18:27017",
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1530024958, 1),
            "t" : NumberLong(2)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1530024958, 1),
            "t" : NumberLong(2)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1530024958, 1),
            "t" : NumberLong(2)
        }
    },
    "members" : [ 
        {
            "_id" : 0,
            "name" : "172.29.142.18:27017",
            "health" : 1.0,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 382251,
            "optime" : {
                "ts" : Timestamp(1530024958, 1),
                "t" : NumberLong(2)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1530024958, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2018-06-26T14:55:58.000Z"),
            "optimeDurableDate" : ISODate("2018-06-26T14:55:58.000Z"),
            "lastHeartbeat" : ISODate("2018-06-26T14:56:07.329Z"),
            "lastHeartbeatRecv" : ISODate("2018-06-26T14:56:06.453Z"),
            "pingMs" : NumberLong(0),
            "electionTime" : Timestamp(1529642739, 1),
            "electionDate" : ISODate("2018-06-22T04:45:39.000Z"),
            "configVersion" : 1
        }, 
        {
            "_id" : 1,
            "name" : "172.29.142.17:27017",
            "health" : 1.0,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 382552,
            "optime" : {
                "ts" : Timestamp(1530024958, 1),
                "t" : NumberLong(2)
            },
            "optimeDate" : ISODate("2018-06-26T14:55:58.000Z"),
            "syncingTo" : "172.29.142.18:27017",
            "configVersion" : 1,
            "self" : true
        }, 
        {
            "_id" : 2,
            "name" : "172.28.226.199:27017",
            "health" : 1.0,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 168617,
            "lastHeartbeat" : ISODate("2018-06-26T14:56:06.895Z"),
            "lastHeartbeatRecv" : ISODate("2018-06-26T14:56:04.092Z"),
            "pingMs" : NumberLong(35),
            "configVersion" : 1
        }
    ],
    "ok" : 1.0
}
View Code

返回參數說明

“health” : 1, #代表機器正常 
“stteStr” : “PRIMARY”, #代表是主節點,可讀寫,其中有以下幾下狀態:

STARTUP:剛加入到復制集中,配置還未加載
STARTUP2:配置已加載完,初始化狀態
RECOVERING:正在恢復,不適用讀
ARBITER: 仲裁者
DOWN:節點不可到達
UNKNOWN:未獲取其他節點狀態而不知是什么狀態,一般發生在只有兩個成員的架構,腦裂
REMOVED:移除復制集
ROLLBACK:數據回滾,在回滾結束時,轉移到RECOVERING或SECONDARY狀態
FATAL:出錯。查看日志grep “replSet FATAL”找出錯原因,重新做同步
PRIMARY:主節點
SECONDARY:備份節點

測試副本集數據復制

注意:mongodb默認是從主節點讀寫數據的,副本節點上不允許讀,需要設置副本節點可以讀:

repset:SECONDARY> db.getMongo().setSlaveOk();

這個很好測試,直接在主節點插入一條數據,在備節點查詢即可

或者可以使用客戶端以集群模式連接mongo集群:

點Test 測試連接:

三個節點的數據是同步的。

測試副本集故障轉移功能

1.查看集群當前狀態,如上返回

當前172.29.142.18是Primary, 172.29.142.17是Secondary

 

2.停掉主節點172.29.142.18,查看另兩台的選票結果

此時17變成了主節點,原先的仲裁節點不變,重新啟動第一次的Primary,則主節點又發生變化,不再截圖,整個過程業務是不中斷的。只要有一台可用即可。

Nodejs連接mongo集群示例

這里強烈不推薦連接單台mongo服務,因為如果一個mongo節點掛掉,業務就掛了,連接集群的話有一台可用就行。

下面舉了個nodejs連接mongo集群的示例:

const mongoose = require('mongoose');
let url = "mongodb://172.29.142.17:27017/testdb,mongodb://172.29.142.18:27017/testdb,mongodb://172.28.226.199:27017/testdb";
let options = {
  "replset": {
    "ha": true,
    "haInterval": 1000,
    "replicaSet": "mongo-rs",
    "connectWithNoPrimary": true,
    "auto_reconnect": true,
    "socketOptions": {
      "keepAlive": 120,
      connectTimeoutMS: 30000
    }
  }
}
 
 
mongoose.connect(url, options).connection
  .on('error', function (error) {
    console.log('mongo 連接錯誤', error)
  }).on('disconnected', mongoConnect).once('open', function () {
    console.log('mongo 連接成功');
  })

 

reference:

https://blog.csdn.net/luonanqin/article/details/8497860

https://blog.csdn.net/wangshuang1631/article/details/53857319


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM