MongoDB集群搭建及Sharding的实现思路

MongoDB集群搭建

MongoDB的复制集群类型:

·主从模式(master/slave)

·副本集模式(replica set)

副本及模式至少3个节点(一主二从),从节点负责复制主节点的oplog到本地并且应用到本地从而实现冗余。

(·arbiter:仅参与选举,但不持有任何数据

·0优先级:可以触发选举,但是不能被选举成为主节点

·可以使用repiset来定义集群名称)


1.编译安装MongDB

准备环境:

系统:Debian 7.2 64位

mongodb:mongodb-linux-x86_64-2.4.5.tgz(官网有下)

root@namenode1:/usr/local/tools# tar xfmongodb-linux-x86_64-2.4.5.tgz

root@namenode1:/usr/local/tools# mv mongodb-linux-x86_64-2.4.5 /usr/local/
root@namenode1:/usr/local/tools# cd /usr/local/
root@namenode1:/usr/local# ln -s /usr/local/mongodb-linux-x86_64-2.4.5//usr/local/mongodb

root@namenode1:/usr/local# ll | grep mongo
lrwxrwxrwx  1 root   staff    38  3
月 17 15:35 mongodb ->/usr/local/mongodb-linux-x86_64-2.4.5/
drwxr-sr-x  3 root   staff  4096  3月 17 15:08 mongodb-linux-x86_64-2.4.5

#创建用户

root@namenode1:~# groupadd -r mongod
root@namenode1:~# useradd -M -r -g mongod -d /data/db -s /bin/false -c mongodmongod

#建立目录

root@namenode1:~# mkdir -p /var/log/mongo/

root@namenode1:~# mkdir -p /mongo/data
root@namenode1:~# chown mongod /mongo/data /var/log/mongo/


root@namenode1:~# ll /var/log/ | grep mongo

drwxr-xr-x 2mongod           root          4096 Mar 17 15:25mongo
root@namenode1:~# ll /mongo/
total 4
drwxr-xr-x 2 mongod root 4096 Mar 17 15:27 data

#LC_ALL="C"加入环境变量,以防启动出错

root@namenode1:~# echo ‘export LC_ALL="C"’ >> /etc/profile

#创建配置文件(将之前rpm包安装mongodb后的配置文件拷贝过来即可)

root@namenode1:~# cat /etc/mongod.conf
# mongo.conf

#where to log
logpath=/var/log/mongo/mongod.log

logappend=true

# fork and run in background
fork = true

#port = 27017

dbpath=/mongo/data

# location of pidfile
pidfilepath = /var/run/mongodb/mongod.pid

# Disables write-ahead journaling
# nojournal = true

# Enables periodic logging of CPU utilization and I/O wait
#cpu = true

# Turn on/off security.  Off is currently the default
#noauth = true
#auth = true

# Verbose logging output.
#verbose = true

# Inspect all client data for validity on receipt (useful for
# developing drivers)
#objcheck = true

# Enable db quota management
#quota = true

# Set oplogging level where n is
#   0=off (default)
#   1=W
#   2=R
#   3=both
#   7=W+some reads
#diaglog = 0

# Ignore query hints
#nohints = true

# Disable the HTTP interface (Defaults to localhost:27018).
#nohttpinterface = true

# Turns off server-side scripting.  This will result in greatly limited
# functionality
#noscripting = true

# Turns off table scans.  Any query that would do a table scan fails.
#notablescan = true

# Disable data file preallocation.
#noprealloc = true

# Specify .ns file size for new databases.
# nssize = <size>

# Accout token for Mongo monitoring server.
#mms-token = <token>

# Server name for Mongo monitoring server.
#mms-name = <server-name>

# Ping interval for Mongo monitoring server.
#mms-interval = <seconds>

# Replication Options

# in replicated mongo databases, specify here whether this is a slave or master
#slave = true
#source = master.example.com
# Slave only: specify a single database to replicate
#only = master.example.com
# or
#master = true
#source = slave.example.com

启动mongodb

export LC_ALL="C"

root@namenode2:/usr/local/mongodb/bin# mongod -f /etc/mongod.conf  


2.安装Rockmongo

RockMongo 是一个PHP5写的MongoDB管理工具。主要特征:使用宽松的New BSD License协议,速度快,安装简单,与mysql的phpmyadmin相似

root@namenode1:~# apt-get install apache2 php5 php5-dev php5-cli

root@namenode1:/etc/apache2# cd /var/www/
root@namenode1:/var/www# wgethttp://rock-php.googlecode.com/files/rockmongo-v1.0.11.zip
root@namenode1:/var/www# unzip rockmongo-v1.0.11.zip

#二次编译php模块

root@namenode1:/var/www/mongo-php-driver-master# phpize
root@namenode1:/var/www/mongo-php-driver-master# ./configure  
root@namenode1:/var/www/mongo-php-driver-master# make && makeinstall

#找到php模块所在路径

root@namenode1:/var/www/mongo-php-driver-master#  php -i | grepextension_dir

extension_dir => /usr/lib/php5/20100525 => /usr/lib/php5/20100525
root@namenode1:/var/www/mongo-php-driver-master# ll /usr/lib/php5/20100525

total 2084
-rwxr-xr-x 1 root root 2016810 Mar 17 16:35 mongo.so

-rw-r--r-- 1 root root  113072 Dec 12 16:53 pdo.so

#php在debian系统所安装的路径在以下的位置,如果是其他系统需根据相对路径进行查找

root@namenode1:/var/www/mongo-php-driver-master# ll/etc/php5/apache2/php.ini

-rw-r--r-- 1 root root 65755 Dec 12 16:53 /etc/php5/apache2/php.ini

root@namenode1:/var/www/mongo-php-driver-master# vi/etc/php5/apache2/php.ini

在733行加入内容,并保存退出

733 extension = mongo.so    


重启apache并查看url是否生效

root@namenode1:/etc/init.d/apache restart

访问以下地址

http://172.23.214.50/rockmongo/index.php?action=index.login

可以看到如下图所示,已经可以正常显示mongodb的管理登陆界面,默认情况下用户名与密码默认都为admin

wKioL1MvyOqwnHOrAAC211s4F84914.jpg

确认用户名和密码,登陆成功,如下所示

wKiom1MvyRHQs9ikAAN5XB0vooI322.jpg


部署MongoDB主从复制:

1.规划如下:

服务器IP

服务器角色

172.23.214.47

Master

172.23.214.50

Slave

2.配置主从

编辑Master配置文件:

root@namenode2:/var/log/mongo# grep -v "#" /etc/mongod.conf |grep -v "^$"

logpath=/var/log/mongo/mongod.log

logappend=true

fork = true

port = 27017

dbpath=/mongo/data

pidfilepath = /var/run/mongodb/mongod.pid

rest = true

maxConns=1024

master=true                           #将指定其为master

oplogSize=2048

编辑Slave配置文件

root@namenode1:/etc# cat mongod.conf.bak_slave  | grep -v "#" | grep -v"^$"

logpath=/var/log/mongo/mongod.log

logappend=true

fork = true

port = 27017

dbpath=/mongo/data

maxConns = 1024

slave = true                         #指定其为slave

source = 172.23.214.47:27017         #指定master的主机地址及端口号

autoresync = true

pidfilepath = /var/run/mongodb/mongod.pid

编辑好配置文件,双方启动mongodb

root@namenode1: mongod --f /etc/mongod.conf


主库查看日志信息:

root@namenode2:/var/log/mongo# cat mongod.log

Tue Mar 18 13:24:32.115 [initandlisten] connection accepted from172.23.214.50:57356 #2 (1 connection now open)

从库查看日志信息

root@namenode1:/var/log/mongo# tail mongod.log  | grep 47
Tue Mar 18 13:24:30.025 [initandlisten] options: { autoresync:"true", config: "/etc/mongod.conf", dbpath:"/mongo/data", fork: "true", logappend: "true",logpath: "/var/log/mongo/mongod.log", maxConns: 1024, pidfilepath:"/var/run/mongodb/mongod.pid", port: 27017, slave: "true",source: "172.23.214.47:27017" }
Tue Mar 18 13:24:31.188 [replslave] repl: syncingfrom host:172.23.214.47:27017


验证:主库创建库,并在从库查看

> db.testcoll.find()
> show collections
> db.testcoll.insert ( {name:"tom"})
> show collections
system.indexes
testcoll
> db.testcoll.find()
{ "_id" : ObjectId("5327dabc9d62778b7a74ccab"),"name" : "tom" }

在从库上查看

>show dbs;
local     0.078125GB

testdb     0.203125GB

> use testdb;
switched to db testdb
> db.testcoll.find()
{ "_id" : ObjectId("5327dabc9d62778b7a74ccab"),"name" : "tom" }

查看从库日志

root@namenode1:/var/log/mongo# tail mongod.log
Tue Mar 18 13:33:48.042 [replslave] build index testdb.testcoll { _id: 1 }
Tue Mar 18 13:33:48.042 [replslave]      fastBuildIndexdupsToDrop:0
Tue Mar 18 13:33:48.043 [replslave] build index done.  scanned 1 totalrecords. 0 secs
Tue Mar 18 13:33:48.062 [replslave] resync: done with initial clone for db:testdb
Tue Mar 18 13:34:55.757 [initandlisten] connection accepted from127.0.0.1:32942 #1 (1 connection now open)
Tue Mar 18 13:35:53.979 [replslave] repl:   checkpoint applied 15operations
Tue Mar 18 13:35:53.979 [replslave] repl:   syncedTo: Mar 18 13:35:445327db30:1
Tue Mar 18 13:38:06.018 [conn1] end connection 127.0.0.1:32942 (0 connectionsnow open)
Tue Mar 18 13:38:23.981 [replslave] repl:   checkpoint applied 15operations
Tue Mar 18 13:38:23.982 [replslave] repl:   syncedTo: Mar 18 13:38:145327dbc6:1

登录主库管理页面,查看其状态信息(master:1)

wKiom1MvyTWxMctVAAIMcTTMsYk485.jpg

2.mongodb副本集部署

准备环境

服务器IP

服务器角色

系统环境

172.23.214.47

master

DeBian 7

172.23.214.50

Slave

DeBian 7

172.23.215.61

Slave

DeBian 7


首先屏蔽掉配置文件中的master/slave这等敏感信息,将配置文件还原为最初状态

最好配置hosts,如果不指hosts则写ip也可以


编辑配置文件:

3台主机配置文件都相同

root@namenode1:~# grep -v "#" /etc/mongod.conf | grep -v"^$"

logpath=/var/log/mongo/mongod.log
logappend=true
fork = true
port = 27017
dbpath=/mongo/data
pidfilepath = /var/run/mongodb/mongod.pid
replSet = true              #
副本集的名字
rest = true

maxConns=1024
oplogSize=2048

先将master节点启动起来,登录想成为master的主机,启动mongod

root@ namenode2:~# mongod -f /etc/mongod.conf

进入mongo

root@namenode2:/mongo/data# mongo

初始化副本集:

>rs.initiate()

构建对象

{
    "_id" : "ture",                                         #
副本集的名字,要与配置文件对应
    "members" : [                                           #指定副本集成员
         {
             "_id" : 0,                          #指定副本集成员的id号
             "host" : 172.23.214.47:27017"       #先将master添加进来而后再依次将其他成员添加进副本集
         }
    ]
}

等待大约30秒钟

> rs.initiate( rsconf )
{
    "info" : "Config now savedlocally.  Should come online in about a minute.",       #
提示需要等待大约1分钟,如果及时查看副本集内容很可能报错
    "ok" : 1

查看副本集

> rs.conf()  

添加slave

true:PRIMARY> rs.add("172.23.214.47:27017")
{ "ok" : 1 }


true:PRIMARY> rs.add("172.23.215.61:27017")
{ "ok" : 1 }

分别在slave上执行:

true:RECOVERING> rs.slaveOk()

验证:

在master上创建库:

true:PRIMARY> use testdb;
switched to db testdb

true:PRIMARY> for(i=1;i<=100;i++) db.testcoll.insert({Name:"User"+i,Age:i,Gender:"M",preferbook:["bluebook","yellow book"]})

在slave节点上查看数据库,可以看到已经被通过到本地

true:RECOVERING> show dbs;
local     2.0771484375GB

testdb    0.203125GB


rs.initiate()//先初始化,再通过rs.add等方法修改
这里的config_object会记录在local.system.replset这个集合内,这个集合会自动的在副本集成员之间广播,而且我们不能直接修改他们,需要使用命令来改变它,例如(replSetInitiate 命令)。


设定某节点的优先级

将一个普通数据节点修改为passive节点,也就是能同步数据、投票,但是不能成为primay
除了仲裁节点,其他每个节点都有个优先权,我们可以通过设置优先权来决定谁的成为primay的权重最大,MongoDB replica sets中通过设置priority的值来决定优先权的大小,这个值的范围是0--100,值越大,优先权越高。如果值是0,那么不能成为prima


如下所示:

(#这个环境是之前保留的镜像副本,以Host_Name进行添加的)

true:PRIMARY> rs.conf()
{
    "_id" : "true",
    "version" : 3,
    "members" : [
         {
             "_id" : 0,
             "host" : "namenode1:27017"
         },
         {
             "_id" : 1,
             "host" : "namenode2:27017"
         },
         {
             "_id" : 2,
             "host" : "datanode1:27017"
         }
    ]
}

设置优先级别

#参考http://www.cnblogs.com/Amaranthus/p/3616951.html

true:PRIMARY> cfg.members[0].priority=2

true:PRIMARY> rs.conf()
{
    "_id" : "true",
    "version" : 3,
    "members" : [
         {
             "_id" : 0,
             "host" : "namenode1:27017"

"priority": 2
         },
         {
             "_id" : 1,
             "host" : "namenode2:27017"
         },
         {
             "_id" : 2,
             "host" : "datanode1:27017"
         }
    ]
}

节点变更
如果需要对副本集进行扩容,例如加入一台mongodb服务器进入副本集,需要先启动这个节点(最好是将数据事先拷贝一份启动,不然一个新的空的数据库进来同步可能会复制过多的数据而导致应用崩溃)

比如我们想将节点datanode1:27017 移除从而新加入节点test:27017

那么首先将集群中的datanode1:27017节点移除


查看节点

true:PRIMARY> rs.status()
{
    "set" : "true",
    "date" : ISODate("2014-03-19T04:38:52Z"),
    "myState" : 1,
    "members" : [
         {
             "_id" : 0,
             "name" : "namenode1:27017",
             "health" : 1,
             "state" : 1,
             "stateStr" : "PRIMARY",
             "uptime" : 9510,
             "optime" : Timestamp(1395197587, 1),
             "optimeDate" : ISODate("2014-03-19T02:53:07Z"),
             "self" : true
         },
         {
             "_id" : 1,
             "name" : "namenode2:27017",
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 9183,
             "optime" : Timestamp(1395197587, 1),
             "optimeDate" : ISODate("2014-03-19T02:53:07Z"),
             "lastHeartbeat" : ISODate("2014-03-19T04:38:51Z"),
             "lastHeartbeatRecv" : ISODate("2014-03-19T04:38:51Z"),
             "pingMs" : 0,
             "syncingTo" : "namenode1:27017"
         },
         {
             "_id" : 2,              
             "name" : "datanode1:27017",     #
将这个节点删除
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 6345,
             "optime" : Timestamp(1395197587, 1),
             "optimeDate" : ISODate("2014-03-19T02:53:07Z"),
             "lastHeartbeat" : ISODate("2014-03-19T04:38:50Z"),
             "lastHeartbeatRecv" : ISODate("2014-03-19T04:38:51Z"),
             "pingMs" : 0,
             "syncingTo" : "namenode1:27017"
         }
    ],
    "ok" : 1
}

移除节点

true:PRIMARY> rs.remove("datanode1:27017")
Wed Mar 19 12:40:44.497 DBClientCursor::init call() failed
Wed Mar 19 12:40:44.498 JavaScript execution failed: Error: error doing query:failed at src/mongo/shell/query.js:L78
Wed Mar 19 12:40:44.498 trying reconnect to 127.0.0.1:27017
Wed Mar 19 12:40:44.498 reconnect 127.0.0.1:27017 ok

再次查看副本集状态,发现datanode1已经没有了

true:PRIMARY> rs.status()
{
    "set" : "true",
    "date" : ISODate("2014-03-19T04:41:03Z"),
    "myState" : 1,
    "members" : [
         {
             "_id" : 0,
             "name" : "namenode1:27017",
             "health" : 1,
             "state" : 1,
             "stateStr" : "PRIMARY",
             "uptime" : 9641,
             "optime" : Timestamp(1395204044, 1),
             "optimeDate" : ISODate("2014-03-19T04:40:44Z"),
             "self" : true
         },
         {
             "_id" : 1,
             "name" : "namenode2:27017",
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 19,
             "optime" : Timestamp(1395204044, 1),
             "optimeDate" : ISODate("2014-03-19T04:40:44Z"),
             "lastHeartbeat" : ISODate("2014-03-19T04:41:02Z"),
             "lastHeartbeatRecv" : ISODate("2014-03-19T04:41:03Z"),
             "pingMs" : 0,
             "lastHeartbeatMessage" : "syncing to: namenode1:27017",
             "syncingTo" : "namenode1:27017"
         }
    ],
    "ok" : 1
}

接着配置启动test节点并启动,配置文件是相同的,启动之后它会自动复制数据。如果数据量过大,还是建议事先通过其它机制同步数据


在master加入新节点

true:PRIMARY> rs.add("test:27017")
{ "ok" : 1 }

查看状态

true:PRIMARY> rs.status()
{
    "set" : "true",
    "date" : ISODate("2014-03-19T04:43:08Z"),
    "myState" : 1,
    "members" : [
         {
             "_id" : 0,
             "name" : "namenode1:27017",
             "health" : 1,
             "state" : 1,
             "stateStr" : "PRIMARY",
             "uptime" : 9766,
             "optime" : Timestamp(1395204185, 1),
             "optimeDate" : ISODate("2014-03-19T04:43:05Z"),
             "self" : true
         },
         {
             "_id" : 1,
             "name" : "namenode2:27017",
             "health" : 1,
             "state" : 2,
             "stateStr" : "SECONDARY",
             "uptime" : 144,
             "optime" : Timestamp(1395204185, 1),
             "optimeDate" : ISODate("2014-03-19T04:43:05Z"),
             "lastHeartbeat" : ISODate("2014-03-19T04:43:06Z"),
             "lastHeartbeatRecv" : ISODate("2014-03-19T04:43:07Z"),
             "pingMs" : 0,
             "syncingTo" : "namenode1:27017"
         },
         {
             "_id" : 2,
             "name" : "test:27017",
             "health" : 1,
             "state" : 6,
             "stateStr" : "UNKNOWN",
             "uptime" : 3,
             "optime" : Timestamp(0, 0),
             "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
             "lastHeartbeat" : ISODate("2014-03-19T04:43:07Z"),
             "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
             "pingMs" : 0,
             "lastHeartbeatMessage" : "still initializing"
         }
    ],
    "ok" : 1
}

切换至test节点查看数据库

root@test:/var/log/mongo# mongo
MongoDB shell version: 2.4.5
connecting to: test
true:SECONDARY> show dbs;
admin     (empty)
local     2.0771484375GB
testdb    0.203125GB
true:SECONDARY> rs.slaveOk()




部署Sharding集群

sharding通过将数据集分布于多个也称作分片(shard)的节点上来降低单节点的访问压力。每个分片都是一个独立的数据库,所有的分片组合起来构成一个逻辑上的完整意义的数据库。因此,分片机制降低了每个分片的数据操作量及需要存储的数据量


sharding的实现思路

选择一个合适索引而减少索引量,这种索引叫做重复索引

能够在索引中直接查找到所有要查询的索引,叫做覆盖索引,能够满足覆盖索引的条件并且排序次序又能够与索引的次序相同,这种次序是"3星"的

所以任何时候创建索引的目的一定要与搜索码完全匹配,至少保持一致

mongodb中可以使用db.mycoll.find().hint().explain()

来显示索引的查询过程mysql中可以使用 explain select XXX



副本集的集群在刚开始配置的时候有以下几个细节:

1、初始化:根据定义好的配置文件初始化,也可以让其系统本身进行简单初始化

2、简单初始化只是将同一个repiset节点的信息添加进来,但默认只初始化当前节点信息

如果想重新配置这个集群的话,可以实现将现有的配置信息读取出来而后在里面做设置之后并重新让后续的配置生效,而也可以在后续新增节点到集群中也可以将已经运行的节点从集群中移除出去,不管是新增和移除它们之间都会进行选举操作的


mongodb shard架构

1、config server : 元数据服务器,3台,1台为单点故障,而如果使用2台在选举时候,会无法得到分布式  (zookeeper)在实验环境中有一个即可

2、mongos:路由,默认端口27017 ,启动的时候必须制定其config server为其指路

3、shard:能够存储分片的服务,可以是独立的服务器,也可以是replica set(副本集,生成环境建议使用此类型),因此生成环境中,一般都需要部署这样的集群


sharding集群

sharding目的:

·当单个节点所持有的数据太大,单个节点无法存储下的时候需要做shard

·如果某个单节点所持有的数据集太大,一个节点无法存储下的时候,则需要做shard

·如果某个单节点承载的读写并发请求过大时

·可预见的时间内,单个节点索引、经常被访问数据量,难在内存容纳下的时候,意味着可能用到swap,如果使用swap那么性能显著下降,对于此种情况需要用到shard

sharding主要做法无非将一个数据分割为多块,平局分布在各个节点,为了保证读写的性能,那么读的操作则不做离散,而写操作需要做离散操作


所以,mongodb主要是根据sharding key来决定分片切割的:

sharding key就是collection的索引,而collection的索引(sharding key)的选择至关重要。通常是第一个shard,也就是主shard


在shard上使用索引

使用顺序索引:

使用顺序插入时,写操作会集中在有限的shard上这样写操作很难均匀分布

使用离散索引:

会被分散到各节点中去,很难提高读性能


如何使用sharding key

假设我们数据库中有个表,表内数据分别为name,Age,Gender, 那么假设将一个collection 按照name切割,而name上创建的索引而是顺序索引,那就意味着是按范围进行切割的,那切割完成之后,那我们经常按照name查询,一般问题不大,查询的请求只交给config server即可,config server可以帮我们完成路由,而name则是charding key。

config server中保存的是每个shard和它所持有的数据的key的范围


以Age为例

如果是范围分区的话,那么我们想查询年龄在0-30岁的时候,则在哪个shard上则会保存在config server上?如果找不到响应的内容,那么则要对其进行全shard扫描

如果是离散的话,那么30在哪个服务器 40在哪里 。。等 config server全都会有记录


对应的key条目和它所对应的shard映射信息就是元数据,就在config server上

那如果我们对name来创建的,那么非常明显config server上所创建的就是某个名字和shard的映关系

所以如果按照age来进行查找的话,则没有办法去查找,那么这时则全shard扫描

如果大多数查询都是根据age来查询,而我们非选择sharding key为name 那么麻烦就大了

所以选择sharding key至关重要


真正选择shard的话 需要根据业务模型来选择的,一定要明白选择标准是什么。


sharding选择思路:

如果选择一个sharding key之后 有可能导致写不均匀,但做shard主要目的是离散写入均匀,所以我们在选择key的时候尽可能

1、尽可能范围选择shard

2、一旦落在某个shard以后仍然会变得过大,我们可以再进行将各chunk分布出去,则可以使用自合索引,比如:

将name和age同时当做sharding key 来使用

  {name:1,age: 1}  #先根据name做分区,意味着作为name的范围匹配了之后落在同一个shard上会根据age再次分区,如果内容量过大的话,会再次分割开的而不会单独在这shard上操作

3、也可以使用三级索引

  {name:1,age: 1,preferbooks} 有时我们存储了大量的数据进去,其会先对name进行分割发现落在某个shard的量过大,它会根据age再次分割,而后再次根据prefer books再次分割 这样可以使得写操作均匀分布,同样如果根据name范围查找的话,本来第一次分割是根据name分割的,很显然在一个范围内的用户通常会落在有限的shard上,所以读操作也做到了集中


在真正集群业务中并不是每个表都可以做shard的

比如有时候做shard可能带来很多问题

以博客为例:

我们以用户名做了shard 结果不同的用户可能被切割到不同shard中去,一个用户所发布的博文信息以及每个博文下的评论信息,每个用户发布的评论可能被存放在当前用户的shard上,当某个用户想查看自己博文下的所有评论信息的时候,那么评论的shard可能来自于多个用户,那么我对用户做了shard,也就意味着这些信息是根据用户所存储的 对应的用户所发布的评论也就有可能分布到多个shard上去 由此某个用户想查看自己博文下的所有评论,那么则会对其做全shard扫描,因此根据name来切割则是行不通的


以上的这种情况只能使用多个键

先根据文章和评论进行切割再根据用户名进行切割,意味着文章为标准,但同一个用户则放在有限的shard上去,这就是组合索引的好处

(尽可能保证前端的查询操作过于分散,这样就可以保证可以查询同一个或有限的shard)


如果文章与评论不是同一类的话:

那么既要考虑用户 又要考虑文章与评论 既然做分区了,如果用户本身信息量不是特别大的话,那么可以将一些有关联的表单独存放在一个库中


分片最主要的因素是选择sharding key

选择sharding key的标准:

1、应该在哪存数据

2、应该在哪得到希望的数据


读数据尽可能来自同一个点,写数据尽可能分散处理

夸分片做查询,比单个分片查询性能要差 但是只要不是太多的分片(2-3个)那么让读只落在有限的分片


总结:sharing基本法则

1、sharing key 应该是主键

2、选择分sharding key的时候应该选择那些避免跨分片查询,但是又得保证写是均匀的

3、将有关联的表放置在独立库中


部署分片集群

规划:

服务器IP

服务器角色

操作系统

172.23.215.61

config server、mongos、mongod

Debian GNU/Linux 7.2

172.23.214.50

config server、mongos、mongod

Debian GNU/Linux 7.2

172.23.214.47

mongos、mongod

Debian GNU/Linux 7.2

配置文件路径:

/mongo/etc/configsvr.conf

/mongo/etc/mongod.conf

/mongo/etc/mongos.conf

日志路径:

config server      /var/log/mongo/mongod_config_server.log

mongod             /var/log/mongo/mongod.log

mongos             /var/log/mongo/mongos.log

数据存放路径:

/mongo/data/configdb

/mongo/data/configsvr

/mongo/data/mongod

1.建立副本集

修改各节点配置文件,如下所示:

root@datanode1:/mongo/etc# cat mongod.conf  | grep -v "#"
logpath=/var/log/mongo/mongod.log
logappend=true
fork = true
port = 27017
dbpath=/mongo/data
pidfilepath = /var/run/mongodb/mongod.pid
replSet = rs0
rest = true
maxConns=1024
oplogSize=2048

启动各个节点mongod

root@datanode1:/mongo/etc# mongod -f mongod.conf

将master添加进副本集

root@datanode1:/mongo/etc# mongo> rsconf = { _id: "rs0",members: [ { _id: 0, host: "172.23.215.61:27017" } ] }

{
    "_id" : "rs0",
    "members" : [
         {
             "_id" : 0,
             "host" : "172.23.215.61:27017"
         }
    ]
}

激活副本集

> rs.initiate( rsconf )
{
    "info" : "Config now savedlocally.  Should come online in about a minute.",
    "ok" : 1
}
> rs.conf()
{
    "_id" : "rs0",
    "version" : 1,
    "members" : [
         {
             "_id" : 0,
             "host" : "172.23.215.61:27017"
         }
    ]
}

陆续添加mongod节点

rs0:PRIMARY> rs.add("172.23.214.50:27017")

rs0:PRIMARY> rs.add("172.23.214.47:27017")

查看成员

rs0:PRIMARY> rs.conf()

{

    "_id" :"rs0",

    "version" : 3,

    "members" : [

        {

             "_id" : 0,

             "host" :"172.23.215.61:27017"

        },

        {

             "_id" : 1,

             "host" :"172.23.214.50:27017"

        },

        {

             "_id" : 2,

             "host" :"172.23.214.47:27017"

        }

    ]

}

测试:

新建集合并插入数据,在从库查看是否同步

rs0:PRIMARY> use test11;
switched to db test11
rs0:PRIMARY> for(i=1;i<=100;i++)db.testcoll.insert({Name:"User"+i,Age:i,Gender:"M",preferbook:["bluebook","yellow book"]})

去从库查看

rs0:SECONDARY> show dbs;
local     2.0771484375GB
test11     0.203125GB
testdb     0.203125GB


2.配置config server

新建立配置文件,各节点内容相同

root@datanode1:/mongo/etc# cat configsvr.conf
configsvr=true
dbpath=/mongo/data/configdb/
port=27019
logpath=/var/log/mongo/mongod_config_server.log
logappend=true
fork=true

启动config server

root@datanode1:/mongo/etc# mongod -f configsvr.conf

查看端口是否被监听

root@datanode1:/mongo/etc# netstat -lnt | grep 27

tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN    

tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN    

tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN    

tcp        0      0 0.0.0.0:27019           0.0.0.0:*               LISTEN


3.配置mongos

root@datanode1:/mongo/etc# cat mongos.conf

# mongo.conf

port=27020

configdb=172.23.215.61:27019,172.23.214.47:27019,172.23.214.50:27019       #指定各config server的ip地址或hostname,以及端口

fork = true

logpath=/var/log/mongo/mongos.log

chunkSize = 100

logappend = true

启动路由(mongos)

root@datanode1:/mongo/etc# mongos -f mongos.conf

使用mongo命令连入mongos实例

root@datanode1:/mongo/etc#  mongo 172.23.215.61:27020

向分区集群中添加各shard服务器或副本集,如果添加的shard是副本集,则需要使用如下格式:

mongos> sh.addShard("rs0/172.23.215.61:27017")

{ "shardAdded" : "rs0", "ok" : 1 }

查看状态

mongos>  sh.status()
--- Sharding Status ---
 sharding version: {
    "_id" : 1,
    "version" : 3,
    "minCompatibleVersion" : 3,
    "currentVersion" : 4,
    "clusterId" :ObjectId("532fa07065574826130abfbf")
}
 shards:
    {  "_id" : "rs0", "host" :"rs0/172.23.214.47:27017,172.23.214.50:27017,172.23.215.61:27017" }
 databases:
    {  "_id" : "admin", "partitioned" : false,  "primary" : "config"}
    {  "_id" : "test11", "partitioned" : false,  "primary" : "rs0" }
    {  "_id" : "testdb", "partitioned" : false,  "primary" : "rs0" }

4.启用sharding功能

mongodb的shard功能实现于collection级别,但若要在collection上启动shard,还需要事先其相关的数据库上启用之。在数据库上启用shard功能后,MongoDB会为其指定一个主shard。

激活数据库分片

switched to db adminmongos

mongos> db.runCommand( { enablesharding : "test11" } );
{ "ok" : 1 }
mongos> db.runCommand( { enablesharding : "testdb" } );
{ "ok" : 1 }

激活collection分片

mongos> use test11

mongos> show collections
system.indexes
testcoll           #
将此表进行激活

进入admin库,激活collection分片并配置shard key唯一

>use admin

mongos> db.runCommand( { shardcollection : "test11.testcoll",key : {_id : 1 } , unique : true  } )
{ "collectionsharded" : "test11.testcoll", "ok" :1 }

查看分片状态信息

mongos> db.printShardingStatus();
--- Sharding Status ---
 sharding version: {
    "_id" : 1,
    "version" : 3,
    "minCompatibleVersion" : 3,
    "currentVersion" : 4,
    "clusterId" :ObjectId("532fa07065574826130abfbf")
}
 shards:
    {  "_id" : "rs0", "host" :"rs0/172.23.214.47:27017,172.23.214.50:27017,172.23.215.61:27017" }
 databases:
    {  "_id" : "admin", "partitioned" : false,  "primary" : "config"}
    {  "_id" : "test11", "partitioned" : true,  "primary" : "rs0" }
         test11.testcoll
             shard key: { "_id" : 1 }
             chunks:
                  rs0     1
             { "_id" : { "$minKey" : 1 } } -->> { "_id": { "$maxKey" : 1 } } on : rs0 Timestamp(1, 0)
    {  "_id" : "testdb", "partitioned" : true,  "primary" : "rs0" }
    {  "_id" : "test", "partitioned" : false,  "primary" : "rs0" }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要搭建MongoDB集群,你可以选择单机版、副本集群或分片集群。在Java开发中,代码本身没有任何区别,区别只在于application.yml的配置。 首先,对于单机版,你只需要配置一个MongoDB实例即可。配置文件中的uri字段指定连接地址,例如:mongodb://192.168.***.***:27017/testdb。 其次,副本集群是由多个MongoDB实例组成的,并且数据会自动复制到其他实例。配置文件中的uri字段指定多个实例的连接地址,例如:mongodb://192.168.***.***:27027,192.168.***.***:27028,192.168.***.***:27029/testdb。 最后,分片集群是由多个分片组成的,每个分片都包含了数据的子集。配置文件中的uri字段指定多个分片的连接地址,例如:mongodb://192.168.***.***:27071,192.168.***.***:27072,192.168.***.***:27073/testdb。在分片集群中,还需要配置路由服务(mongos)。 在安装MongoDB时,你可以使用提供的安装包和工具包。解压安装包和工具包后,将工具包中的bin目录下的各个可执行文件(如bsondump、mongodump等)复制到MongoDB的安装目录下的bin目录中。 通过以上步骤,你就可以搭建MongoDB集群了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [MongoDB集群搭建](https://blog.csdn.net/qq_55106682/article/details/122135750)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Mongodb集群搭建](https://blog.csdn.net/qq_21333693/article/details/128968829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值