21.4 MongoDB介绍


什么是MongoDB

MongoDB也是NoSQL的一种,它是一个基于分布式文件存储的文档型数据库,由C++语言编写。因为是文档型数据库,所以它是非关系数据库中功能最丰富、最像关系数据库的。

官方网站 ,最新版本4.0.1。

MongoDB将数据存储为一个文档,数据结构将键值(key-value)对组成,MongoDB文档类似于JSON对象,字段值可以包含其它文档、数组及文档数组。

了解JSON

  • 基本概念:
文档(document):MongoDB中数据的基本单元,非常类似于关系型数据库系统中的行,但是比行要复杂的多。集合(collection):一组文档,如果说MongoDB中的文档类似于关系型数据库中的行,那么集合就如同表。MongoDB的单个计算机可以容纳多个独立的数据库,每一个数据库都有自己的集合和权限;MongoDB自带简洁但功能强大的JavaScript shell,这个工具对于管理MongoDB实例和操作数据作用非常大;每一个文档都有一个特殊的键”_id”,它在文档所处的集合中是唯一的,相当于关系数据库中的表的主键。

MongoDB的特点是高性能、易部署、易使用,存储数据非常方便,它的主要特性有:

面向集合存储,易存储对象类型的数据
模式自由
支持动态查询
支持完全索引,包含内部对象
支持复制和故障恢复
使用高效的二进制数据存储,包括大型对象
文件存储格式为BSON(一种JSON的扩展)


MongoDB安装

  • 安装MongoDB:
# cd /etc/yum.repos.d/# vim mongo.repo[mongodb-org-3.4]name=MongoDB Repositorybaseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/gpgcheck=1enabled=1gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc# yum install -y mongodb-org


连接MongoDB

  • 启动服务:
# systemctl start mongod# ps aux |grep mongodmongod     1522  0.8  0.9 972380 37512 ?        Sl   10:30   0:00 /usr/bin/mongod -f /etc/mongo.conf# netstat -lntp |grep mongodtcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      1522/mongod

  • 进入mongodb shell:
# mongoMongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27017#显示IP及监听端口MongoDB server version: 3.4.16Welcome to the MongoDB shell.For interactive help, type "help".For more comprehensive documentation, seehttp://docs.mongodb.org/Questions? Try the support grouphttp://groups.google.com/group/mongodb-userServer has startup warnings: 2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] 2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] 2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] 2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] 2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'#关于内核的警告,可忽略2018-08-25T10:30:18.431+0800 I CONTROL  [initandlisten] >

如果监听端口不是默认的27017,则在连接的时候需要加--port选项,如:

mongo --port 27018

远程连接mongodb,需要加--host,如:

mongo --host 127.0.0.1

如果设置了验证,则在连接的时候需要带上用户名和密码,如:

mongo -u用户名 -p密码 --authenticationDatabase 数据库名#和mysql类似


MongoDB用户管理

  • 管理用户:
> use admin#use切换库,只有在admin库中才可以操作用户管理switched to db admin#创建用户并授权;customData表示对用户的描述,可省略;roles表示角色,指定库的权限> db.createUser( { user: "admin", customData: {description: "superuser"}, pwd: "admin123", roles: [ { role: "root", db:"admin" } ] } )Successfully added user: {"user" : "admin","customData" : {"description" : "superuser"},"roles" : [{"role" : "root","db" : "admin"}]}

> db.system.users.find()#列出所有用户,需要切换到admin库{ "_id" : "admin.admin", "user" : "admin", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "J8r1+mWlE53xnEKSiQ98hA==", "storedKey" : "7dl9ZmLoj8AHTb7LguX/w4C9X9U=", "serverKey" : "ZMpgYfQMxGAULJh9a5rFijPny2E=" } }, "customData" : { "description" : "superuser" }, "roles" : [ { "role" : "root", "db" : "admin" } ] }#admin.admin表示admin库的admin用户

> show users#列出当前库下所有的用户{"_id" : "admin.admin","user" : "admin","db" : "admin","customData" : {"description" : "superuser"},"roles" : [{"role" : "root","db" : "admin"}]}

> db.createUser({user:"lzx",pwd:"123123",roles:[{role:"read",db:"testdb"}]})#创建lzx用户,设为read角色,针对的库是testdbSuccessfully added user: {"user" : "lzx","roles" : [{"role" : "read","db" : "testdb"}]}> show users#查看新创建的用户{"_id" : "admin.admin","user" : "admin","db" : "admin","customData" : {"description" : "superuser"},"roles" : [{"role" : "root","db" : "admin"}]}{"_id" : "admin.lzx","user" : "lzx","db" : "admin","roles" : [{"role" : "read","db" : "testdb"}]}> db.dropUser('lzx')#删除刚创建的lzx用户true> show users          {"_id" : "admin.admin","user" : "admin","db" : "admin","customData" : {"description" : "superuser"},"roles" : [{"role" : "root","db" : "admin"}]}#新创建的用户已经消失

新增用户之后,若要用户生效,还需要编辑启动脚本:

# vim /usr/lib/systemd/system/mongod.serviceEnvironment="OPTIONS=--auth -f /etc/mongod.conf"# systemctl daemon-reload# systemctl restart mongod# ps aux |grep mongodmongod     8049 17.8  1.0 972380 41420 ?        Sl   14:03   0:02 /usr/bin/mongod --auth -f /etc/mongod.conf# mongo --host 127.0.0.1 --port 27017MongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27017/MongoDB server version: 3.4.16

> use adminswitched to db admin> show users#刚刚登录的用户没有权限执行命令2018-08-25T14:06:39.482+0800 E QUERY    [thread1] Error: not authorized on admin to execute command { usersInfo: 1.0 } :_getErrorWithCode@src/mongo/shell/utils.js:25:13DB.prototype.getUsers@src/mongo/shell/db.js:1539:1shellHelper.show@src/mongo/shell/utils.js:771:9shellHelper@src/mongo/shell/utils.js:678:15@(shellhelp2):1:1# mongo --host 127.0.0.1 --port 27017 -u 'admin' -p 'admin123' --authenticationDatabase "admin"#指定用户密码和库,再次登录MongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27017/MongoDB server version: 3.4.16Server has startup warnings: 2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] 2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] 2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-25T14:03:27.518+0800 I CONTROL  [initandlisten] > use adminswitched to db admin> show users#再次执行命令就没问题了{"_id" : "admin.admin","user" : "admin","db" : "admin","customData" : {"description" : "superuser"},"roles" : [{"role" : "root","db" : "admin"}]}

> use db1switched to db db1> db.createUser({user:"test1",pwd:"123123",roles:[{role:"readWrite",db:"db1"},{role:"read",db:"db2"}]})#创建用户test1,对db1库有读写权限,对db2库只读Successfully added user: {"user" : "test1","roles" : [{"role" : "readWrite","db" : "db1"},{"role" : "read","db" : "db2"}]}

use db1,表示用户在db1库中创建,用户的信息会跟随数据库

> db.auth('test1','123123')#在命令行认证用户1#返回1说明认证成功> use db2switched to db db2> db.auth('test1','123123')Error: Authentication failed.0#db2下认证失败

MongoDB中有这些角色:

read:允许用户读取指定数据库readWrite:允许用户读写指定数据库dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profileuserAdmin:允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户clusterAdmin:只在admin数据中可用,赋予用户所有分片和复制集相关函数的管理权限readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限userAdminAnyDatabase:只在admin数据库中可用,赋予所有数据库的userAdmin权限dbAdminAnyDatabase:只在admin数据库中可用,赋予所有数据库的dbAdmin权限root:只在admin数据库中可用。超级账号,超级权限


MongoDB创建集合、数据管理

> use db1switched to db db1> db.createCollection("mycol",{capped:true,size:6142800,max:10000}){ "ok" : 1 }

创建集合;集合名为mycol;option可选,用来配置集合的参数。
capped true/false (可选),如果为true,则启用封顶集合。封顶集合是固定大小的集合,当它达到最大大小,会自动覆盖最早的条目。如果指定为true,也需要指定尺寸参数;
size(可选),指定最大大小字节封顶集合。如果capped是true,那么就必须指定这个字段,单位B;
max(可选),指定封顶集合允许在文件的最大数量。

> show tables#查看集合mycol> show collections#这样也可以查看集合mycol

> db.Account.insert({AccountID:1,UserName:"123",password:"123456"})#向集合中插入数据,若集合不存在,则自动创建WriteResult({ "nInserted" : 1 })> show collectionsAccountmycol

> db.Account.insert({AccountID:2,UserName:"aaa",password:"aaaaaa"})#再插入一个文档WriteResult({ "nInserted" : 1 })> show collectionsAccount#仍属于Account集合     mycol> db.Account.update({AccountID:1},{"$set":{"Age":20}})#更新集合中AccountID:1文档的数据WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })> db.Account.find()#查看所有文档{ "_id" : ObjectId("5b80feb826e56a836ac4d168"), "AccountID" : 1, "UserName" : "123", "password" : "123456", "Age" : 20 }{ "_id" : ObjectId("5b8100cc26e56a836ac4d169"), "AccountID" : 2, "UserName" : "aaa", "password" : "aaaaaa" }

> db.Account.find({AccountID:1})#指定条件查询{ "_id" : ObjectId("5b80feb826e56a836ac4d168"), "AccountID" : 1, "UserName" : "123", "password" : "123456", "Age" : 20 }

> db.Account.remove({AccountID:1})WriteResult({ "nRemoved" : 1 })#指定条件删除文档> db.Account.find(){ "_id" : ObjectId("5b8100cc26e56a836ac4d169"), "AccountID" : 2, "UserName" : "aaa", "password" : "aaaaaa" }

> db.Account.drop()#删除集合Account中所有文档,即删除集合true> show collectionsmycol> db.mycol.drop()true> show collections

> db.col123.insert({AccountID:1,UserName:"123",password:"123456"})WriteResult({ "nInserted" : 1 })> db.printCollectionStats()#查看所有集合状态col123{"ns" : "db1.col123","size" : 80,"count" : 1,"avgObjSize" : 80,"storageSize" : 16384,"capped" : false,"wiredTiger" : {"metadata" : {"formatVersion" : 1},"creationString" : "access_pattern_hint=none,allocation_size=4KB,app_metadata=(formatVersion=1),block_allocation=best,block_compressor=snappy,cache_resident=false,checksum=on,colgroups=,collator=,columns=,dictionary=0,encryption=(keyid=,name=),exclusive=false,extractor=,format=btree,huffman_key=,huffman_value=,ignore_in_memory_cache_size=false,immutable=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=q,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=64MB,log=(enabled=true),lsm=(auto_throttle=true,bloom=true,bloom_bit_count=16,bloom_config=,bloom_hash_count=8,bloom_oldest=false,chunk_count_limit=0,chunk_max=5GB,chunk_size=10MB,merge_max=15,merge_min=0),memory_page_max=10m,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,source=,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,type=file,value_format=u","type" : "file","uri" : "statistics:table:collection-4-6088379814182883756","LSM" : {"bloom filter false positives" : 0,"bloom filter hits" : 0,"bloom filter misses" : 0,"bloom filter pages evicted from cache" : 0,"bloom filter pages read into cache" : 0,"bloom filters in the LSM tree" : 0,"chunks in the LSM tree" : 0,"highest merge generation in the LSM tree" : 0,"queries that could have benefited from a Bloom filter that did not exist" : 0,"sleep for LSM checkpoint throttle" : 0,"sleep for LSM merge throttle" : 0,"total size of bloom filters" : 0},"block-manager" : {"allocations requiring file extension" : 3,"blocks allocated" : 3,"blocks freed" : 0,"checkpoint size" : 4096,"file allocation unit size" : 4096,"file bytes available for reuse" : 0,"file magic number" : 120897,"file major version number" : 1,"file size in bytes" : 16384,"minor version number" : 0},"btree" : {"btree checkpoint generation" : 22,"column-store fixed-size leaf pages" : 0,"column-store internal pages" : 0,"column-store variable-size RLE encoded values" : 0,"column-store variable-size deleted values" : 0,"column-store variable-size leaf pages" : 0,"fixed-record size" : 0,"maximum internal page key size" : 368,"maximum internal page size" : 4096,"maximum leaf page key size" : 2867,"maximum leaf page size" : 32768,"maximum leaf page value size" : 67108864,"maximum tree depth" : 3,"number of key/value pairs" : 0,"overflow pages" : 0,"pages rewritten by compaction" : 0,"row-store internal pages" : 0,"row-store leaf pages" : 0},"cache" : {"bytes currently in the cache" : 952,"bytes read into cache" : 0,"bytes written from cache" : 175,"checkpoint blocked page eviction" : 0,"data source pages selected for eviction unable to be evicted" : 0,"hazard pointer blocked page eviction" : 0,"in-memory page passed criteria to be split" : 0,"in-memory page splits" : 0,"internal pages evicted" : 0,"internal pages split during eviction" : 0,"leaf pages split during eviction" : 0,"modified pages evicted" : 0,"overflow pages read into cache" : 0,"overflow values cached in memory" : 0,"page split during eviction deepened the tree" : 0,"page written requiring lookaside records" : 0,"pages read into cache" : 0,"pages read into cache requiring lookaside entries" : 0,"pages requested from the cache" : 1,"pages written from cache" : 2,"pages written requiring in-memory restoration" : 0,"tracked dirty bytes in the cache" : 0,"unmodified pages evicted" : 0},"cache_walk" : {"Average difference between current eviction generation when the page was last considered" : 0,"Average on-disk page image size seen" : 0,"Clean pages currently in cache" : 0,"Current eviction generation" : 0,"Dirty pages currently in cache" : 0,"Entries in the root page" : 0,"Internal pages currently in cache" : 0,"Leaf pages currently in cache" : 0,"Maximum difference between current eviction generation when the page was last considered" : 0,"Maximum page size seen" : 0,"Minimum on-disk page image size seen" : 0,"On-disk page image sizes smaller than a single allocation unit" : 0,"Pages created in memory and never written" : 0,"Pages currently queued for eviction" : 0,"Pages that could not be queued for eviction" : 0,"Refs skipped during cache traversal" : 0,"Size of the root page" : 0,"Total number of pages currently in cache" : 0},"compression" : {"compressed pages read" : 0,"compressed pages written" : 0,"page written failed to compress" : 0,"page written was too small to compress" : 2,"raw compression call failed, additional data available" : 0,"raw compression call failed, no additional data available" : 0,"raw compression call succeeded" : 0},"cursor" : {"bulk-loaded cursor-insert calls" : 0,"create calls" : 1,"cursor-insert key and value bytes inserted" : 81,"cursor-remove key bytes removed" : 0,"cursor-update value bytes updated" : 0,"insert calls" : 1,"next calls" : 0,"prev calls" : 1,"remove calls" : 0,"reset calls" : 2,"restarted searches" : 0,"search calls" : 0,"search near calls" : 0,"truncate calls" : 0,"update calls" : 0},"reconciliation" : {"dictionary matches" : 0,"fast-path pages deleted" : 0,"internal page key bytes discarded using suffix compression" : 0,"internal page multi-block writes" : 0,"internal-page overflow keys" : 0,"leaf page key bytes discarded using prefix compression" : 0,"leaf page multi-block writes" : 0,"leaf-page overflow keys" : 0,"maximum blocks required for a page" : 0,"overflow values written" : 0,"page checksum matches" : 0,"page reconciliation calls" : 2,"page reconciliation calls for eviction" : 0,"pages deleted" : 0},"session" : {"object compaction" : 0,"open cursor count" : 1},"transaction" : {"update conflicts" : 0}},"nindexes" : 1,"totalIndexSize" : 16384,"indexSizes" : {"_id_" : 16384},"ok" : 1}


PHP的MongoDB扩展

针对PHP的mongodb扩展有两个:mongo.somongodb.so,其中,mongo.so针对的是PHP5.x版本,新的扩展是mongodb.so。两个可以任选一个,下面安装mongodb.so的扩展。

  • 下载解压:
# cd /software# wget https://pecl.php.net/get/mongodb-1.3.0.tgz# tar zxf mongodb-1.3.0.tgz # cd mongodb-1.3.0# /usr/local/php-fpm/bin/phpize Configuring for:PHP Api Version:         20131106Zend Module Api No:      20131226Zend Extension Api No:   220131226

  • 编译安装:
# ./configure --with-php-config=/usr/local/php-fpm/bin/php-config# echo $?0# make && make install# echo $?0# vim /usr/local/php-fpm/etc/php.ini#增加下面一行extension=mongodb.so# /usr/local/php-fpm/bin/php -m[PHP Modules]Corectypecurldatedomeregexiffileinfofilterftpgdhashiconvjsonlibxmlmbstringmcryptmongodb#有mongodb说明没问题mysqlopensslpcrePDOpdo_sqlitePharposixredisReflectionsessionSimpleXMLsoapSPLsqlite3standardtokenizerxmlxmlreaderxmlwriterzlib[Zend Modules]# /etc/init.d/php-fpm restartGracefully shutting down php-fpm  doneStarting php-fpm  done

安装mongo.so的步骤与上面基本相同,这里不做赘述。


MongoDB副本集

MongoDB也可以做主从配置。在早期,使用master-slave,一主一从和MySQL类似,但slave在此架构中为只读,当主库宕机后,从库不能自动切换为主。目前已经淘汰这种模式。

现在改为副本集,这种模式下,一主(primary)多从(secondary),从仍然只读。同时支持设置权重,当主宕掉后,权重最高的从自动切换为主。
此外,此架构中还可以建立一个仲裁(arbiter)的角色,只负责裁决主是否宕机,而不存储数据,也是为了防止脑裂。因为读写数据都是在主上,所以要想实现负载均衡,还需要手动指定读库的目标server。

  • 场景设置:
全部关闭防火墙和selinuxprimary192.168.100.150(主)secondary192.168.100.160(从1)secondary192.168.100.170(从2)


在主上进行操作

  • 修改配置文件:
# vim /etc/mongod.confport:27018bindIp: 127.0.0.1,192.168.100.150#本机内网IPreplication:  oplogSizeMB: 20#冒号后面记得空格,否则启动会报错  replSetName: lzx#定义副本集的名字# systemctl restart mongod# ps aux |grep mongodmongod     1510  8.0  1.4 1017096 46800 ?       Sl   21:21   0:00 /usr/bin/mongod --auth -f /etc/mongod.conf# vim /usr/lib/systemd/system/mongod.serviceEnvironment="OPTIONS=-f /etc/mongod.conf"#方便实验,去掉--auth# systemctl daemon-reload# systemctl restart mongod# ps aux |grep mongodmongod     1716 14.3  1.3 1017096 44488 ?       Sl   21:40   0:00 /usr/bin/mongod -f /etc/mongod.conf# netstat -lntp |grep mongodtcp        0      0 192.168.100.150:27018   0.0.0.0:*               LISTEN      1716/mongodtcp        0      0 127.0.0.1:27018         0.0.0.0:*               LISTEN      1716/mongod


在从1上进行操作

  • 修改配置文件:
# vim /etc/mongod.confport:27019bindIp: 127.0.0.1,192.168.100.160#本机内网IPreplication:  oplogSizeMB: 20  replSetName: lzx# vim /usr/lib/systemd/system/mongod.serviceEnvironment="OPTIONS=-f /etc/mongod.conf"# systemctl daemon-reload# systemctl restart mongod# ps aux |grep mongodmongod     2076 14.0  1.2 1017092 48488 ?       Sl   21:40   0:00 /usr/bin/mongod -f /etc/mongod.conf# netstat -lntp |grep mongodtcp        0      0 192.168.100.160:27019   0.0.0.0:*               LISTEN      2076/mongodtcp        0      0 127.0.0.1:27019         0.0.0.0:*               LISTEN      2076/mongod


在从2上进行操作

  • 修改配置文件:
# vim /etc/mongod.confport:27020bindIp: 127.0.0.1,192.168.100.170#本机内网IPreplication:  oplogSizeMB: 20  replSetName: lzx# vim /usr/lib/systemd/system/mongod.serviceEnvironment="OPTIONS=-f /etc/mongod.conf"# systemctl daemon-reload# systemctl restart mongod# ps aux |grep mongodmongod     2086 11.5  1.1 1017100 44588 ?       Sl   21:39   0:00 /usr/bin/mongod -f /etc/mongod.conf# netstat -lntp |grep mongodtcp        0      0 192.168.100.170:27020   0.0.0.0:*               LISTEN      2086/mongodtcp        0      0 127.0.0.1:27020         0.0.0.0:*               LISTEN      2086/mongod


再在主上进行操作

  • 连接主,在主上运行mongo:
# mongo --port 27018MongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27018MongoDB server version: 3.4.16Server has startup warnings: 2018-08-25T21:40:19.064+0800 I CONTROL  [initandlisten] 2018-08-25T21:40:19.064+0800 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.2018-08-25T21:40:19.064+0800 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.2018-08-25T21:40:19.064+0800 I CONTROL  [initandlisten] 2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] 2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] 2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-25T21:40:19.065+0800 I CONTROL  [initandlisten] > use adminswitched to db admin

  • 创建副本集:
> config={_id:"lzx",members:[{_id:0,host:"192.168.100.150:27018"},{_id:1,host:"192.168.100.160:27019"},{_id:2,host:"192.168.100.170:27020"}]}{"_id" : "lzx","members" : [{"_id" : 0,"host" : "192.168.100.150:27018"},{"_id" : 1,"host" : "192.168.100.160:27019"},{"_id" : 2,"host" : "192.168.100.170:27020"}]}> rs.initiate(config)#初始化副本集,必须要保证之前数据库中没有任何数据,否则报错{ "ok" : 1 }lzx:OTHER> rs.status()#查看副本集状态{"set" : "lzx","date" : ISODate("2018-08-26T09:29:41.449Z"),"myState" : 1,"term" : NumberLong(1),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"appliedOpTime" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"durableOpTime" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)}},"members" : [{"_id" : 0,"name" : "192.168.100.150:27018","health" : 1,"state" : 1,"stateStr" : "PRIMARY",#192.168.100.150是primary"uptime" : 268,"optime" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2018-08-26T09:29:36Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","electionTime" : Timestamp(1535275644, 1),"electionDate" : ISODate("2018-08-26T09:27:24Z"),"configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 1,"name" : "192.168.100.160:27019","health" : 1,"state" : 2,"stateStr" : "SECONDARY",#192.168.100.160是secondary"uptime" : 148,"optime" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"optimeDurable" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2018-08-26T09:29:36Z"),"optimeDurableDate" : ISODate("2018-08-26T09:29:36Z"),"lastHeartbeat" : ISODate("2018-08-26T09:29:40.721Z"),"lastHeartbeatRecv" : ISODate("2018-08-26T09:29:40.698Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "192.168.100.170:27020","syncSourceHost" : "192.168.100.170:27020","syncSourceId" : 2,"infoMessage" : "","configVersion" : 1},{"_id" : 2,"name" : "192.168.100.170:27020","health" : 1,"state" : 2,"stateStr" : "SECONDARY",#192.168.100.170是secondary"uptime" : 148,"optime" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"optimeDurable" : {"ts" : Timestamp(1535275776, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2018-08-26T09:29:36Z"),"optimeDurableDate" : ISODate("2018-08-26T09:29:36Z"),"lastHeartbeat" : ISODate("2018-08-26T09:29:40.721Z"),"lastHeartbeatRecv" : ISODate("2018-08-26T09:29:39.563Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "192.168.100.150:27018","syncSourceHost" : "192.168.100.150:27018","syncSourceId" : 0,"infoMessage" : "","configVersion" : 1}],"ok" : 1}

如果两个从上的状态为"stateStr":"STARTUP",则需要执行下面操作:

> var config={_id:"lzx",members:[{_id:0,host:"192.168.100.150:27018"},{_id:1,host:"192.168.100.160:27019"},{_id:2,host:"192.168.100.170:27020"}]}> rs.reconfig(config)

此时再次查看rs.status()会发现从的状态变为SECONDARY。如果没有PRIMARY,可以去增加权重,权重高的即为PRIMARY

  • 副本集测试:
lzx:PRIMARY> use mydbswitched to db mydblzx:PRIMARY> db.acc.insert({AccountID:1,UserName:"123",password:"123456"})#创建集合,插入数据WriteResult({ "nInserted" : 1 })lzx:PRIMARY> show dbsadmin  0.000GBlocal  0.000GBmydb   0.000GB#有mydb库lzx:PRIMARY> use mydbswitched to db mydblzx:PRIMARY> show tablesacc#有acc集合


在从1上进行操作

  • 查看刚刚主上创建的数据:
# mongo --port 27019MongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27019/MongoDB server version: 3.4.16Server has startup warnings: 2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] 2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] 2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] 2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] 2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-26T05:32:20.355-0400 I CONTROL  [initandlisten] lzx:SECONDARY> show dbs2018-08-26T05:58:31.215-0400 E QUERY    [thread1] Error: listDatabases failed:{"ok" : 0,"errmsg" : "not master and slaveOk=false",#有这样的报错信息"code" : 13435,"codeName" : "NotMasterNoSlaveOk"} :_getErrorWithCode@src/mongo/shell/utils.js:25:13Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1shellHelper.show@src/mongo/shell/utils.js:788:19shellHelper@src/mongo/shell/utils.js:678:15@(shellhelp2):1:1       lzx:SECONDARY> rs.slaveOk()#设置slaveOk=truelzx:SECONDARY> show dbsadmin  0.000GBlocal  0.000GBmydb   0.000GB#可以看到有mydb库lzx:SECONDARY> use mydbswitched to db mydblzx:SECONDARY> show tablesacc#可以看到有acc集合


在从2上进行操作

  • 查看刚刚主上创建的数据(与上面一致):
# mongo --port 27020MongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27020/MongoDB server version: 3.4.16Server has startup warnings: 2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2018-08-26T05:25:13.079-0400 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-26T05:25:13.080-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:13.080-0400 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2018-08-26T05:25:13.080-0400 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-26T05:25:13.080-0400 I CONTROL  [initandlisten]lzx:SECONDARY> show dbs2018-08-26T05:58:31.215-0400 E QUERY    [thread1] Error: listDatabases failed:{"ok" : 0,"errmsg" : "not master and slaveOk=false","code" : 13435,"codeName" : "NotMasterNoSlaveOk"} :_getErrorWithCode@src/mongo/shell/utils.js:25:13Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1shellHelper.show@src/mongo/shell/utils.js:788:19shellHelper@src/mongo/shell/utils.js:678:15@(shellhelp2):1:1       lzx:SECONDARY> rs.slaveOk()#设置slaveOk=truelzx:SECONDARY> show dbsadmin  0.000GBlocal  0.000GBmydb   0.000GB#可以看到有mydb库lzx:SECONDARY> use mydbswitched to db mydblzx:SECONDARY> show tablesacc#可以看到有acc集合


继续在主上进行操作:

  • 查看权重:
lzx:PRIMARY> rs.config(){"_id" : "lzx","version" : 1,"protocolVersion" : NumberLong(1),"members" : [{"_id" : 0,"host" : "192.168.100.150:27018","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,#权重为1"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 1,"host" : "192.168.100.160:27019","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,#权重为1"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 2,"host" : "192.168.100.170:27020","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,#权重为1"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1}],"settings" : {"chainingAllowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : 60000,"getLastErrorModes" : {},"getLastErrorDefaults" : {"w" : 1,"wtimeout" : 0},"replicaSetId" : ObjectId("5b827271b551f8b2b89e2ff0")}}

  • 增加防火墙规则,模拟宕机:
# iptables -I INPUT -p tcp --dport 27018 -j DROP

  • 在从1上面查看副本集状态:
lzx:SECONDARY> rs.status(){"set" : "lzx","date" : ISODate("2018-08-26T10:13:08.119Z"),"myState" : 2,"term" : NumberLong(2),"syncingTo" : "192.168.100.170:27020","syncSourceHost" : "192.168.100.170:27020","syncSourceId" : 2,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1535277967, 1),"t" : NumberLong(2)},"appliedOpTime" : {"ts" : Timestamp(1535277967, 1),"t" : NumberLong(2)},"durableOpTime" : {"ts" : Timestamp(1535277967, 1),"t" : NumberLong(2)}},"members" : [{"_id" : 0,"name" : "192.168.100.150:27018","health" : 0,"state" : 8,"stateStr" : "(not reachable/healthy)",#192.168.100.150变成不可达"uptime" : 0,"optime" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"optimeDurable" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"optimeDate" : ISODate("1970-01-01T00:00:00Z"),"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),"lastHeartbeat" : ISODate("2018-08-26T10:13:06.423Z"),"lastHeartbeatRecv" : ISODate("2018-08-26T10:13:07.227Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "Couldn't get a connection within the time limit","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : -1},{"_id" : 1,"name" : "192.168.100.160:27019","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 2449,"optime" : {"ts" : Timestamp(1535277967, 1),"t" : NumberLong(2)},"optimeDate" : ISODate("2018-08-26T10:06:07Z"),"syncingTo" : "192.168.100.170:27020","syncSourceHost" : "192.168.100.170:27020","syncSourceId" : 2,"infoMessage" : "","configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 2,"name" : "192.168.100.170:27020","health" : 1,"state" : 1,"stateStr" : "PRIMARY",#192.168.100.170变成primary"uptime" : 2344,"optime" : {"ts" : Timestamp(1535277967, 1),"t" : NumberLong(2)},"optimeDurable" : {"ts" : Timestamp(1535277967, 1),"t" : NumberLong(2)},"optimeDate" : ISODate("2018-08-26T10:06:07Z"),"optimeDurableDate" : ISODate("2018-08-26T10:06:07Z"),"lastHeartbeat" : ISODate("2018-08-26T10:13:06.469Z"),"lastHeartbeatRecv" : ISODate("2018-08-26T10:13:06.866Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","electionTime" : Timestamp(1535277926, 2),"electionDate" : ISODate("2018-08-26T10:05:26Z"),"configVersion" : 1}],"ok" : 1}

  • 在主上操作:删除规则,查看是否变回去:
# iptables -D INPUT -p tcp --dport 27018 -j DROP# mongo --port 27018MongoDB shell version v3.4.16connecting to: mongodb://127.0.0.1:27018/MongoDB server version: 3.4.16Server has startup warnings: 2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] 2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] **        We suggest setting it to 'never'2018-08-26T05:25:16.157-0400 I CONTROL  [initandlisten] lzx:SECONDARY>#192.168.100.150仍然是从,因为三者权重相等,除非它的权重最高才会变回primary


在从2上进行操作(因为是新的主)

  • 设置权重:
lzx:PRIMARY> cfg=rs.conf(){"_id" : "lzx","version" : 1,"protocolVersion" : NumberLong(1),"members" : [{"_id" : 0,"host" : "192.168.100.150:27018","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 1,"host" : "192.168.100.160:27019","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 2,"host" : "192.168.100.170:27020","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1}],"settings" : {"chainingAllowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : 60000,"getLastErrorModes" : {},"getLastErrorDefaults" : {"w" : 1,"wtimeout" : 0},"replicaSetId" : ObjectId("5b827271b551f8b2b89e2ff0")}}lzx:PRIMARY> cfg.members[0].priority = 3#设置成员0权重为33lzx:PRIMARY> cfg.members[1].priority = 2#设置成员1权重为22lzx:PRIMARY> cfg.members[2].priority = 1#设置成员2权重为11lzx:PRIMARY> rs.reconfig(cfg)#使上面权重设置生效{ "ok" : 1 }lzx:PRIMARY>#按Enter键2018-08-26T06:21:40.200-0400 I NETWORK  [thread1] trying reconnect to 127.0.0.1:27020 (127.0.0.1) failed2018-08-26T06:21:40.200-0400 I NETWORK  [thread1] reconnect 127.0.0.1:27020 (127.0.0.1) oklzx:SECONDARY>#从2由主变为从lzx:SECONDARY> rs.config()#查看权重{"_id" : "lzx","version" : 2,"protocolVersion" : NumberLong(1),"members" : [{"_id" : 0,"host" : "192.168.100.150:27018","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 3,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 1,"host" : "192.168.100.160:27019","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 2,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1},{"_id" : 2,"host" : "192.168.100.170:27020","arbiterOnly" : false,"buildIndexes" : true,"hidden" : false,"priority" : 1,"tags" : {},"slaveDelay" : NumberLong(0),"votes" : 1}],"settings" : {"chainingAllowed" : true,"heartbeatIntervalMillis" : 2000,"heartbeatTimeoutSecs" : 10,"electionTimeoutMillis" : 10000,"catchUpTimeoutMillis" : 60000,"getLastErrorModes" : {},"getLastErrorDefaults" : {"w" : 1,"wtimeout" : 0},"replicaSetId" : ObjectId("5b827271b551f8b2b89e2ff0")}}


MongoDB分片

分片就是将数据库进行拆分,将大型集合分割到不同服务器上。比如,本来100G的数据,可以分割成10份存储到10台服务器上,这样每台机器只有10G的数据。

分片后的数据存储与访问是由一个mongos的进程来实现的,即mongos是整个分片架构的核心。对客户端而言是透明的,客户端只需要把读写操作转达给mongos即可。

虽然分片会把数据分割到很多服务器上,但是每一个节点都需要有一个备用角色的,这样能保证数据的高可用。当系统需要更多空间或资源的时候,分片可以很方便地让我们按需扩展,只需要把mongodb服务的机器加入到分片集群中即可。

MongoDB分片相关概念:

mongos:数据库集群请求的入口,所有的请求都是通过mongos进行协调,不需要再应用程序中添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉而导致所有的mongodb请求都没有办法操作。config server:配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置放服务器则实际存储这些信息。mongos第一次启动或者关掉重启就会从配置服务器加载配置信息,以后如果配置服务器信息变化会通知到所有的mongos更新自己的状态,这样mongos就能继续准确路由。在生产环境通常有多个config server,因为它存储了分片路由的元数据,防止数据丢失。shard:存储了一个集合部分数据的mongodb实例,每个分片是单独的mongodb服务或者副本集,在生产环境中,所有的分片都应该是副本集。

  • 场景设置:
A:192.168.100.150B:192.168.100.160C:192.168.100.170 A搭建:mongos、config server、副本集1 主节点、副本集2 从节点、副本集3 仲裁B搭建:mongos、config server、副本集1 仲裁、副本集2 主节点、副本集3 从节点C搭建:mongos、config server、副本集1 从节点、副本集2 仲裁、副本集3 主节点端口分配:mongos 20000、config 21000、副本集1 27001、副本集2 27002、副本集3 27003分别在三台机器上创建各个角色所需要的目录:/data/mongodb/mongos/log/data/mongodb/config/{data,log}/data/mongodb/shard1/{data,log}/data/mongodb/shard2/{data,log}/data/mongodb/shard3/{data,log}三台机器全部关闭防火墙和SElinux,或者增加对应端口的规则


config server配置

在A机器上进行操作
  • 创建目录:
# mkdir -p /data/mongodb/mongos/log# mkdir -p /data/mongodb/config/{data,log}# mkdir -p /data/mongodb/shard1/{data,log}# mkdir -p /data/mongodb/shard2/{data,log}# mkdir -p /data/mongodb/shard3/{data,log}# mkdir /etc/mongod/

  • 修改配置文件:
# vim /etc/mongod/config.confpidfilepath = /var/run/mongodb/configsrv.piddbpath = /data/mongodb/config/datalogpath = /data/mongodb/config/log/configsrv.loglogappend = truebind_ip = 192.168.100.150port = 21000fork = trueconfigsvr = truereplSet=configs#副本集名称maxConns=20000#设置最大连接数

  • 启动服务:
# mongod -f /etc/mongod/config.conf about to fork child process, waiting until server is ready for connections.forked process: 10212child process started successfully, parent exiting# netstat -lntp |grep mongodtcp        0      0 192.168.100.150:21000    0.0.0.0:*               LISTEN      10212/mongodtcp        0      0 192.168.100.150:27018    0.0.0.0:*               LISTEN      10185/mongod        tcp        0      0 127.0.0.1:27018         0.0.0.0:*               LISTEN      10185/mongod

在B机器上进行操作
  • 创建目录:
# mkdir -p /data/mongodb/mongos/log# mkdir -p /data/mongodb/config/{data,log}# mkdir -p /data/mongodb/shard1/{data,log}# mkdir -p /data/mongodb/shard2/{data,log}# mkdir -p /data/mongodb/shard3/{data,log}# mkdir /etc/mongod/

  • 添加配置文件:
# vim /etc/mongod/config.confpidfilepath = /var/run/mongodb/configsrv.piddbpath = /data/mongodb/config/datalogpath = /data/mongodb/config/log/configsrv.loglogappend = truebind_ip = 192.168.100.160port = 21000fork = trueconfigsvr = truereplSet=configsmaxConns=20000

  • 启动服务:
# mongod -f /etc/mongod/config.confabout to fork child process, waiting until server is ready for connections.forked process: 10472child process started successfully, parent exiting# netstat -lntp |grep mongodtcp        0      0 192.168.100.160:27019    0.0.0.0:*               LISTEN      10446/mongod           tcp        0      0 127.0.0.1:27019         0.0.0.0:*               LISTEN      10446/mongod        tcp        0      0 192.168.100.160:21000    0.0.0.0:*               LISTEN      10472/mongod

在C机器上进行操作
  • 创建目录:
# mkdir -p /data/mongodb/mongos/log# mkdir -p /data/mongodb/config/{data,log}# mkdir -p /data/mongodb/shard1/{data,log}# mkdir -p /data/mongodb/shard2/{data,log}# mkdir -p /data/mongodb/shard3/{data,log}# mkdir /etc/mongod/

  • 修改配置文件:
# vim /etc/mongod/config.confpidfilepath = /var/run/mongodb/configsrv.piddbpath = /data/mongodb/config/datalogpath = /data/mongodb/config/log/configsrv.loglogappend = truebind_ip = 192.168.100.170port = 21000fork = trueconfigsvr = truereplSet=configsmaxConns=20000

  • 启动服务:
# mongod -f /etc/mongod/config.confabout to fork child process, waiting until server is ready for connections.forked process: 10444child process started successfully, parent exiting# netstat -lntp |grep mongodtcp        0      0 192.168.100.170:27020    0.0.0.0:*               LISTEN      10418/mongod        tcp        0      0 127.0.0.1:27020         0.0.0.0:*               LISTEN      10418/mongod        tcp        0      0 192.168.100.170:21000    0.0.0.0:*               LISTEN      10444/mongod

创建副本集

三台机器都已经启动服务,由于他们权重都一样,所以可以任选一台机器来创建副本集。下面我在A机器上操作。

  • 创建并初始化副本集:
# mongo --host 192.168.100.150 --port 21000> use adminswitched to db admin> config={_id:"configs",members:[{_id:0,host:"192.168.100.150:21000"},{_id:1,host:"192.168.100.160:21000"},{_id:2,host:"192.168.100.170:21000"}]}{"_id" : "configs","members" : [{"_id" : 0,"host" : "192.168.100.150:21000"},{"_id" : 1,"host" : "192.168.100.160:21000"},{"_id" : 2,"host" : "192.168.100.170:21000"}]}> rs.initiate(config)#初始化副本集{ "ok" : 1 }configs:OTHER> rs.status()#查看副本集状态{"set" : "configs","date" : ISODate("2018-08-27T05:28:33.632Z"),"myState" : 1,"term" : NumberLong(1),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"configsvr" : true,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"readConcernMajorityOpTime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"appliedOpTime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"durableOpTime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)}},"members" : [{"_id" : 0,"name" : "192.168.100.150:21000","health" : 1,"state" : 1,"stateStr" : "PRIMARY",#192.168.100.150是primary"uptime" : 1163,"optime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2018-08-27T05:28:14Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "could not find member to sync from","electionTime" : Timestamp(1535347692, 1),"electionDate" : ISODate("2018-08-27T05:28:12Z"),"configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 1,"name" : "192.168.100.160:21000","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 32,"optime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"optimeDurable" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2018-08-27T05:28:14Z"),"optimeDurableDate" : ISODate("2018-08-27T05:28:14Z"),"lastHeartbeat" : ISODate("2018-08-27T05:28:32.620Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T05:28:31.678Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "192.168.100.170:21000","syncSourceHost" : "192.168.100.170:21000","syncSourceId" : 2,"infoMessage" : "","configVersion" : 1},{"_id" : 2,"name" : "192.168.100.170:21000","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 32,"optime" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"optimeDurable" : {"ts" : Timestamp(1535347694, 1),"t" : NumberLong(1)},"optimeDate" : ISODate("2018-08-27T05:28:14Z"),"optimeDurableDate" : ISODate("2018-08-27T05:28:14Z"),"lastHeartbeat" : ISODate("2018-08-27T05:28:32.620Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T05:28:32.763Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "192.168.100.150:21000","syncSourceHost" : "192.168.100.150:21000","syncSourceId" : 0,"infoMessage" : "","configVersion" : 1}],"ok" : 1}

至此,config server配置完毕。


shard配置

在A机器上进行操作
  • 添加配置文件:
# vim /etc/mongod/shard1.confpidfilepath = /var/run/mongodb/shard1.piddbpath = /data/mongodb/shard1/datalogpath = /data/mongodb/shard1/log/shard1.loglogappend = truebind_ip = 192.168.100.150port = 27001fork = truehttpinterface=true#打开web监控rest=truereplSet=shard1#副本集名称shardsvr = true        maxConns=20000#设置最大连接数

# cd /etc/mongod/# cp shard1.conf shard2.conf# cp shard1.conf shard3.conf# vim shard2.confpidfilepath = /var/run/mongodb/shard2.piddbpath = /data/mongodb/shard2/datalogpath = /data/mongodb/shard2/log/shard2.loglogappend = truebind_ip = 192.168.100.150port = 27002#注意更改端口fork = truehttpinterface=truerest=truereplSet=shard2         shardsvr = truemaxConns=20000

# vim shard3.confpidfilepath = /var/run/mongodb/shard3.piddbpath = /data/mongodb/shard3/datalogpath = /data/mongodb/shard3/log/shard3.loglogappend = truebind_ip = 192.168.100.150port = 27003#注意更改端口fork = truehttpinterface=truerest=truereplSet=shard3         shardsvr = truemaxConns=20000

  • 启动服务:
# mongod -f /etc/mongod/shard1.conf about to fork child process, waiting until server is ready for connections.forked process: 10387child process started successfully, parent exiting# mongod -f /etc/mongod/shard2.conf about to fork child process, waiting until server is ready for connections.forked process: 10417child process started successfully, parent exiting# mongod -f /etc/mongod/shard3.conf about to fork child process, waiting until server is ready for connections.forked process: 10446child process started successfully, parent exiting# netstat -lntp |grep mongodtcp        0      0 192.168.100.150:27001    0.0.0.0:*               LISTEN      10387/mongod        tcp        0      0 192.168.100.150:27002    0.0.0.0:*               LISTEN      10417/mongod        tcp        0      0 192.168.100.150:27003    0.0.0.0:*               LISTEN      10446/mongod        tcp        0      0 192.168.100.150:28001    0.0.0.0:*               LISTEN      10387/mongod        tcp        0      0 192.168.100.150:28002    0.0.0.0:*               LISTEN      10417/mongod        tcp        0      0 192.168.100.150:28003    0.0.0.0:*               LISTEN      10446/mongod        tcp        0      0 192.168.100.150:21000    0.0.0.0:*               LISTEN      10212/mongod        tcp        0      0 192.168.100.150:27018    0.0.0.0:*               LISTEN      10185/mongod        tcp        0      0 127.0.0.1:27018         0.0.0.0:*               LISTEN      10185/mongod

在B机器上进行操作
  • 添加配置文件:
# vim /etc/mongod/shard1.confpidfilepath = /var/run/mongodb/shard1.piddbpath = /data/mongodb/shard1/datalogpath = /data/mongodb/shard1/log/shard1.loglogappend = truebind_ip = 192.168.100.160port = 27001fork = truehttpinterface=truerest=truereplSet=shard1shardsvr = true        maxConns=20000

# cd /etc/mongod/# cp shard1.conf shard2.conf# cp shard1.conf shard3.conf# vim shard2.confpidfilepath = /var/run/mongodb/shard2.piddbpath = /data/mongodb/shard2/datalogpath = /data/mongodb/shard2/log/shard2.loglogappend = truebind_ip = 192.168.100.160port = 27002fork = truehttpinterface=truerest=truereplSet=shard2         shardsvr = truemaxConns=20000

# vim shard3.confpidfilepath = /var/run/mongodb/shard3.piddbpath = /data/mongodb/shard3/datalogpath = /data/mongodb/shard3/log/shard3.loglogappend = truebind_ip = 192.168.100.160port = 27003fork = truehttpinterface=truerest=truereplSet=shard3         shardsvr = truemaxConns=20000

  • 启动服务:
# mongod -f /etc/mongod/shard1.conf about to fork child process, waiting until server is ready for connections.forked process: 10795child process started successfully, parent exiting# mongod -f /etc/mongod/shard2.conf about to fork child process, waiting until server is ready for connections.forked process: 10824child process started successfully, parent exiting# mongod -f /etc/mongod/shard3.conf about to fork child process, waiting until server is ready for connections.forked process: 10853child process started successfully, parent exiting# netstat -lntp |grep mongodtcp        0      0 192.168.100.160:27019    0.0.0.0:*               LISTEN      10446/mongod        tcp        0      0 127.0.0.1:27019         0.0.0.0:*               LISTEN      10446/mongod        tcp        0      0 192.168.100.160:27001    0.0.0.0:*               LISTEN      10795/mongod        tcp        0      0 192.168.100.160:27002    0.0.0.0:*               LISTEN      10824/mongod        tcp        0      0 192.168.100.160:27003    0.0.0.0:*               LISTEN      10853/mongod        tcp        0      0 192.168.100.160:28001    0.0.0.0:*               LISTEN      10795/mongod        tcp        0      0 192.168.100.160:28002    0.0.0.0:*               LISTEN      10824/mongod        tcp        0      0 192.168.100.160:28003    0.0.0.0:*               LISTEN      10853/mongod        tcp        0      0 192.168.100.160:21000    0.0.0.0:*               LISTEN      10472/mongod

在C机器上进行操作
  • 添加配置文件:
# vim /etc/mongod/shard1.confpidfilepath = /var/run/mongodb/shard1.piddbpath = /data/mongodb/shard1/datalogpath = /data/mongodb/shard1/log/shard1.loglogappend = truebind_ip = 192.168.100.170port = 27001fork = truehttpinterface=truerest=truereplSet=shard1shardsvr = true        maxConns=20000

# cd /etc/mongod/# cp shard1.conf shard2.conf# cp shard1.conf shard3.conf# vim shard2.confpidfilepath = /var/run/mongodb/shard2.piddbpath = /data/mongodb/shard2/datalogpath = /data/mongodb/shard2/log/shard2.loglogappend = truebind_ip = 192.168.100.170port = 27002fork = truehttpinterface=truerest=truereplSet=shard2         shardsvr = truemaxConns=20000

# vim shard3.confpidfilepath = /var/run/mongodb/shard3.piddbpath = /data/mongodb/shard3/datalogpath = /data/mongodb/shard3/log/shard3.loglogappend = truebind_ip = 192.168.100.170port = 27003fork = truehttpinterface=truerest=truereplSet=shard3         shardsvr = truemaxConns=20000

  • 启动服务:
# mongod -f /etc/mongod/shard1.conf about to fork child process, waiting until server is ready for connections.forked process: 10607child process started successfully, parent exiting# mongod -f /etc/mongod/shard2.conf about to fork child process, waiting until server is ready for connections.forked process: 10636child process started successfully, parent exiting# mongod -f /etc/mongod/shard3.conf about to fork child process, waiting until server is ready for connections.forked process: 10665child process started successfully, parent exiting# netstat -lntp |grep mongodtcp        0      0 192.168.100.170:27020    0.0.0.0:*               LISTEN      10418/mongod        tcp        0      0 127.0.0.1:27020         0.0.0.0:*               LISTEN      10418/mongod        tcp        0      0 192.168.100.170:27001    0.0.0.0:*               LISTEN      10607/mongod        tcp        0      0 192.168.100.170:27002    0.0.0.0:*               LISTEN      10636/mongod        tcp        0      0 192.168.100.170:27003    0.0.0.0:*               LISTEN      10665/mongod        tcp        0      0 192.168.100.170:28001    0.0.0.0:*               LISTEN      10607/mongod        tcp        0      0 192.168.100.170:28002    0.0.0.0:*               LISTEN      10636/mongod        tcp        0      0 192.168.100.170:28003    0.0.0.0:*               LISTEN      10665/mongod        tcp        0      0 192.168.100.170:21000    0.0.0.0:*               LISTEN      10444/mongod

创建副本集

因为每个分片里面都有仲裁节点,而仲裁节点不能作为登录入口,所以只能选择非仲裁节点登录进行操作。

针对shard1,我使用A机器登录操作。

  • 创建并初始化副本集shard1:
# mongo --host 192.168.100.150 --port 27001> use adminswitched to db admin> config={_id:"shard1",members:[{_id:0,host:"192.168.100.150:27001"},{_id:1,host:"192.168.100.160:27001"},{_id:2,host:"192.168.100.170:27001",arbiterOnly:true}]}        //192.168.100.170作为仲裁节点  {"_id" : "shard1","members" : [{"_id" : 0,"host" : "192.168.100.150:27001"},{"_id" : 1,"host" : "192.168.100.160:27001"},{"_id" : 2,"host" : "192.168.100.170:27001","arbiterOnly" : true}]}> rs.initiate(config)#初始化副本集{ "ok" : 1 }shard1:OTHER> rs.status(){"set" : "shard1","date" : ISODate("2018-08-27T04:45:50.273Z"),"myState" : 2,"term" : NumberLong(0),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"appliedOpTime" : {"ts" : Timestamp(1535345139, 1),"t" : NumberLong(-1)},"durableOpTime" : {"ts" : Timestamp(1535345139, 1),"t" : NumberLong(-1)}},"members" : [{"_id" : 0,"name" : "192.168.100.150:27001","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 828,"optime" : {"ts" : Timestamp(1535345139, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2018-08-27T04:45:39Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "could not find member to sync from","configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 1,"name" : "192.168.100.160:27001","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 10,"optime" : {"ts" : Timestamp(1535345139, 1),"t" : NumberLong(-1)},"optimeDurable" : {"ts" : Timestamp(1535345139, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2018-08-27T04:45:39Z"),"optimeDurableDate" : ISODate("2018-08-27T04:45:39Z"),"lastHeartbeat" : ISODate("2018-08-27T04:45:49.984Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T04:45:47.086Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 1},{"_id" : 2,"name" : "192.168.100.170:27001","health" : 1,"state" : 7,"stateStr" : "ARBITER",#仲裁节点"uptime" : 10,"lastHeartbeat" : ISODate("2018-08-27T04:45:49.984Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T04:45:46.960Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 1}],"ok" : 1}shard1:SECONDARY>#多按几次Enter键shard1:PRIMARY>#自动变为primary,再次rs.status()就能看到

针对shard2,我使用B机器登录操作。

  • 创建并初始化副本集shard2:
# mongo --host 192.168.100.160 --port 27002> use adminswitched to db admin> config={_id:"shard2",members:[{_id:0,host:"192.168.100.150:27002",arbiterOnly:true},{_id:1,host:"192.168.100.160:27002"},{_id:2,host:"192.168.100.170:27002"}]}{"_id" : "shard2","members" : [{"_id" : 0,"host" : "192.168.100.150:27002","arbiterOnly" : true},{"_id" : 1,"host" : "192.168.100.160:27002"},{"_id" : 2,"host" : "192.168.100.170:27002"}]}> rs.initiate(config){ "ok" : 1 }shard2:OTHER> rs.status(){"set" : "shard2","date" : ISODate("2018-08-27T12:28:23.263Z"),"myState" : 2,"term" : NumberLong(0),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"appliedOpTime" : {"ts" : Timestamp(1535372897, 1),"t" : NumberLong(-1)},"durableOpTime" : {"ts" : Timestamp(1535372897, 1),"t" : NumberLong(-1)}},"members" : [{"_id" : 0,"name" : "192.168.100.150:27002","health" : 1,"state" : 7,"stateStr" : "ARBITER","uptime" : 6,"lastHeartbeat" : ISODate("2018-08-27T12:28:22.126Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T12:28:19.097Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 1},{"_id" : 1,"name" : "192.168.100.160:27002","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 987,"optime" : {"ts" : Timestamp(1535372897, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2018-08-27T12:28:17Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "could not find member to sync from","configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""},{"_id" : 2,"name" : "192.168.100.170:27002","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 6,"optime" : {"ts" : Timestamp(1535372897, 1),"t" : NumberLong(-1)},"optimeDurable" : {"ts" : Timestamp(1535372897, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2018-08-27T12:28:17Z"),"optimeDurableDate" : ISODate("2018-08-27T12:28:17Z"),"lastHeartbeat" : ISODate("2018-08-27T12:28:22.126Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T12:28:19.236Z"),"pingMs" : NumberLong(0),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 1}],"ok" : 1}shard2:SECONDARY>#多按几次Enter键shard2:PRIMARY>#自动变为primary,再次rs.status()就能看到

针对shard3,我使用C机器登录操作。

  • 创建并初始化副本集shard3:
# mongo --host 192.168.100.170 --port 27003> use adminswitched to db admin> config={_id:"shard3",members:[{_id:0,host:"192.168.100.150:27003"},{_id:1,host:"192.168.100.160:27003",arbiterOnly:true},{_id:2,host:"192.168.100.170:27003"}]}{"_id" : "shard3","members" : [{"_id" : 0,"host" : "192.168.100.150:27003"},{"_id" : 1,"host" : "192.168.100.160:27003","arbiterOnly" : true},{"_id" : 2,"host" : "192.168.100.170:27003"}]}> rs.initiate(config){ "ok" : 1 }shard3:OTHER> rs.status(){"set" : "shard3","date" : ISODate("2018-08-27T12:32:53.016Z"),"myState" : 2,"term" : NumberLong(0),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"heartbeatIntervalMillis" : NumberLong(2000),"optimes" : {"lastCommittedOpTime" : {"ts" : Timestamp(0, 0),"t" : NumberLong(-1)},"appliedOpTime" : {"ts" : Timestamp(1535373164, 1),"t" : NumberLong(-1)},"durableOpTime" : {"ts" : Timestamp(1535373164, 1),"t" : NumberLong(-1)}},"members" : [{"_id" : 0,"name" : "192.168.100.150:27003","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 8,"optime" : {"ts" : Timestamp(1535373164, 1),"t" : NumberLong(-1)},"optimeDurable" : {"ts" : Timestamp(1535373164, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2018-08-27T12:32:44Z"),"optimeDurableDate" : ISODate("2018-08-27T12:32:44Z"),"lastHeartbeat" : ISODate("2018-08-27T12:32:49.921Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T12:32:48.571Z"),"pingMs" : NumberLong(1),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 1},{"_id" : 1,"name" : "192.168.100.160:27003","health" : 1,"state" : 7,"stateStr" : "ARBITER","uptime" : 8,"lastHeartbeat" : ISODate("2018-08-27T12:32:49.921Z"),"lastHeartbeatRecv" : ISODate("2018-08-27T12:32:52.646Z"),"pingMs" : NumberLong(1),"lastHeartbeatMessage" : "","syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "","configVersion" : 1},{"_id" : 2,"name" : "192.168.100.170:27003","health" : 1,"state" : 2,"stateStr" : "SECONDARY","uptime" : 1067,"optime" : {"ts" : Timestamp(1535373164, 1),"t" : NumberLong(-1)},"optimeDate" : ISODate("2018-08-27T12:32:44Z"),"syncingTo" : "","syncSourceHost" : "","syncSourceId" : -1,"infoMessage" : "could not find member to sync from","configVersion" : 1,"self" : true,"lastHeartbeatMessage" : ""}],"ok" : 1}shard3:SECONDARY>#多按几次Enter键shard3:PRIMARY>#自动变为primary,再次rs.status()就能看到

至此,shard配置完毕。


mongos配置

为什么要将mongos放在最后配置,是因为mongos要想启动起来,它必须要知道config server和shard是谁。

在A机器上进行操作
  • 添加配置文件:
# vim /etc/mongod/mongos.confpidfilepath = /var/run/mongodb/mongospidlogpath = /data/mongodb/mongos/log/mongos.loglogappend = truebind_ip = 192.168.100.150port = 20000fork = trueconfigdb = configs/192.168.100.150:21000,192.168.100.160:21000,192.168.100.170:21000maxConns=20000

  • 启动服务:
# mongos -f /etc/mongod/mongos.conf#注意,之前是mongod,这里是mongosabout to fork child process, waiting until server is ready for connections.forked process: 1562child process started successfully, parent exiting# netstat -lntp |grep mongostcp        0      0 192.168.100.150:20000    0.0.0.0:*               LISTEN      1562/mongos

在B机器上进行操作
  • 添加配置文件:
# vim /etc/mongod/mongos.confpidfilepath = /var/run/mongodb/mongospidlogpath = /data/mongodb/mongos/log/mongos.loglogappend = truebind_ip = 192.168.100.160port = 20000fork = trueconfigdb = configs/192.168.100.150:21000,192.168.100.160:21000,192.168.100.170:21000maxConns=20000

  • 启动服务:
# mongos -f /etc/mongod/mongos.confabout to fork child process, waiting until server is ready for connections.forked process: 1550child process started successfully, parent exiting# netstat -lntp |grep mongostcp        0      0 192.168.100.160:20000   0.0.0.0:*               LISTEN      1550/mongos

在C机器上进行操作
  • 添加配置文件:
# vim /etc/mongod/mongos.confpidfilepath = /var/run/mongodb/mongospidlogpath = /data/mongodb/mongos/log/mongos.loglogappend = truebind_ip = 192.168.100.170port = 20000fork = trueconfigdb = configs/192.168.100.150:21000,192.168.100.160:21000,192.168.100.170:21000maxConns=20000

  • 启动服务:
# mongos -f /etc/mongod/mongos.conf about to fork child process, waiting until server is ready for connections.forked process: 1559child process started successfully, parent exiting# netstat -lntp |grep mongostcp        0      0 192.168.100.170:20000   0.0.0.0:*               LISTEN      1559/mongos

至此,mongos配置完毕。


启用分片

现在就要启用分片,把所有分片和mongos(路由器)串联起来。任选一台机器操作,这里我使用A机器进行操作。

  • 登录mongos启用分片:
# mongo --host 192.168.100.150 --port 20000#登录mongosMongoDB shell version v3.4.16connecting to: mongodb://192.168.100.150:20000/MongoDB server version: 3.4.16Server has startup warnings: 2018-08-27T08:55:48.279-0400 I CONTROL  [main] 2018-08-27T08:55:48.279-0400 I CONTROL  [main] ** WARNING: Access control is not enabled for the database.2018-08-27T08:55:48.279-0400 I CONTROL  [main] **          Read and write access to data and configuration is unrestricted.2018-08-27T08:55:48.279-0400 I CONTROL  [main] ** WARNING: You are running this process as the root user, which is not recommended.2018-08-27T08:55:48.279-0400 I CONTROL  [main] #把shard1分片和mongos串联起来mongos> sh.addShard("shard1/192.168.100.150:27001,192.168.100.160:27001,192.168.100.170:27001"){ "shardAdded" : "shard1", "ok" : 1 }#把shard2分片和mongos串联起来mongos> sh.addShard("shard2/192.168.100.150:27002,192.168.100.160:27002,192.168.100.170:27002"){ "shardAdded" : "shard2", "ok" : 1 }#把shard3分片和mongos串联起来mongos> sh.addShard("shard3/192.168.100.150:27003,192.168.100.160:27003,192.168.100.170:27003"){ "shardAdded" : "shard3", "ok" : 1 }mongos> sh.status()#查看分片状态--- Sharding Status ---   sharding version: {  "_id" : 1,  "minCompatibleVersion" : 5,  "currentVersion" : 6,  "clusterId" : ObjectId("5b83e28d28d74224a9920642")  }  shards:        {  "_id" : "shard1",  "host" : "shard1/192.168.100.150:27001,192.168.100.160:27001",  "state" : 1 }        {  "_id" : "shard2",  "host" : "shard2/192.168.100.160:27002,192.168.100.170:27002",  "state" : 1 }        {  "_id" : "shard3",  "host" : "shard3/192.168.100.150:27003,192.168.100.170:27003",  "state" : 1 }  active mongoses:        "3.4.16" : 1  autosplit:        Currently enabled: yes  balancer:        Currently enabled:  yes        Currently running:  noNaN        Failed balancer rounds in last 5 attempts:  0        Migration Results for the last 24 hours:                 No recent migrations  databases:

分片启用完成。


分片测试

现在进行分片测试,任选一台机器操作,这里我选择A机器进行操作。

  • 登录mongos进行测试:
# mongo --host 192.168.100.150 --port 20000mongos> use adminswitched to db admin#指定要分片的数据,db.runCommand({enablesharding:"testdb"}) 也可以实现mongos> sh.enableSharding("testdb"){ "ok" : 1 }#指定数据库里需要分片的集合和片键,db.runCommand({shardcollection:"testdb.table1",key:{id:1}}) 也可以实现mongos> sh.shardCollection("testdb.table1",{"id":1}){ "collectionsharded" : "testdb.table1", "ok" : 1 }mongos> use testdbswitched to db testdbmongos> for (var i = 1; i <= 10000; i++) db.table1.save({id:1,"test1":"testval1"})#插入测试数据,10000条WriteResult({ "nInserted" : 1 })mongos> show dbsadmin   0.000GBconfig  0.001GBtestdb  0.000GBmongos> sh.status()--- Sharding Status ---   sharding version: {  "_id" : 1,  "minCompatibleVersion" : 5,  "currentVersion" : 6,  "clusterId" : ObjectId("5b83e28d28d74224a9920642")  }  shards:        {  "_id" : "shard1",  "host" : "shard1/192.168.100.150:27001,192.168.100.160:27001",  "state" : 1 }        {  "_id" : "shard2",  "host" : "shard2/192.168.100.160:27002,192.168.100.170:27002",  "state" : 1 }        {  "_id" : "shard3",  "host" : "shard3/192.168.100.150:27003,192.168.100.170:27003",  "state" : 1 }  active mongoses:        "3.4.16" : 1  autosplit:        Currently enabled: yes  balancer:        Currently enabled:  yes        Currently running:  noNaN        Failed balancer rounds in last 5 attempts:  0        Migration Results for the last 24 hours:                 No recent migrations  databases:        {  "_id" : "testdb",  "primary" : "shard2",  "partitioned" : true }                testdb.table1#有刚刚创建的数据                        shard key: { "id" : 1 }                        unique: false                        balancing: true                        chunks:                                shard21#刚刚创建的testdb.table1在shard2里面                        { "id" : { "$minKey" : 1 } } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(1, 0)

  • 再创建一个库:
mongos> sh.enableSharding("db2"){ "ok" : 1 }mongos> sh.shardCollection("db2.col2",{"id":1}){ "collectionsharded" : "db2.col2", "ok" : 1 }mongos> sh.status()--- Sharding Status ---   sharding version: {  "_id" : 1,  "minCompatibleVersion" : 5,  "currentVersion" : 6,  "clusterId" : ObjectId("5b83e28d28d74224a9920642")  }  shards:        {  "_id" : "shard1",  "host" : "shard1/192.168.100.150:27001,192.168.100.160:27001",  "state" : 1 }        {  "_id" : "shard2",  "host" : "shard2/192.168.100.160:27002,192.168.100.170:27002",  "state" : 1 }        {  "_id" : "shard3",  "host" : "shard3/192.168.100.150:27003,192.168.100.170:27003",  "state" : 1 }  active mongoses:        "3.4.16" : 1  autosplit:        Currently enabled: yes  balancer:        Currently enabled:  yes        Currently running:  noNaN        Failed balancer rounds in last 5 attempts:  0        Migration Results for the last 24 hours:                 No recent migrations  databases:        {  "_id" : "testdb",  "primary" : "shard2",  "partitioned" : true }                testdb.table1                        shard key: { "id" : 1 }                        unique: false                        balancing: true                        chunks:                                shard21                        { "id" : { "$minKey" : 1 } } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(1, 0)         {  "_id" : "db2",  "primary" : "shard1",  "partitioned" : true }                db2.col2#刚刚创建的db2.col2                        shard key: { "id" : 1 }                        unique: false                        balancing: true                        chunks:                                shard11#在shard1里面                        { "id" : { "$minKey" : 1 } } -->> { "id" : { "$maxKey" : 1 } } on : shard1 Timestamp(1, 0)

  • 再创建一个库:
mongos> sh.enableSharding("db3"){ "ok" : 1 }mongos> sh.shardCollection("db3.col3",{"id":1}){ "collectionsharded" : "db3.col3", "ok" : 1 }mongos> sh.status()--- Sharding Status ---   sharding version: {  "_id" : 1,  "minCompatibleVersion" : 5,  "currentVersion" : 6,  "clusterId" : ObjectId("5b83e28d28d74224a9920642")  }  shards:        {  "_id" : "shard1",  "host" : "shard1/192.168.100.150:27001,192.168.100.160:27001",  "state" : 1 }        {  "_id" : "shard2",  "host" : "shard2/192.168.100.160:27002,192.168.100.170:27002",  "state" : 1 }        {  "_id" : "shard3",  "host" : "shard3/192.168.100.150:27003,192.168.100.170:27003",  "state" : 1 }  active mongoses:        "3.4.16" : 1  autosplit:        Currently enabled: yes  balancer:        Currently enabled:  yes        Currently running:  noNaN        Failed balancer rounds in last 5 attempts:  0        Migration Results for the last 24 hours:                 No recent migrations  databases:        {  "_id" : "testdb",  "primary" : "shard2",  "partitioned" : true }                testdb.table1                        shard key: { "id" : 1 }                        unique: false                        balancing: true                        chunks:                                shard21                        { "id" : { "$minKey" : 1 } } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(1, 0)         {  "_id" : "db2",  "primary" : "shard1",  "partitioned" : true }                db2.col2                        shard key: { "id" : 1 }                        unique: false                        balancing: true                        chunks:                                shard11                        { "id" : { "$minKey" : 1 } } -->> { "id" : { "$maxKey" : 1 } } on : shard1 Timestamp(1, 0)         {  "_id" : "db3",  "primary" : "shard3",  "partitioned" : true }                db3.col3#刚刚创建的db3.col3                        shard key: { "id" : 1 }                        unique: false                        balancing: true                        chunks:                                shard31#在shard3上面                        { "id" : { "$minKey" : 1 } } -->> { "id" : { "$maxKey" : 1 } } on : shard3 Timestamp(1, 0)

可以看到数据是在三个分片上均衡存储的。这其实也不够明显,因为数据量不够庞大。当生产环境下数据量很庞大的时候,3个分片上面的数据就会很平均。


MongoDB备份和恢复

任选一台机器操作,下面在A机器上进行操作。

  • 备份指定库:
# mkdir /tmp/mongobak; mongodump --host 192.168.100.150 --port 20000 -d testdb -o /tmp/mongobak#-d 指定备份的数据库;-o 指定存储的位置,这里如果不先创建存储位置目录,就无法备份2018-08-27T09:44:58.747-0400writing testdb.table1 to 2018-08-27T09:44:58.808-0400done dumping testdb.table1 (10000 documents)# ls /tmp/mongobak/testdb# ls /tmp/mongobak/testdb/table1.bson  table1.metadata.json# cd !$cd /tmp/mongobak/testdb/# du -sh *528Ktable1.bson4.0Ktable1.metadata.json# cat table1.metadata.json         {"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"testdb.table1"},{"v":2,"key":{"id":1.0},"name":"id_1","ns":"testdb.table1"}]}#有刚刚创建的testdb.table1,有所记录

  • 备份所有库:
# mongodump --host 192.168.100.150 --port 20000  -o /tmp/mongobak#不使用-d 指定库,就会备份所有库;这里存储位置的目录不存在也会自动创建2018-08-27T09:52:22.762-0400writing admin.system.version to 2018-08-27T09:52:22.764-0400done dumping admin.system.version (1 document)2018-08-27T09:52:22.764-0400writing testdb.table1 to 2018-08-27T09:52:22.764-0400writing config.lockpings to 2018-08-27T09:52:22.764-0400writing config.changelog to 2018-08-27T09:52:22.764-0400writing config.locks to 2018-08-27T09:52:22.771-0400done dumping config.lockpings (11 documents)2018-08-27T09:52:22.771-0400writing config.chunks to 2018-08-27T09:52:22.776-0400done dumping config.changelog (9 documents)2018-08-27T09:52:22.776-0400writing config.collections to 2018-08-27T09:52:22.778-0400done dumping config.collections (3 documents)2018-08-27T09:52:22.778-0400writing config.databases to 2018-08-27T09:52:22.781-0400done dumping config.locks (7 documents)2018-08-27T09:52:22.781-0400writing config.shards to 2018-08-27T09:52:22.782-0400done dumping config.shards (3 documents)2018-08-27T09:52:22.782-0400writing config.mongos to 2018-08-27T09:52:22.785-0400done dumping config.mongos (2 documents)2018-08-27T09:52:22.785-0400writing config.version to 2018-08-27T09:52:22.786-0400done dumping config.version (1 document)2018-08-27T09:52:22.786-0400writing config.tags to 2018-08-27T09:52:22.789-0400done dumping config.tags (0 documents)2018-08-27T09:52:22.789-0400writing config.migrations to 2018-08-27T09:52:22.790-0400done dumping config.migrations (0 documents)2018-08-27T09:52:22.790-0400writing db2.col2 to 2018-08-27T09:52:22.795-0400done dumping config.databases (3 documents)2018-08-27T09:52:22.795-0400writing db3.col3 to 2018-08-27T09:52:22.797-0400done dumping config.chunks (3 documents)2018-08-27T09:52:22.799-0400done dumping db2.col2 (0 documents)2018-08-27T09:52:22.800-0400done dumping db3.col3 (0 documents)2018-08-27T09:52:22.941-0400done dumping testdb.table1 (10000 documents)# cd ..# ls         admin  config  db2  db3  testdb#每一个目录代表一个库

  • 备份指定集合:
# mongodump --host 192.168.100.150 --port 20000 -d testdb -c table1 -o /tmp/mongobak1#-c 指定备份的集合2018-08-27T09:57:12.795-0400writing testdb.table1 to 2018-08-27T09:57:12.840-0400done dumping testdb.table1 (10000 documents)# ls !$ls /tmp/mongobak1testdb# ls /tmp/mongobak1/testdb/table1.bson  table1.metadata.json

  • 导出集合为json文件:
# mongoexport --host 192.168.100.150 --port 20000 -d testdb -c table1 -o /tmp/table1.json#mongoexport表示导出,-o 指定存储文件,不存在会自动创建2018-08-27T10:01:34.462-0400connected to: 192.168.100.150:200002018-08-27T10:01:34.610-0400exported 10000 records# vim !$vim /tmp/table1.json{"_id":{"$oid":"5b83fb338c1de6b83f6a11ab"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11ac"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11ad"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11ae"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11af"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11b0"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11b1"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11b2"},"id":1.0,"test1":"testval1"}{"_id":{"$oid":"5b83fb338c1de6b83f6a11b3"},"id":1.0,"test1":"testval1"}#这里就是我们之前插入的10000条数据,不是乱码

  • 恢复指定库:
# mongorestore --host 192.168.100.150 --port 20000 -d mydb dir#-d 后跟要恢复的库,dir表示该库备份时所在的目录

  • 恢复所有库:
# mongorestore --host 192.168.100.150 --port 20000  dir#dir表示该库备份时所在的目录

  • 恢复集合:
# mongorestore --host 192.168.100.150 --port 20000 -d mydb  -c tab1 dir#-c 后跟要恢复的库的集合,dir表示该集合备份时所在的目录

  • 导入集合:
# mongoimport --host 192.168.100.150 --port 20000 -d testdb -c table1 --file /tmp/table1.json#mongoexport表示导出,--file指定导入文件


更多资料参考:

安全部署MongoDB最佳实践

mongo执行js脚本

©著作权归作者所有:来自51CTO博客作者80民工的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. Map集合封装获取参数
  2. List集合封装获取参数
  3. 怎么在java中创建一个自定义的collector
  4. 初学Redis最清晰完整的教程
  5. Git 工具和指令集合
  6. 静态网站(博客)生成器Static Site Generators(SSGs)大集合
  7. Pycharm最高效的快捷键集合
  8. 集合类型内置方法
  9. MongoDB副本集配置hidden从库

随机推荐

  1. Android 内存泄漏
  2. 开发环境之Mac上Android(安卓)Studio上虚
  3. Android开发平台简介
  4. Android多媒体数据库之MediaStore研究
  5. Webview实现Android和JS通信
  6. CAMERA(12)---[Android相机]光线传感器识
  7. android 那些事---主线程是线程不安全的
  8. android json 转换
  9. android inputType属性
  10. Android(Java):把EHCache集成到android项