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

选择一个合适索引而减少索引量,这种索引叫做重复索引,能够在索引中直接查找到所有要查询的索引,叫做覆盖索引,能够满足覆盖索引的条件并且排序次序又能够与索引的次序相同,这种次序是"3星"的,所以任何时候创建索引的目的一定要与搜索码完全匹配,至少保持一致.

选择一个合适索引而减少索引量,这种索引叫做重复索引,能够在索引中直接查找到所有要查询的索引,叫做覆盖索引,能够满足覆盖索引的条件并且排序次序又能够与索引的次序相同,这种次序是"3星"的,所以任何时候创建索引的目的一定要与搜索码完全匹配,至少保持一致.

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(官网有下)

  1. root@namenode1:/usr/local/tools#tarxfmongodb-linux-x86_64-2.4.5.tgz
  2. root@namenode1:/usr/local/tools#mvmongodb-linux-x86_64-2.4.5/usr/local/
  3. root@namenode1:/usr/local/tools#cd/usr/local/
  4. root@namenode1:/usr/local#ln-s/usr/local/mongodb-linux-x86_64-2.4.5//usr/local/mongodb
  5. root@namenode1:/usr/local#ll|grepmongo
  6. lrwxrwxrwx1rootstaff383月1715:35mongodb->/usr/local/mongodb-linux-x86_64-2.4.5/
  7. drwxr-sr-x3rootstaff40963月1715:08mongodb-linux-x86_64-2.4.5

#创建用户

  1. root@namenode1:~#groupadd-rmongod
  2. root@namenode1:~#useradd-M-r-gmongod-d/data/db-s/bin/false-cmongodmongod

#建立目录

  1. root@namenode1:~#mkdir-p/var/log/mongo/
  2. root@namenode1:~#mkdir-p/mongo/data
  3. root@namenode1:~#chownmongod/mongo/data/var/log/mongo/
  4. root@namenode1:~#ll/var/log/|grepmongo
  5. drwxr-xr-x2mongodroot4096Mar1715:25mongo
  6. root@namenode1:~#ll/mongo/
  7. total4
  8. drwxr-xr-x2mongodroot4096Mar1715:27data

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

  1. root@namenode1:~#echo‘exportLC_ALL="C"’>>/etc/profile

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

  1. root@namenode1:~#cat/etc/mongod.conf
  2. #mongo.conf
  3. #wheretolog
  4. logpath=/var/log/mongo/mongod.log
  5. logappend=true
  6. #forkandruninbackground
  7. fork=true
  8. #port=27017
  9. dbpath=/mongo/data
  10. #locationofpidfile
  11. pidfilepath=/var/run/mongodb/mongod.pid
  12. #Disableswrite-aheadjournaling
  13. #nojournal=true
  14. #EnablesperiodicloggingofCPUutilizationandI/Owait
  15. #cpu=true
  16. #Turnon/offsecurity.Offiscurrentlythedefault
  17. #noauth=true
  18. #auth=true
  19. #Verboseloggingoutput.
  20. #verbose=true
  21. #Inspectallclientdataforvalidityonreceipt(usefulfor
  22. #developingdrivers)
  23. #objcheck=true
  24. #Enabledbquotamanagement
  25. #quota=true
  26. #Setoplogginglevelwherenis
  27. #0=off(default)
  28. #1=W
  29. #2=R
  30. #3=both
  31. #7=W+somereads
  32. #diaglog=0
  33. #Ignorequeryhints
  34. #nohints=true
  35. #DisabletheHTTPinterface(Defaultstolocalhost:27018).
  36. #nohttpinterface=true
  37. #Turnsoffserver-sidescripting.Thiswillresultingreatlylimited
  38. #functionality
  39. #noscripting=true
  40. #Turnsofftablescans.Anyquerythatwoulddoatablescanfails.
  41. #notablescan=true
  42. #Disabledatafilepreallocation.
  43. #noprealloc=true
  44. #Specify.nsfilesizefornewdatabases.
  45. #nssize=<size>
  46. #AccouttokenforMongomonitoringserver.
  47. #mms-token=<token>
  48. #ServernameforMongomonitoringserver.
  49. #mms-name=<server-name>
  50. #PingintervalforMongomonitoringserver.
  51. #mms-interval=<seconds>
  52. #ReplicationOptions
  53. #inreplicatedmongodatabases,specifyherewhetherthisisaslaveormaster
  54. #slave=true
  55. #source=master.example.com
  56. #Slaveonly:specifyasingledatabasetoreplicate
  57. #only=master.example.com
  58. #or
  59. #master=true
  60. #source=slave.example.com

启动mongodb

  1. exportLC_ALL="C"
  2. root@namenode2:/usr/local/mongodb/bin#mongod-f/etc/mongod.conf

2.安装Rockmongo

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

  1. root@namenode1:~#apt-getinstallapache2php5php5-devphp5-cli
  2. root@namenode1:/etc/apache2#cd/var/www/
  3. root@namenode1:/var/www#wgethttp://rock-php.googlecode.com/files/rockmongo-v1.0.11.zip
  4. root@namenode1:/var/www#unziprockmongo-v1.0.11.zip

#二次编译php模块

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

#找到php模块所在路径

  1. root@namenode1:/var/www/mongo-php-driver-master#php-i|grepextension_dir
  2. extension_dir=>/usr/lib/php5/20100525=>/usr/lib/php5/20100525
  3. root@namenode1:/var/www/mongo-php-driver-master#ll/usr/lib/php5/20100525
  4. total2084
  5. -rwxr-xr-x1rootroot2016810Mar1716:35mongo.so
  6. -rw-r--r--1rootroot113072Dec1216:53pdo.so

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

  1. root@namenode1:/var/www/mongo-php-driver-master#ll/etc/php5/apache2/php.ini
  2. -rw-r--r--1rootroot65755Dec1216:53/etc/php5/apache2/php.ini
  3. root@namenode1:/var/www/mongo-php-driver-master#vi/etc/php5/apache2/php.ini

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

  1. 733extension=mongo.so

重启apache并查看url是否生效

  1. root@namenode1:/etc/init.d/apacherestart

访问以下地址

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

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

wKioL1MvyOqwnHOrAAC211s4F84914.jpg

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

wKiom1MvyRHQs9ikAAN5XB0vooI322.jpg

#p#

部署MongoDB主从复制:

1.规划如下:

服务器IP

服务器角色

172.23.214.47

Master

172.23.214.50

Slave

2.配置主从

编辑Master配置文件:

  1. root@namenode2:/var/log/mongo#grep-v"#"/etc/mongod.conf|grep-v"^$"
  2. logpath=/var/log/mongo/mongod.log
  3. logappend=true
  4. fork=true
  5. port=27017
  6. dbpath=/mongo/data
  7. pidfilepath=/var/run/mongodb/mongod.pid
  8. rest=true
  9. maxConns=1024
  10. master=true#将指定其为master
  11. oplogSize=2048

编辑Slave配置文件

  1. root@namenode1:/etc#catmongod.conf.bak_slave|grep-v"#"|grep-v"^$"
  2. logpath=/var/log/mongo/mongod.log
  3. logappend=true
  4. fork=true
  5. port=27017
  6. dbpath=/mongo/data
  7. maxConns=1024
  8. slave=true#指定其为slave
  9. source=172.23.214.47:27017#指定master的主机地址及端口号
  10. autoresync=true
  11. pidfilepath=/var/run/mongodb/mongod.pid

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

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

主库查看日志信息:

  1. root@namenode2:/var/log/mongo#catmongod.log
  2. TueMar1813:24:32.115[initandlisten]connectionacceptedfrom172.23.214.50:57356#2(1connectionnowopen)

从库查看日志信息

  1. root@namenode1:/var/log/mongo#tailmongod.log|grep47
  2. TueMar1813: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"}
  3. TueMar1813:24:31.188[replslave]repl:syncingfromhost:172.23.214.47:27017

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

  1. >db.testcoll.find()
  2. >showcollections
  3. >db.testcoll.insert({name:"tom"})
  4. >showcollections
  5. system.indexes
  6. testcoll
  7. >db.testcoll.find()
  8. {"_id":ObjectId("5327dabc9d62778b7a74ccab"),"name":"tom"}

在从库上查看

  1. >showdbs;
  2. local0.078125GB
  3. testdb0.203125GB
  4. >usetestdb;
  5. switchedtodbtestdb
  6. >db.testcoll.find()
  7. {"_id":ObjectId("5327dabc9d62778b7a74ccab"),"name":"tom"}

查看从库日志

  1. root@namenode1:/var/log/mongo#tailmongod.log
  2. TueMar1813:33:48.042[replslave]buildindextestdb.testcoll{_id:1}
  3. TueMar1813:33:48.042[replslave]fastBuildIndexdupsToDrop:0
  4. TueMar1813:33:48.043[replslave]buildindexdone.scanned1totalrecords.0secs
  5. TueMar1813:33:48.062[replslave]resync:donewithinitialclonefordb:testdb
  6. TueMar1813:34:55.757[initandlisten]connectionacceptedfrom127.0.0.1:32942#1(1connectionnowopen)
  7. TueMar1813:35:53.979[replslave]repl:checkpointapplied15operations
  8. TueMar1813:35:53.979[replslave]repl:syncedTo:Mar1813:35:445327db30:1
  9. TueMar1813:38:06.018[conn1]endconnection127.0.0.1:32942(0connectionsnowopen)
  10. TueMar1813:38:23.981[replslave]repl:checkpointapplied15operations
  11. TueMar1813:38:23.982[replslave]repl:syncedTo:Mar1813: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台主机配置文件都相同

  1. root@namenode1:~#grep-v"#"/etc/mongod.conf|grep-v"^$"
  2. logpath=/var/log/mongo/mongod.log
  3. logappend=true
  4. fork=true
  5. port=27017
  6. dbpath=/mongo/data
  7. pidfilepath=/var/run/mongodb/mongod.pid
  8. replSet=true#副本集的名字
  9. rest=true
  10. maxConns=1024
  11. oplogSize=2048

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

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

进入mongo

  1. root@namenode2:/mongo/data#mongo

初始化副本集:

  1. >rs.initiate()

构建对象

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

等待大约30秒钟

  1. >rs.initiate(rsconf)
  2. {
  3. "info":"Confignowsavedlocally.Shouldcomeonlineinaboutaminute.",#提示需要等待大约1分钟,如果及时查看副本集内容很可能报错
  4. "ok":1

查看副本集

  1. >rs.conf()

添加slave

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

分别在slave上执行:

  1. true:RECOVERING>rs.slaveOk()

验证:

在master上创建库:

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

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

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

设定某节点的优先级

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

如下所示:

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

  1. true:PRIMARY>rs.conf()
  2. {
  3. "_id":"true",
  4. "version":3,
  5. "members":[
  6. {
  7. "_id":0,
  8. "host":"namenode1:27017"
  9. },
  10. {
  11. "_id":1,
  12. "host":"namenode2:27017"
  13. },
  14. {
  15. "_id":2,
  16. "host":"datanode1:27017"
  17. }
  18. ]
  19. }

设置优先级别

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

  1. true:PRIMARY>cfg.members[0].priority=2
  2. true:PRIMARY>rs.conf()
  3. {
  4. "_id":"true",
  5. "version":3,
  6. "members":[
  7. {
  8. "_id":0,
  9. "host":"namenode1:27017"
  10. "priority":2
  11. },
  12. {
  13. "_id":1,
  14. "host":"namenode2:27017"
  15. },
  16. {
  17. "_id":2,
  18. "host":"datanode1:27017"
  19. }
  20. ]
  21. }

#p#

节点变更

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

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

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

查看节点

  1. true:PRIMARY>rs.status()
  2. {
  3. "set":"true",
  4. "date":ISODate("2014-03-19T04:38:52Z"),
  5. "myState":1,
  6. "members":[
  7. {
  8. "_id":0,
  9. "name":"namenode1:27017",
  10. "health":1,
  11. "state":1,
  12. "stateStr":"PRIMARY",
  13. "uptime":9510,
  14. "optime":Timestamp(1395197587,1),
  15. "optimeDate":ISODate("2014-03-19T02:53:07Z"),
  16. "self":true
  17. },
  18. {
  19. "_id":1,
  20. "name":"namenode2:27017",
  21. "health":1,
  22. "state":2,
  23. "stateStr":"SECONDARY",
  24. "uptime":9183,
  25. "optime":Timestamp(1395197587,1),
  26. "optimeDate":ISODate("2014-03-19T02:53:07Z"),
  27. "lastHeartbeat":ISODate("2014-03-19T04:38:51Z"),
  28. "lastHeartbeatRecv":ISODate("2014-03-19T04:38:51Z"),
  29. "pingMs":0,
  30. "syncingTo":"namenode1:27017"
  31. },
  32. {
  33. "_id":2,
  34. "name":"datanode1:27017",#将这个节点删除
  35. "health":1,
  36. "state":2,
  37. "stateStr":"SECONDARY",
  38. "uptime":6345,
  39. "optime":Timestamp(1395197587,1),
  40. "optimeDate":ISODate("2014-03-19T02:53:07Z"),
  41. "lastHeartbeat":ISODate("2014-03-19T04:38:50Z"),
  42. "lastHeartbeatRecv":ISODate("2014-03-19T04:38:51Z"),
  43. "pingMs":0,
  44. "syncingTo":"namenode1:27017"
  45. }
  46. ],
  47. "ok":1
  48. }

移除节点

  1. true:PRIMARY>rs.remove("datanode1:27017")
  2. WedMar1912:40:44.497DBClientCursor::initcall()failed
  3. WedMar1912:40:44.498JavaScriptexecutionfailed:Error:errordoingquery:failedatsrc/mongo/shell/query.js:L78
  4. WedMar1912:40:44.498tryingreconnectto127.0.0.1:27017
  5. WedMar1912:40:44.498reconnect127.0.0.1:27017ok

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

  1. true:PRIMARY>rs.status()
  2. {
  3. "set":"true",
  4. "date":ISODate("2014-03-19T04:41:03Z"),
  5. "myState":1,
  6. "members":[
  7. {
  8. "_id":0,
  9. "name":"namenode1:27017",
  10. "health":1,
  11. "state":1,
  12. "stateStr":"PRIMARY",
  13. "uptime":9641,
  14. "optime":Timestamp(1395204044,1),
  15. "optimeDate":ISODate("2014-03-19T04:40:44Z"),
  16. "self":true
  17. },
  18. {
  19. "_id":1,
  20. "name":"namenode2:27017",
  21. "health":1,
  22. "state":2,
  23. "stateStr":"SECONDARY",
  24. "uptime":19,
  25. "optime":Timestamp(1395204044,1),
  26. "optimeDate":ISODate("2014-03-19T04:40:44Z"),
  27. "lastHeartbeat":ISODate("2014-03-19T04:41:02Z"),
  28. "lastHeartbeatRecv":ISODate("2014-03-19T04:41:03Z"),
  29. "pingMs":0,
  30. "lastHeartbeatMessage":"syncingto:namenode1:27017",
  31. "syncingTo":"namenode1:27017"
  32. }
  33. ],
  34. "ok":1
  35. }

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

在master加入新节点

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

查看状态

  1. true:PRIMARY>rs.status()
  2. {
  3. "set":"true",
  4. "date":ISODate("2014-03-19T04:43:08Z"),
  5. "myState":1,
  6. "members":[
  7. {
  8. "_id":0,
  9. "name":"namenode1:27017",
  10. "health":1,
  11. "state":1,
  12. "stateStr":"PRIMARY",
  13. "uptime":9766,
  14. "optime":Timestamp(1395204185,1),
  15. "optimeDate":ISODate("2014-03-19T04:43:05Z"),
  16. "self":true
  17. },
  18. {
  19. "_id":1,
  20. "name":"namenode2:27017",
  21. "health":1,
  22. "state":2,
  23. "stateStr":"SECONDARY",
  24. "uptime":144,
  25. "optime":Timestamp(1395204185,1),
  26. "optimeDate":ISODate("2014-03-19T04:43:05Z"),
  27. "lastHeartbeat":ISODate("2014-03-19T04:43:06Z"),
  28. "lastHeartbeatRecv":ISODate("2014-03-19T04:43:07Z"),
  29. "pingMs":0,
  30. "syncingTo":"namenode1:27017"
  31. },
  32. {
  33. "_id":2,
  34. "name":"test:27017",
  35. "health":1,
  36. "state":6,
  37. "stateStr":"UNKNOWN",
  38. "uptime":3,
  39. "optime":Timestamp(0,0),
  40. "optimeDate":ISODate("1970-01-01T00:00:00Z"),
  41. "lastHeartbeat":ISODate("2014-03-19T04:43:07Z"),
  42. "lastHeartbeatRecv":ISODate("1970-01-01T00:00:00Z"),
  43. "pingMs":0,
  44. "lastHeartbeatMessage":"stillinitializing"
  45. }
  46. ],
  47. "ok":1
  48. }

切换至test节点查看数据库

  1. root@test:/var/log/mongo#mongo
  2. MongoDBshellversion:2.4.5
  3. connectingto:test
  4. true:SECONDARY>showdbs;
  5. admin(empty)
  6. local2.0771484375GB
  7. testdb0.203125GB
  8. true:SECONDARY>rs.slaveOk()

部署Sharding集群

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

sharding的实现思路

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

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

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

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

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

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

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

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

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

#p#

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

配置文件路径:

  1. /mongo/etc/configsvr.conf
  2. /mongo/etc/mongod.conf
  3. /mongo/etc/mongos.conf

日志路径:

  1. configserver/var/log/mongo/mongod_config_server.log
  2. mongod/var/log/mongo/mongod.log
  3. mongos/var/log/mongo/mongos.log

数据存放路径:

  1. /mongo/data/configdb
  2. /mongo/data/configsvr
  3. /mongo/data/mongod

1.建立副本集

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

  1. root@datanode1:/mongo/etc#catmongod.conf|grep-v"#"
  2. logpath=/var/log/mongo/mongod.log
  3. logappend=true
  4. fork=true
  5. port=27017
  6. dbpath=/mongo/data
  7. pidfilepath=/var/run/mongodb/mongod.pid
  8. replSet=rs0
  9. rest=true
  10. maxConns=1024
  11. oplogSize=2048

启动各个节点mongod

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

将master添加进副本集

  1. root@datanode1:/mongo/etc#mongo>rsconf={_id:"rs0",members:[{_id:0,host:"172.23.215.61:27017"}]}
  2. {
  3. "_id":"rs0",
  4. "members":[
  5. {
  6. "_id":0,
  7. "host":"172.23.215.61:27017"
  8. }
  9. ]
  10. }

激活副本集

  1. >rs.initiate(rsconf)
  2. {
  3. "info":"Confignowsavedlocally.Shouldcomeonlineinaboutaminute.",
  4. "ok":1
  5. }
  6. >rs.conf()
  7. {
  8. "_id":"rs0",
  9. "version":1,
  10. "members":[
  11. {
  12. "_id":0,
  13. "host":"172.23.215.61:27017"
  14. }
  15. ]
  16. }

陆续添加mongod节点

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

查看成员

  1. rs0:PRIMARY>rs.conf()
  2. {
  3. "_id":"rs0",
  4. "version":3,
  5. "members":[
  6. {
  7. "_id":0,
  8. "host":"172.23.215.61:27017"
  9. },
  10. {
  11. "_id":1,
  12. "host":"172.23.214.50:27017"
  13. },
  14. {
  15. "_id":2,
  16. "host":"172.23.214.47:27017"
  17. }
  18. ]
  19. }

#p#

测试:

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

  1. rs0:PRIMARY>usetest11;
  2. switchedtodbtest11
  3. rs0:PRIMARY>for(i=1;i<=100;i++)db.testcoll.insert({Name:"User"+i,Age:i,Gender:"M",preferbook:["bluebook","yellowbook"]})

去从库查看

  1. rs0:SECONDARY>showdbs;
  2. local2.0771484375GB
  3. test110.203125GB
  4. testdb0.203125GB

2.配置config server

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

  1. root@datanode1:/mongo/etc#catconfigsvr.conf
  2. configsvr=true
  3. dbpath=/mongo/data/configdb/
  4. port=27019
  5. logpath=/var/log/mongo/mongod_config_server.log
  6. logappend=true
  7. fork=true

启动config server

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

查看端口是否被监听

  1. root@datanode1:/mongo/etc#netstat-lnt|grep27
  2. tcp00127.0.0.1:6310.0.0.0:*LISTEN
  3. tcp00127.0.0.1:250.0.0.0:*LISTEN
  4. tcp000.0.0.0:270170.0.0.0:*LISTEN
  5. tcp000.0.0.0:270190.0.0.0:*LISTEN

3.配置mongos

  1. root@datanode1:/mongo/etc#catmongos.conf
  2. #mongo.conf
  3. port=27020
  4. configdb=172.23.215.61:27019,172.23.214.47:27019,172.23.214.50:27019#指定各configserver的ip地址或hostname,以及端口
  5. fork=true
  6. logpath=/var/log/mongo/mongos.log
  7. chunkSize=100
  8. logappend=true

启动路由(mongos)

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

使用mongo命令连入mongos实例

  1. root@datanode1:/mongo/etc#mongo172.23.215.61:27020

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

  1. mongos>sh.addShard("rs0/172.23.215.61:27017")
  2. {"shardAdded":"rs0","ok":1}

查看状态

  1. mongos>sh.status()
  2. ---ShardingStatus---
  3. shardingversion:{
  4. "_id":1,
  5. "version":3,
  6. "minCompatibleVersion":3,
  7. "currentVersion":4,
  8. "clusterId":ObjectId("532fa07065574826130abfbf")
  9. }
  10. shards:
  11. {"_id":"rs0","host":"rs0/172.23.214.47:27017,172.23.214.50:27017,172.23.215.61:27017"}
  12. databases:
  13. {"_id":"admin","partitioned":false,"primary":"config"}
  14. {"_id":"test11","partitioned":false,"primary":"rs0"}
  15. {"_id":"testdb","partitioned":false,"primary":"rs0"}

4.启用sharding功能

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

激活数据库分片

  1. switchedtodbadminmongos
  2. mongos>db.runCommand({enablesharding:"test11"});
  3. {"ok":1}
  4. mongos>db.runCommand({enablesharding:"testdb"});
  5. {"ok":1}

激活collection分片

  1. mongos>usetest11
  2. mongos>showcollections
  3. system.indexes
  4. testcoll#将此表进行激活

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

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

查看分片状态信息

  1. mongos>db.printShardingStatus();
  2. ---ShardingStatus---
  3. shardingversion:{
  4. "_id":1,
  5. "version":3,
  6. "minCompatibleVersion":3,
  7. "currentVersion":4,
  8. "clusterId":ObjectId("532fa07065574826130abfbf")
  9. }
  10. shards:
  11. {"_id":"rs0","host":"rs0/172.23.214.47:27017,172.23.214.50:27017,172.23.215.61:27017"}
  12. databases:
  13. {"_id":"admin","partitioned":false,"primary":"config"}
  14. {"_id":"test11","partitioned":true,"primary":"rs0"}
  15. test11.testcoll
  16. shardkey:{"_id":1}
  17. chunks:
  18. rs01
  19. {"_id":{"$minKey":1}}-->>{"_id":{"$maxKey":1}}on:rs0Timestamp(1,0)
  20. {"_id":"testdb","partitioned":true,"primary":"rs0"}
  21. {"_id":"test","partitioned":false,"primary":"rs0"}

博文链接:http://yijiu.blog.51cto.com/433846/1382239

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月6日 01:56
下一篇 2023年5月6日 01:56

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信