MongoDB復制集及數據分片詳解

前言

MongoDB是一個由C++語言編寫的基于分布式文件存儲的數據庫,是當前NoSQL數據庫中比較熱門的一種,旨在為Web應用提供可擴展的高性能數據存儲解決方案。本文介紹MongoDB復制集及數據分片。

MongoDB

簡介

MongoDB是一個介于關系數據庫和非關系數據庫之間的產品,是非關系數據庫當中功能最豐富,最像關系數據庫的。支持的數據結構非常松散,因此可以存儲比較復雜的數據類型。最大的特點是其支持的查詢語言非常強大,其語法有點類似于面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。

特點及功能特性

特點:高性能、易部署、易使用,存儲數據非常方便

主要功能特性有:

面向集合存儲,易存儲對象類型的數據

模式自由

支持動態查詢

支持完全索引,包含內部對象

支持查詢

支持復制和故障恢復

使用高效的二進制數據存儲,包括大型對象(如視頻等)

自動處理碎片,以支持云計算層次的擴展性

支持Ruby,Python,Java,C++,PHP等多種語言

文件存儲格式為Bson(一種Json的擴展)

可通過網絡訪問

優缺點

與非關系型數據庫相比,MongoDB的優點:

弱一致性(最終一致),更能保證用戶的訪問速度

文檔結構的存儲方式,能夠更便捷的獲取數據

內置GridFS,支持大容量的存儲

內置Sharding

第三方支持豐富(這是與其他的NoSQL相比,MongoDB也具有的優勢)

性能優越

與非關系型數據庫相比,MongoDB的缺點:

不支持事務操作

占用空間過大

沒有成熟的維護工具

MongoDB復制集

復制集

MongoDB有兩種復制類型:Master/Slave主從和Replica Set副本集復制,由于MongoDB的特性,主從復制架構已基本不再使用,目前比較常見的是副本集復制方式

工作特性:

至少三個,且應該為奇數個節點,可使用arbiter(仲裁者)來參與選舉

復制集可實現失效自動轉移(通過選舉方式實現)

復制集的中特殊類型的節點:

0優先級的節點:冷備節點,不會被選舉成為主節點,但可以參與選舉

被隱藏的從節點:首先是一個0優先級的從節點,且對客戶端不可見

延遲復制的從節點:首先是一個0優先級的從節點,且復制時間落后于主節點一個固定時長

arbiter: 仲裁者

復制集架構

mongodb主從復制.jpg

實驗拓撲

mongodb復制集.jpg

#系統環境:CentOS6.6
#各節點時間已同步

配置過程

安裝所需軟件

[root@node1 ~]# cd mongodb/
[root@node1 mongodb]# ls
mongodb-org-server-2.6.10-1.x86_64.rpm  mongodb-org-tools-2.6.10-1.x86_64.rpm
mongodb-org-shell-2.6.10-1.x86_64.rpm
[root@node1 mongodb]# yum install *.rpm -y      #3個包都安裝

#所有節點都執行以上安裝操作

編輯配置文件

[root@node1 ~]# vim /etc/mongod.conf 

logpath=/var/log/mongodb/mongod.log
logappend=true
fork=true
dbpath=/mongodb/data                        #數據位置
pidfilepath=/var/run/mongodb/mongod.pid
#bind_ip=127.0.0.1                          #默認監聽本機,注釋掉監聽所有
httpinterface=true                          #開放web
rest=true
replSet=testSet                             #復制集名,可自定義
replIndexPrefetch=_id_only

同步配置文件至各節點

[root@node1 ~]# scp /etc/mongod.conf node3:/etc
root@node3's password: 
mongod.conf                                             100% 1567     1.5KB/s   00:00    
[root@node1 ~]# scp /etc/mongod.conf node4:/etc
root@node4's password: 
mongod.conf                                             100% 1567     1.5KB/s   00:00

創建數據目錄

[root@node1 ~]# mkdir /mongodb/data -pv
mkdir: created directory `/mongodb'
mkdir: created directory `/mongodb/data'
[root@node1 ~]# chown -R mongod.mongod /mongodb

#各節點都執行以上操作

啟動服務

[root@node1 ~]# service mongod start
Starting mongod:                                           [  OK  ]
[root@node1 mongodb]# ss -tnl | grep 27017
LISTEN     0      128                       *:27017                    *:*   

#各節點啟動服務,啟動過程中需要初始化數據,故啟動較慢

連接數據庫做初始化

[root@node1 ~]# mongo
MongoDB shell version: 2.6.10
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
	http://docs.mongodb.org/
Questions? Try the support group
	http://groups.google.com/group/mongodb-user
> rs.initiate()
{
	"info2" : "no configuration explicitly specified -- making one",
	"me" : "node1.scholar.com:27017",
	"info" : "Config now saved locally.  Should come online in about a minute.",
	"ok" : 1
}

#初始化成功,查看狀態信息
> rs.status()
{
	"set" : "testSet",
	"date" : ISODate("2015-07-13T12:33:27Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "node1.scholar.com:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 1111,
			"optime" : Timestamp(1436790736, 1),
			"optimeDate" : ISODate("2015-07-13T12:32:16Z"),
			"electionTime" : Timestamp(1436790737, 1),
			"electionDate" : ISODate("2015-07-13T12:32:17Z"),
			"self" : true
		}
	],
	"ok" : 1
}
testSet:PRIMARY> 

#已成為主節點

添加節點

testSet:PRIMARY> rs.add("172.16.10.125")
{ "ok" : 1 }
testSet:PRIMARY> rs.add("172.16.10.126")
{ "ok" : 1 }

#查看各節點狀態
testSet:PRIMARY> rs.status()
{
	"set" : "testSet",
	"date" : ISODate("2015-07-13T12:41:07Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "node1.scholar.com:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 1571,
			"optime" : Timestamp(1436791178, 1),
			"optimeDate" : ISODate("2015-07-13T12:39:38Z"),
			"electionTime" : Timestamp(1436790737, 1),
			"electionDate" : ISODate("2015-07-13T12:32:17Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "172.16.10.125:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 98,
			"optime" : Timestamp(1436791178, 1),
			"optimeDate" : ISODate("2015-07-13T12:39:38Z"),
			"lastHeartbeat" : ISODate("2015-07-13T12:41:06Z"),
			"lastHeartbeatRecv" : ISODate("2015-07-13T12:41:05Z"),
			"pingMs" : 1,
			"syncingTo" : "node1.scholar.com:27017"
		},
		{
			"_id" : 2,
			"name" : "172.16.10.126:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 89,
			"optime" : Timestamp(1436791178, 1),
			"optimeDate" : ISODate("2015-07-13T12:39:38Z"),
			"lastHeartbeat" : ISODate("2015-07-13T12:41:06Z"),
			"lastHeartbeatRecv" : ISODate("2015-07-13T12:41:06Z"),
			"pingMs" : 1,
			"syncingTo" : "node1.scholar.com:27017"
		}
	],
	"ok" : 1
}

創建數據,驗證是否同步

#主節點
testSet:PRIMARY> use testdb
switched to db testdb
testSet:PRIMARY> db.students.insert({name: "ZhangSan",age: "21"})
WriteResult({ "nInserted" : 1 })

#從節點
testSet:SECONDARY> rs.slaveOk()     #每個從節點首先申明從節點準備完畢才可同步
testSet:SECONDARY> use testdb
switched to db testdb
testSet:SECONDARY> show collections
students
system.indexes
testSet:SECONDARY> db.students.findOne()
{
	"_id" : ObjectId("55a3b494ebcafd9edbdfce4d"),
	"name" : "ZhangSan",
	"age" : "21"
}
#驗證從節點是否可寫
testSet:SECONDARY> db.classes.insert({class: "2",numstu: "50"})
WriteResult({ "writeError" : { "code" : undefined, "errmsg" : "not master" } })

#由此可見,只有主節點才可寫

以上便是復制集的相關配置,如果主節點故障,從節點會自動選舉出新的主節點,這里就不再演示

數據分片

分片緣由

分片(sharding)是MongoDB用來將大型集合分割到不同服務器(集群)上所采用的方法。當單臺服務器CPU,Memory,IO等無法滿足需求,就需要將數據分片存放,減緩服務器壓力。

分片架構

mongodb分片.jpg

實驗拓撲

mongodb分片拓撲.jpg

配置過程

因為以上做過實驗我們首先來清理一下數據

[root@node1 ~]# service mongod stop
Stopping mongod:                                           [  OK  ]
[root@node1 ~]# rm -rf /mongodb/data/*

#各節點都執行以上操作,若第一次做可忽略

Config Server配置

#安裝所需包
[root@node2 mongodb]# ls
mongodb-org-server-2.6.10-1.x86_64.rpm  mongodb-org-tools-2.6.10-1.x86_64.rpm
mongodb-org-shell-2.6.10-1.x86_64.rpm
[root@node2 mongodb]# yum install *.rpm -y

修改配置文件

[root@node2 ~]# vim /etc//mongod.conf 

logpath=/var/log/mongodb/mongod.log
logappend=true
fork=true
dbpath=/mongodb/data  
configsvr=true                               #開啟config server                  
pidfilepath=/var/run/mongodb/mongod.pid
#bind_ip=127.0.0.1                          
httpinterface=true                         
rest=true

創建數據目錄

[root@node2 ~]# mkdir /mongodb/data -pv
mkdir: created directory `/mongodb'
mkdir: created directory `/mongodb/data'
[root@node2 ~]# chown -R mongod.mongod /mongodb

啟動服務

[root@node2 ~]# service mongod start
Starting mongod:                                           [  OK  ]
[root@node2 ~]# ss -tnl | grep 27019
LISTEN     0      128                       *:27019                    *:*     

#監聽端口已發生改變,不再是27017

Mongos配置

#安裝所需包,Mongos節點只裝此包即可,無需裝第一次實驗中的mongod的相關包
[root@node1 ~]# yum install mongodb-org-mongos-2.6.10-1.x86_64.rpm -y

啟動服務

[root@node1 ~]# mongos --configdb=172.16.10.124 --fork --logpath=/var/log/mongodb/mongos.log
2015-07-13T22:22:47.404+0800 warning: running with 1 config server should be done only fo
r testing purposes and is not recommended for production
about to fork child process, waiting until server is ready for connections.
forked process: 3583
child process started successfully, parent exiting

#--configdb指定config server --logpath指定日志位置 --fork后臺運行

Shard配置

#以為我們第一次實驗安裝過軟件了,下面直接修改配置文件
[root@node3 ~]# vim /etc/mongod.conf 

logpath=/var/log/mongodb/mongod.log
logappend=true
fork=true
dbpath=/mongodb/data                      
pidfilepath=/var/run/mongodb/mongod.pid
#bind_ip=127.0.0.1                          
httpinterface=true                         
rest=true

[root@node3 ~]# service mongod start
Starting mongod:                                           [  OK  ]

#兩個shard節點都執行以上操作

Mongos節點添加Shard節點

[root@node1 ~]# mongo --host 172.16.10.123
MongoDB shell version: 2.6.10
connecting to: 172.16.10.123:27017/test
mongos> sh.addShard("172.16.10.125")
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("172.16.10.126")
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"version" : 4,
	"minCompatibleVersion" : 4,
	"currentVersion" : 5,
	"clusterId" : ObjectId("55a3c9ba131b83ff44e19435")
}
  shards:
	{  "_id" : "shard0000",  "host" : "172.16.10.125:27017" }
	{  "_id" : "shard0001",  "host" : "172.16.10.126:27017" }
  databases:
	{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }

對所需對象啟用分片功能

#對數據庫啟用sharding功能
mongos> sh.enableSharding("testdb")
{ "ok" : 1 }
mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"version" : 4,
	"minCompatibleVersion" : 4,
	"currentVersion" : 5,
	"clusterId" : ObjectId("55a3c9ba131b83ff44e19435")
}
  shards:
	{  "_id" : "shard0000",  "host" : "172.16.10.125:27017" }
	{  "_id" : "shard0001",  "host" : "172.16.10.126:27017" }
  databases:
	{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
	{  "_id" : "test",  "partitioned" : false,  "primary" : "shard0000" }
	{  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }

#指定需要分片的Collection及索引
mongos> sh.shardCollection("testdb.students",{"age": 1})
{ "collectionsharded" : "testdb.students", "ok" : 1 }
mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"version" : 4,
	"minCompatibleVersion" : 4,
	"currentVersion" : 5,
	"clusterId" : ObjectId("55a3c9ba131b83ff44e19435")
}
  shards:
	{  "_id" : "shard0000",  "host" : "172.16.10.125:27017" }
	{  "_id" : "shard0001",  "host" : "172.16.10.126:27017" }
  databases:
	{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
	{  "_id" : "test",  "partitioned" : false,  "primary" : "shard0000" }
	{  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }
		testdb.students
			shard key: { "age" : 1 }
			chunks:
				shard0000	1
			{ "age" : { "$minKey" : 1 } } -->> { "age" : { "$maxKey" : 1 } }
on : shard0000 Timestamp(1, 0)

分片功能已開啟,接下來我們手動創建數據來驗證是否會分片

mongos> use testdb
switched to db testdb
mongos> for (i=1;i<=100000;i++) db.students.insert({name:"student"+i,age:(i%120),addr:"china"})
WriteResult({ "nInserted" : 1 })
mongos> db.students.find().count()
100000
mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"version" : 4,
	"minCompatibleVersion" : 4,
	"currentVersion" : 5,
	"clusterId" : ObjectId("55a3c9ba131b83ff44e19435")
}
  shards:
	{  "_id" : "shard0000",  "host" : "172.16.10.125:27017" }
	{  "_id" : "shard0001",  "host" : "172.16.10.126:27017" }
  databases:
	{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
	{  "_id" : "test",  "partitioned" : false,  "primary" : "shard0000" }
	{  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }
		testdb.students
			shard key: { "age" : 1 }
			chunks:
				shard0001	1
				shard0000	2
			{ "age" : { "$minKey" : 1 } } -->> { "age" : 1 } on : shard0001 Timestamp(2, 0) 
			{ "age" : 1 } -->> { "age" : 119 } on : shard0000 Timestamp(2, 2) 
			{ "age" : 119 } -->> { "age" : { "$maxKey" : 1 } } on : shard0000 Timestamp(2, 3)

查看數據狀態會發現數據已被分到不同shard上,至此,數據分片成功實現

The end

MongoDB復制集及數據分片就先說到這里了,通過以上簡單應用可以看出,MongoDB在無論大數據處理還是復制方面都有著比MySQL更加優秀的性能和更加簡單的操作,但由于MongoDB目前還不是很成熟,在實際的應用中還有許多問題有待解決,相信在未來MongoDB會更加出色。以上僅為個人學習整理,如有錯漏,大神勿噴~~~

原創文章,作者:書生,如若轉載,請注明出處:http://www.www58058.com/6254

(0)
書生書生
上一篇 2015-07-15 22:27
下一篇 2015-07-16 22:25

相關推薦

  • 那些年我們一起追過的緩存寫法(二)

    原文出處: 蘑菇先生   上次主要討論緩存讀寫這塊各種代碼實現。本篇是就上次的問題接著來,繼續看那些年我們各種緩存用法。 一:緩存預熱 上次有同學問過。在第一次加載時,我們的緩存都為空,怎么進行預熱。 單機Web情況下,一般我們使用RunTimeCache。相對于這種情況下: 1:我們可以在啟動事件里面刷新 1 2 3 4 vo…

    Linux干貨 2015-03-04
  • 私人定制—linux系統

    自制Linux系統: 1、分區并創建文件系統 [root@localhost6 ~]# fdisk  /dev/sdb 分兩個必要的分區 /dev/sdb1對應/boot /dev/sdb2對應根/ 創建文件系統: [root@localhost6 ~]# mkfs.ext4 /dev/s…

    Linux干貨 2016-09-26
  • test

    test the URL.

    Linux干貨 2016-12-03
  • 馬哥教育第20期一班第一周博客

    Linux入門 1、Linux的哲學思想 一切皆文件(硬件設備亦表現為文件) 由眾多目的單一的小程序組成;一個程序只做一件事,并且要做好 組合小程序完成復雜任務 盡可能避免跟用戶交互 使用文本文件保存配置信息 提供機制,而非策略 2、常用命令 id命令 簡介:   id – print real a…

    Linux干貨 2016-07-26
  • 文本處理工具

    1、cat命令 功能: 顯示文本內容,連接合并文本內容并在標準設備上輸出 語法: cat [OPTION]… [FILE]… 選項: -E:顯示行結束符(回車)$ -A:顯示所有控制符,相當于-vET -n:對顯示出的每一行進行編號 -b:對非空白行編號 -s:將連續的空行壓縮成一行 -T:把TAB字符顯示為^I -v:除了&nb…

    Linux干貨 2016-08-07
  • CentOS7的啟動及Systemd的管理?

    CentOS7的啟動流程     POST–>Boot Sequence–>Bootloader–>kernel+initramfs(initrd)–>rootfs–>/sbin/init    &n…

    Linux干貨 2016-09-21
欧美性久久久久