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
下一篇 2015-07-16

相關推薦

  • 磁盤分區和文件系統管理

    磁盤分區 兩種分區方式:MBR,GPT  MBR: Master Boot Record,1982年,使用32位表示扇區 數,分區不超過2T  如何分區:按柱面      0磁道0扇區:512bytes      446bytes: boo…

    Linux干貨 2016-08-29
  • HA cluster應用—CoroSync+Pacemaker

    HA cluster應用——CoroSync v2 (quorum system)+Pacemaker (standalone daemon)+ crmsh/pcsh corosync簡述: Corosync是OpenAIS發展到Wilson版本后衍生出來的開放性集群引擎工程??梢哉fCorosync是OpenAIS工程的一部分。OpenAIS從openais…

    2016-11-27
  • 網絡管理2

    六、配置網絡     跨網絡通信:路由     路由分類:         主機路由         網絡路由 &nbs…

    Linux干貨 2016-09-09
  • Linux文件查看和管理類命令

    1、Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示。
    4、文件的元數據信息有哪些,分別表示什么含義,如何查看?如何修改文件的時間戳信息。

    2018-03-17
  • Linux內核介紹

                               Linux內核介紹 嚴格來講,Linux這個詞本身只表示Linux內核,但實際上人們已經習慣了用Linux來形容整個基于Linux內核,并且使用GNU工程各種工具和數…

    Linux干貨 2016-10-27
  • shell腳本基礎

    1、編程基礎     程序:指令+數據   程序編程風格:                         過程式:以指令為中心,數據服務于指令         &nbs…

    2017-04-20
欧美性久久久久