mongodb運維之副本集實踐

突然發現芋頭好雞賊php

正式環境,4臺機器+一臺定時任務的機器。
服務器是阿里雲的ECS,
負載均衡用的是阿里雲的SLB,
mysql用阿里雲的RDS,
緩存用阿里雲的OCS,
運維基本上是都不須要擔憂了,
如今的雲服務已經很是完善了,
其實咱們用阿里雲的服務很是多,
大概有20多個類型的服務,
感謝阿里雲。

而個人技術棧是nodejs + mongodb,而阿里雲有k-v兼容redis協議的nosql,無mongodb,因此就要悲劇的本身運維mongodb了。html

阿里的ots是非結構化存儲,沒有nodejs的sdk,就算有,不兼容mongodb,也沒啥可玩的。node

雲服務

MongoDB存儲服務的雲平臺(MongoHQ, MongoLabs 和 Mongo Machine)mysql

國內的貌似只有 http://developer.baidu.com/wiki/index.php?title=docs/cplat/bae/mongodblinux

芋頭推薦用pg,支持json格式存儲redis

還有就是parse和leancloud這類面向api的。算法

京東和騰訊都有過,後來關閉了,不知何故sql

mongodb部署最佳實踐

常識: replset + shardmongodb

replset是副本集,shard是分片docker

mongoDB的主從模式其實就是一個單副本的應用,沒有很好的擴展性和容錯性。而副本集具備多個副本保證了容錯性,就算一個副本掛掉了還有不少副本存在,而且解決了上面第一個問題「主節點掛掉了,整個集羣內會自動切換」。

好比遊戲,開了某一個服,那麼全部的數據都在一臺服務器上,此時它要保證的是服務不掛就能夠,不用考慮更多的併發上的壓力,那麼它首先是副本集。

若是有節點掛了,它會從新選舉新的主節點

而更多的狀況是,你要考慮併發,並且多是千萬,億萬併發,副本集是搞不定的。

因而shard就登場了。

分片並非mongo獨有的概念,不少數據庫都有,mongodb裏的分片是指經過mongos來當網關路由,分發請求到每一個shard,而後每一個shard會對應各自的副本集。

既然是分發請求,就會有必定的性能損耗,但好處是你能處理更多請求。因此按照場景選擇

  • 性能最佳,固然是一個副本集,若是能知足需求,優先
  • 若是副本集不足及支撐併發,那麼就選shard

準備3臺阿里雲主機

  • 10.51.83.118
  • 10.51.77.129
  • 10.44.204.241

先各自ping一下,保證網絡通暢。

肯定個人目標是1主,2從,奇數個

這篇文字講了Bully算法以及爲啥是奇數個

http://www.lanceyan.com/tech/mongodb_repset2.html

注意點

  • 服務器節點以前時間要同步
  • 開啓防火牆的必定要容許經過
  • 開啓selinux的也要進行設置
  • 創建雙擊互信模式最好不過

格式化阿里雲的新增硬盤

http://www.cnblogs.com/dudu/archive/2012/12/07/aliyun-linux-fdisk.html

而後掛載到/data目錄下

配置文件

~/config/r0.config

port=27000
fork=true
logpath=/data/replset/log/r0.log
dbpath=/data/replset/r0
logappend=true
replSet=rs
#keyFile=/data/replset/key/r0

~/config/r1.config

port=27001
fork=true
logpath=/data/replset/log/r1.log
dbpath=/data/replset/r1
logappend=true
replSet=rs
#keyFile=/data/replset/key/r1

~/config/r2.config

port=27002
fork=true
logpath=/data/replset/log/r2.log
dbpath=/data/replset/r2
logappend=true
replSet=rs
#keyFile=/data/replset/key/r2

啓動

確保目錄爲空,殺死全部mongod進程

rm -rf /data/replset/

ps -ef|grep mongod | awk '{print $2}' | xargs kill -9
ps -ef|grep mongod

建立目錄

mkdir -p /data/replset/r0
mkdir -p /data/replset/r1
mkdir -p /data/replset/r2
mkdir -p /data/replset/key
mkdir -p /data/replset/log

準備key文件

echo "replset1 key" > /data/replset/key/r0
echo "replset1 key" > /data/replset/key/r1
echo "replset1 key" > /data/replset/key/r2
chmod 600 /data/replset/key/r*

注意第一次不能用keyFile

mongod -f ~/config/r0.config &
mongod -f ~/config/r1.config &
mongod -f ~/config/r2.config &

配置文件裏是fork=true,因此啓動須要點時間

初始化

> rs.initiate()  
{
	"info2" : "no configuration explicitly specified -- making one",
	"me" : "iZ25xk7uei1Z:27001",
	"ok" : 1
}

擦,超級慢。。。。

使用下面語句初始化

mongo --port 27000
rs.initiate({ _id:'rs',members:[{ _id:0, host:'10.51.77.129:27000' }]})

這個其實也很慢。。。。

待完成後,繼續增長其餘2個節點(必定要注意,在rs:PRIMARY即主節點上才能增長rs:SECONDARY和ARBITER。若是以前連的是其餘端口,須要切換的。)

rs.add("10.51.77.129:27001")
rs.addArb("10.51.77.129:27002")

查看狀態

rs.status();

若是想移除某一個節點

rs.remove("10.51.77.129:27001")
rs.remove("10.51.77.129:27000")
rs.remove("10.51.77.129:27002")

reconfig

若是想刪除,重置用rs.reconfig(),這樣作不必定會成功,有的時候沒法切換到主節點,因此須要,刪除/data/replset目錄,而後重啓全部mongo的進程。

rs.reconfig({ _id:'rs',members:[{ _id:1, host:'10.51.77.129:27000' }]})
rs.add("10.51.77.129:27000")
rs.addArb("10.51.77.129:27002")

db.oplog.rs

rs:PRIMARY> use local
switched to db local
rs:PRIMARY> show collections
me
oplog.rs
startup_log
system.indexes
system.replset
rs:PRIMARY> 
rs:PRIMARY> 
rs:PRIMARY> db.oplog.rs.find()
{ "ts" : Timestamp(1435495192, 1), "h" : NumberLong(0), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : Timestamp(1435495306, 1), "h" : NumberLong(0), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 2 } }
{ "ts" : Timestamp(1435495323, 1), "h" : NumberLong(0), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 3 } }

在SECONDARY節點沒法show dbs

主從啓動以後,鏈接slave能夠成功連上,可是在slave中執行 show dbs 的時候就報錯了:

QUERY    Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }

解決方法:

在報錯的slave機器上執行 rs.slaveOk()方法便可。

解釋一下具體slaveOk方法是什麼意思?

Provides a shorthand for the following operation:

db.getMongo().setSlaveOk()
This allows the current connection to allow read operations to run on secondary members. See the readPref() method for more fine-grained control over read preference in the mongo shell.

see

內存問題

查看內存狀況最經常使用的是free命令:

[deploy@iZ25xk7uei1Z config]$ free -m
             total       used       free     shared    buffers     cached
Mem:          7567       6821        745          8        129       6122
-/+ buffers/cache:        569       6997
Swap:            0          0          0

限制內存

全部鏈接消耗的內存加起來會至關驚人,推薦把Stack設置小一點,好比說1024:

ulimit -s 1024

經過調整內核參數drop_caches也能夠釋放緩存:

sysctl vm.drop_caches=1

有時候,出於某些緣由,你可能想釋放掉MongoDB佔用的內存,不過前面說了,內存管理工做是由虛擬內存管理器控制的,幸虧可使用MongoDB內置的closeAllDatabases命令達到目的:

mongo> use admin
mongo> db.runCommand({closeAllDatabases:1})

平時能夠經過mongo命令行來監控MongoDB的內存使用狀況,以下所示:

mongo> db.serverStatus().mem:
{
 "resident" : 22346,
 "virtual" : 1938524,
 "mapped" : 962283
}

還能夠經過mongostat命令來監控MongoDB的內存使用狀況,以下所示:

shell> mongostat
mapped vsize res faults
 940g 1893g 21.9g 0

其中內存相關字段的含義是:

  • mapped:映射到內存的數據大小
  • visze:佔用的虛擬內存大小
  • res:佔用的物理內存大小

注:若是操做不能在內存中完成,結果faults列的數值不會是0,視大小可能有性能問題。 在上面的結果中,vsize是mapped的兩倍,而mapped等於數據文件的大小,因此說vsize是數據文件的兩倍,之因此會這樣,是由於本例中,MongoDB開啓了journal,須要在內存裏多映射一次數據文件,若是關閉journal,則vsize和mapped大體至關。

see

更好的作法是使用docker,一勞永逸

全文完

歡迎關注個人公衆號【node全棧】

node全棧.png

相關文章
相關標籤/搜索