简介
MongoDB官方在线文档:https://www.mongodb.com/docs/manual/

MongoDB是个文档型NoSQL数据库,目的是方便应用开发和扩展。
(底层是由C++编写的,基于分布式文件存储的文档型数据库,也就是说支持集群、分片等等)
它支持的数据结构非常松散,是类似json的bson格式,可以存储复杂的数据类型,支持语言非常强大,实现关系型数据库单表查询的绝大部分功能。3.2版本之后可实现多个集合联合查询。
2009年开源。2018年4.0版本开始支持ACID强事务。
特点
1.面向集合存储,易存储对象类型的数据;
2.支持查询、分页查询、动态查询等;
3.客户端语言支持ruby、python、java、C++、PHP、C#;
4.文件存储格式为BSON;
5.支持复制、故障恢复、分片;
6.在4.0版本后,对于单条记录的操作,支持事务ACID的强一致性;
...
应用场景
- 游戏应用:存储用户信息,装备积分等,以文档形式存储,方便查询和更新;
- 物流应用:订单状态不断更新,用MongoDB内嵌数组形式存储,一次可以查到订单所有变更;
- 社交应用:附近的人、地点等功能
...
安装
一.传统方式安装
此过程较为简略,有关OS配置、配置文件、不同启停方式等可参考之前的MongoDB3.X笔记
1.下载
访问官网:https://www.mongodb.com/try/download/community

选择对应的OS、选择压缩包的形式。
2.上传和解压
将安装包上传到指定目录后,解压并重命名
tar -zxf mongodb-linux-x86_64-rhel70-5.0.8.tgz
ls
mv mongodb-linux-x86_64-rhel70-5.0.8 mongodb
3.查看安装目录
查看解压目录下内容
cd mongodb/
ll
cd bin/
ll
可以看到四个脚本,其中
- install_compass*是用来安装compass工具的,
- mongo*是对应的mongodb的一个客户端,
- mongod*是用来启动mongodb服务的,
- mongos*是分片用到的路由脚本;
4.启动MongoDB服务
查看mongod帮助选项:
./mongod --help
mongodb不能直接启动,必须加相关参数才可以启动,关键参数如下:
--port 端口,不加此参数的话默认运行在27017;
--fork,后台运行,不会占用窗口;
--logpath,指定日志文件写的位置,如果不指定则会把日志打到当前终端里;
--dbpath,指定数据存放位置,默认是/data/db;
进入mongodb的bin目录后,使用mongod启动:
./mongod --port=27017 --dbpath=/data/mongodata --logpath=/data/mongolog/mongo.log --bind_ip=0.0.0.0
如果提示existing log file则说明之前存在相关日志,启动时会自动重命名新日志名字。新开窗口查看日志,如果提示等待连接则说明启动完成。
查看是否已启动:
ps aux |grep mongo
5.客户端连接
进入MongoDB目录的bin目录下使用mongo脚本连接
./mongo --port=27017
可以看到mongodb的shell版本,以及会话的uuid,以及命令行界面。
查看所有库:
show dbs;
如果能看到admin、config、local三个保留库则说明mongodb已经安装完成。
使用exit退出客户端。
传统方式安装默认不开启远程访问权限,如果需要开启远程需要在启动选项中添加--bind_ip=0.0.0.0
二.Docker方式安装
1.拉取mongodb镜像
百度搜索dockerhub就可以进入dockerhub的官网,之后搜索mongodb,在Tags中搜索MongoDB的版本;
搜索到版本后选择标准版(没有后缀)下载即可,这里以5.0.5为例。
查看docker镜像:
docker images
2.运行mongo镜像
查看docker启动的镜像:
docker ps
以docker方式启动,映射主机端口27017:
docker run --name mongo -d -p 27017:27017 mongo:5.0.5
3.进入mongo容器
找到容器mongodb的容器id后进入:
(例如此id为deb0f28d9275)
docker ps
docker exec -it deb0f28d9275 bash
在容器中环境变量都是配置好的,直接使用mongo命令即可进入命令行界面;
使用exit命令退出容器。
停止容器:
docker stop deb0f28d9275
查看包括历史容器的信息,再重新启动该容器:
docker ps -a
docker start deb0f28d9275
使用OS中的mongo客户端也可连接,对容器内的mongo来说就是外部客户端连接。
核心概念及操作
1.库<DataBase>
类似传统关系型数据库中的库的概念,用来隔离不同应用的数据。
mongodb中每个库都有自己的集合和权限,不同数据库也放在不同的文件中。
默认数据库为test,数据库存在启动指定的data目录中。
2.集合<Collection>
集合就是MongoDB文档组,类似RDBMS中的表概念。
一个库可以有多个集合,每个集合没有固定结构,意味着可以对集合插入不同格式和类型的数据,但通常情况下插入集合的数据都会有一定关联性。
3.文档<Document>
文档是集合中一条条记录,是一组键值(key-value)对(即BSON)。MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大区别。
一.库的相关操作
(使用mongo客户端连上来后,使用cls命令可以清除之前的显示内容)
查看所有库:
show databases
show dbs;
当一个库中没有集合的时候默认是显示不出来的。
创建一个库baizhi:
use baizhi;
查看当前所在库:
db;
默认连进来的库是test库,但因为test没有任何数据,所以无法通过show命令显示出来。
保留数据库说明:
- admin:理解为root数据库,添加到此库的用户将继承所有数据库权限;一些特定的服务器端命令也只能从这个数据库运行。
- local:这个数据不会被主从复制。
- config:用于保存分片的相关信息。
不建议对保留数据库做相关操作。
向baizhi库插一条数据:
db.users.insert({"id":1,"name":'xiaochen'});
删除数据库(默认删除当前使用的库):
db.dropDatabase()
二.集合的相关操作
查看库中的集合:
show collections;
show tables;
创建集合:
db.createCollection('集合名称',[options]);
db.createCollection('products');
db.createCollection('users',{max:1000,capped:true,size:5000});
options可以是如下选项:

不加options则使用默认选项。
向一个不存在的集合中插入文档也可以自动创建相应的集合:
db.emps.insert({name:'wenjie.wang'});
集合是没有修改操作的。
删除集合:
db.集合名称.drop();
三.文档的相关操作
参考:https://docs.mongodb.com/manual/reference/method/
1.插入文档
单条文档:
db.集合名称.insert({"name":"wenjie.wang","age":26,"bir":"2000-05-31"});
返回WriteResult({"nInserted" : 1})说明一个文档已经插入。
多条文档:
db.集合名称.insertMany(
[<document 1>, <document 2>, ...],
{
writeConcern: 1, //写入策略,默认为1,即要求确认写操作,0是不要求确认写操作
ordered:true //指定是否按顺序写入,默认true,按即顺序写入
}
)
db.集合名称.insert([
{"name":"wenjie.wang","age":26,"bir":"2000-05-31"},
{"name":"marshall","age":26,"bir":"1995-05-31"}
]);
确认写操作是指,插入时会有是否插入的提示。
返回值中有"acknowledged" : true说明已经插入。
在新版本中直接使用insert也可插入多条,从返回结果的nInserted查看有多少文档已插入。
脚本方式:
for(let i=0;i<100;i++){
db.userCollection.insert({
"_id":i,"name":"it_"+i,"age":26
});
}
脚本的方式只会返回最后一次插入的result。
注:在mongodb中每个文档都会有一个_id作为唯一标识,_id默认会自动生成;如果手动指定,将使用手动指定的值作为_id的值。
查询所有文档
db.集合名称.find();
2.删除文档
db.集合名称.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
query:(可选)删除文档的条件。
justOne:(可选)如果设为true或1,则只删除一个文档,如果不设置该参数,或使用默认值false,则删除所有匹配条件的文档。
writeConcern:(可选)抛出异常的级别。
因此用空条件来删除users集合的所有文档:
db.users.remove({});
删除_id为1的文档:
db.users.remove({_id:1});
同理,删除自动生成的id值的话只用将ObjectId中双引号和双引号内的内容作为条件即可,即替换上面的1。
删除年龄是21的所有文档:
db.users.remove({age:21});
3.更新文档
db.集合名称.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
);
参数说明:
query:update的查询条件,类似sql update查询内where后面的。
update:update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的内容。
upsert:(可选),这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false不插入。
multi:(可选),mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern:(可选),抛出异常的级别。
例:将一个age为25的文档更新为28
db.users.update({age:25},{age:28})
mongodb中的更新操作实际上是将原文档删除再重新插入,所以保留原始内容更新的话需要使用$set,例如:
db.集合名称.update({"name": "xiaohei"},{$set: {name: "xiaobai"}});
这样就可以保留原来数据的同时进行更新,更新符合条件的第一个文档。
如果需要保留原来数据,并更所有符合要求的文档,需要加multi选项:
db.集合名称.update({"name": "xiaohei"},{$set: {name: "xiaobai"}},{multi: true});
4.查询文档
使用find()方法,单独的find()以非结构化的方式来显示所有文档,默认会显示前20条,使用it继续往下查看。
语法:
db.集合名称.find(query, projection)
query:(可选)使用查询操作符指定查询条件。
projection:(可选)使用投影操作符指定返回的键。返回文档的所有键只需省略该参数即可(默认省略)。
用易读的方式来读取数据可使用pretty()方法,语法格式如下:
db.集合名称.find().pretty()
注意:pretty()方法以格式化的方式来显示所有文档。(美化)
比较运算符:
与SQL语句对比如下表:
操作 | RDBMS语句 | mongodb格式 | 例子 |
---|---|---|---|
等于 | where name = 'wenjie.wang' | {<key>:<value>} | db.col.find({"name":"wenjie.wang"}).pretty() |
小于 | where age <120 | {<key>:{$lt:<value>}} | db.col.find({"age":{$lt:120}}).pretty() |
小于等于 | where age <=120 | {<key>:{$lte:<value>}} | db.col.find({"age":{$lte:120}}).pretty() |
大于 | where age >120 | {<key>:{$gt:<value>}} | db.col.find({"age":{$gt:120}}).pretty() |
大于等于 | where age >=120 | {<key>:{$gte:<value>}} | db.col.find({"age":{$gte:120}}).pretty() |
不等于 | where age !=120 | {<key>:{$ne:<value>}} | db.col.find({"age":{$ne:120}}).pretty() |
AND:
db.集合名称.find({key1:value1, key2:value2}).pretty()
类似传统SQL中的where key1=value1 and key2=value2;
如果多次写重复的键做条件的话,会以最后出现的为准。
(与做交集有区别)
如果是区间使用$and,参考下面例子:
db.集合名称.find({'$and':[{age:{$gt:22},age:{$lt:25}}]})
OR:
使用关键字$or,or的条件用数组连接起来,语法格式如下:
db.集合名称.find(
{
$or: [
{key1:value1}, {key2:value2}
]
}
).pretty();
类似传统SQL中的where key1=value1 or key2=value2;
AND和OR联合:
db.集合名称.find(
{
"age":{$gt:120}, $or:[{"name":"wenjie.wang"},{"name":"yu.li"}]
}
).pretty();
类似SQL语句为:where age > 120 and (name = 'wenjie.wang' or name = 'yu.li');
数组中查询
mongodb本身就支持数组类型查询,比如查询“喜好”中包含“看电视”的:
db.集合名称.insert({"_id":11,"age":29,"likes":["看电视","读书","美女"],"name":"wenjie.wang"});
db.集合名称.find({likes:"看电视"});
可以使用$size按长度查询数组(在例子中$size:3代表“喜好”有三个)
db.users.find({likes:{$size:3}});
模糊查询
靠正则实现近似的模糊查询。不要加引号,否则会被当成是值;以斜杠/开头,以斜杠/结尾;这样就构建了一个js中的正则表达式。
db.users.find({name:/wang/});
类似传统SQL中的where name like '%wang%'。
对于数组中的值也可以使用模糊查询,如:
db.users.find({likes:/读/});
排序
使用sort()方法
db.集合名称.find().sort({name:1,age:1})
类似传统SQL中的order by name asc, age asc,
其中1代表asc,-1代表desc。
如果有的文档没有这个键,那么升序时没有这个排序键的会排在最前面。
查询结果分页
db.集合名词.find().sort({条件}).skip(start).limit(rows);
类似于SQL:limit start, rows
总条数
db.集合名称.count();
db.集合名称.find({"name":"wenjie.wang"}).count();
db.集合名称.find({_id:{$gt:5000}}).count();
去重
db.集合名称.distinct('字段');
返回值是一个去重后值的数组。
指定返回的字段
projection投影操作:
db.集合名称.({查询条件},{name:1,age:1});
1代表从所有字段中返回的字段,0代表从所有字段中不返回的字段。但1和0不能同时使用,要么都是1要么都是0。
_id默认是一定返回的,因为是文档的唯一标识,除非手动加0。
$type操作符
$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
MongoDB中可以使用的类型如下表所示:
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | |
String | 2 | |
Object | 3 | |
Array | 4 | |
Binary data | 5 | |
Undefined | 6 | 已废弃。 |
Object id | 7 | |
Boolean | 8 | |
Date | 9 | |
Null | 10 | |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
32-bit integer | 16 | |
Timestamp | 17 | |
64-bit integer | 18 | |
Min key | 255 | Query with -1. |
Max key | 127 |
下表为MongoDB 常用的几种数据类型的描述:
数据类型 | 描述 |
---|---|
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 (每个文档都有) |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 JavaScript 代码。 |
Regular expression | 正则表达式 |
想获取集合col中title为string的数据,可以使用如下语句:
db.col.find({"title": {$type:2}}).pretty;
db.col.find({"title": {$type:'string'}}).pretty;
想获取集合col中tags为Array的数据,可以使用如下语句:
db.col.find({"tags":{$type:'array'}}).pretty();
在mongodb中,无论是整数还是小数,默认都是以double类型存放的。
聚合查询
aggregate
mongodb中的聚合查询和ES中的差不多。
db.集合名称.aggregate(
[{$group: {_id:'$by_user'}}]
);
db.集合名称.aggregate(
[{$group: {_id:'$by_user', num_tutorial:{$sum:1}}}
]
);
其中$group表示以谁分组,即_id后的字段,此处是以$by_user分组,$sum:1表示是否求和(1表示求和结果×1,0表示求和结果×0,2表示求和结果×2,以此类推) ,num_tutorial是我们用来装统计结果的自定义key

四.索引及其相关操作
1.mongodb索引概述
mongodb也是用来提高查询效率的数据结构。从根本上说,mongodb中的索引与其他数据库系统中的索引类似。MongoDB在集合层面上定义了索引(类比关系型数据库在表级定义索引),并支持对MongoDB集合中的任何字段或文档的子字段进行索引。

和传统关系型数据库索引一样,利用索引都是最左前缀原则。
参考官网:https://www.mongodb.com/docs/manual/indexes/
2.创建索引
首先当我们创建一个集合的时候,mongodb会自动为_id加一个唯一索引。
手动创建索引如下:
db.集合名称.createIndex(keys,options);
db.集合名称.createIndex({"titls":1,"description":-1});
其中1代表升序,-1代表降序。同关系学数据库一样,也可以多个字段建立复合索引。
options可选参数如下:
Parameter | Type | Description |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
dropDups | Boolean | 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
3.查看索引
查看一个集合中有哪些索引:
db.集合名称.getIndexes();
查看集合索引大小:
db.集合名称.totalIndexSize();
返回值单位是字节。
4.删除索引
删除集合所有索引:
db.集合名称.dropIndexes();
使用dropIndexes时,仍会保留_id上的索引“_id_”。
删除集合指定索引:
db.集合名称.dropIndex('索引名称');
副本集
MongoDB副本集(Replica Set)是有故障恢复功能的主从集群,有一个Primary节点和一个或多个的Secondary节点组成。副本集没有固定的主节点,当主节点发生故障时整个集群会选举一个主节点为系统提供服务以保证系统的高可用。最小的搭建是需要两节点,但实际最小是三节点,最好是奇数个节点。
缺陷在于无法做读写分离、负载均衡,辅助副本默认也是不能读的。
当副本集中只剩一个节点时,对外是不可用的。

官网说明页:https://www.mongodb.com/docs/manual/replication/
Automatic Failover
自动故障转移机制:当主节点未与集合的其他成员通信超过配置的选举超时时间(默认为10s时),合格的辅助节点将调用选举以将自己提名为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。

副本集搭建
选择“一主副本两辅助副本”的架构,需要三台服务器。此处以本地三实例为例搭建,生产环境还是建议多台服务器。
创建数据目录:
#在安装目录中创建
mkdir -p ../repl/data1
mkdir -p ../repl/data2
mkdir -p ../repl/data3
搭建副本集:
./mongod --port 27017 --dbpath ../repl/data1 --bind_ip 0.0.0.0 --replSet myreplace/[localhost:27018,localhost:27019]
./mongod --port 27018 --dbpath ../repl/data2 --bind_ip 0.0.0.0 --replSet myreplace/[localhost:27017,localhost:27019]
./mongod --port 27019 --dbpath ../repl/data3 --bind_ip 0.0.0.0 --replSet myreplace/[localhost:27017,localhost:27018]
replSet指定了副本集名称myreplace,以及集群其他节点的主机和端口
配置副本集
连接任意节点:./mongo --port 27017
然后use admin,
初始化副本集
> var config = {
_id:"myreplace",
members:[
{_id:0,host:"121.5.167.13:27017"},
{_id:1,host:"121.5.167.13:27018"},
{_id:2,host:"121.5.167.13:27019"}]
}
> rs.initiate(config); //初始化配置
注意在配置中我们一定要写本机ip而不要写localhost,否则会出问题。
rs是一个内置对象(replicate set),我们把刚才的config构建进去就初始化了,初始化完成后一开始所有节点都是secondary,然后就会选举主节点,过段时间就有主节点产生,整个系统就可以提供服务了。
如果想检验从节点是否有数据了,需要读取,因此需要执行:
rs.slaveOk();
rs.secondaryOk(); //尽量用这个,因为slaveOk在未来的大版本中会移除
执行之后就可以在从节点进行查询了。
应用连接
对于应用来说,应写副本集所有节点地址,并写副本集名字,以springbot为例连baizhi库:
spring.data.mongodb.url=mongodb://121.5.167.13:27017,121.5.167.13:27018,121.5.167.13:27019/baizhi?replicaSet=myreplace
分片集群
分片概述
分片(sharding)是指将数据拆分,将其分散在不同机器的过程,有事也用分区(partitioning)来表示这个概念,将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。
分片目的是通过分片能够增加更多机器来应对不断增加的负载和数据,还不影响应用运行。
MongoDB支持自动分配,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡。MongoDB分片的基本思想就是将集合拆分成多个块,这些块分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放的位置,应用只需要直接与mongos交互即可。mongos自动将请求转到相应的片上获取数据,从应用角度看分不分片没有什么区别。
架构

- shared:用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组成一个replica set承担,防止主机单点故障
- config server:mongod实例,存储了整个clusterMetadata。因为存储了集群元数据,非常重要,因此官方强制要求config server必须是副本集。
- query routers:前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
- shared key:片键,设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,着个片键称之为shard key,片键的选取很重要,片键的选取决定了数据散列是否均匀。
搭建
规划:
shard server 1:27017
shard repl 1:27018
shard server 2:27019
shard repl 2:27020
shard server 3:27021
shard repl 3:27022
config server :27023
config server :27024
config server :27025
route process :27026
创建数据目录:
mkdir -p ../cluster/shard/s0
mkdir -p ../cluster/shard/s0-repl
mkdir -p ../cluster/shard/s1
mkdir -p ../cluster/shard/s1-repl
mkdir -p ../cluster/shard/s2
mkdir -p ../cluster/shard/s2-repl
mkdir -p ../cluster/shard/config1
mkdir -p ../cluster/shard/config2
mkdir -p ../cluster/shard/config3
接下来启动6个shard服务。
启动so、r0:
./mongod --port 27017 --dbpath ../cluster/shard/s0 --bind_ip 0.0.0.0 --shardsvr --replSet r0/121.5.167.13:27018
./mongod --port 27018 --dbpath ../cluster/shard/s0-repl --bind_ip 0.0.0.0 --shardsvr --replSet r0/121.5.167.13:27017
此处加了--shardsvr,代表以分片服务方式启动;
定义副本集r0;
登陆任意节点 use admin
执行:
config = { _id:"r0",members:[
{_id:0,host:"121.5.167.13:27017"},
{_id:1,host:"121.5.167.13:27018"}
]
}
rs.initiate(config);
能看到“OK” : 1则说明副本集构建成功。
同理启动s1、r1:
./mongod --port 27019 --dbpath ../cluster/shard/s1 --bind_ip 0.0.0.0 --shardsvr --replSet r1/121.5.167.13:27020
./mongod --port 27020 --dbpath ../cluster/shard/s1-repl --bind_ip 0.0.0.0 --shardsvr --replSet r1/121.5.167.13:27019
定义副本集r1;
登陆任意节点 use admin
执行:
config = { _id:"r1",members:[
{_id:0,host:"121.5.167.13:27019"},
{_id:1,host:"121.5.167.13:27020"}
]
}
rs.initiate(config); //初始化
同理启动s2、r2:
./mongod --port 27021 --dbpath ../cluster/shard/s2 --bind_ip 0.0.0.0 --shardsvr --replSet r2/121.5.167.13:27022
./mongod --port 27022 --dbpath ../cluster/shard/s2-repl --bind_ip 0.0.0.0 --shardsvr --replSet r2/121.5.167.13:27021
定义副本集r2;
登陆任意节点 use admin
执行:
config = { _id:"r2",members:[
{_id:0,host:"121.5.167.13:27021"},
{_id:1,host:"121.5.167.13:27022"}
]
}
rs.initiate(config); //初始化
启动3个config服务:
./mongod --port 27023 --dbpath ../cluster/shard/config1 --bind_ip 0.0.0.0 --replSet config/[121.5.167.13:27024,121.5.167.13:27025] --configsvr
./mongod --port 27024 --dbpath ../cluster/shard/config2 --bind_ip 0.0.0.0 --replSet config/[121.5.167.13:27023,121.5.167.13:27025] --configsvr
./mongod --port 27025 --dbpath ../cluster/shard/config3 --bind_ip 0.0.0.0 --replSet config/[121.5.167.13:27023,121.5.167.13:27024] --configsvr
初始化config server副本集:
登录任一config server节点
use admin
在admin中执行:
var config = {
_id:"config",
configsvr:true,
members:[
{_id:0,host:"121.5.167.13:27023"},
{_id:1,host:"121.5.167.13:27024"},
{_id:2,host:"121.5.167.13:27025"}
]
}
rs.initiate(config); //初始化副本集配置
启动mongos路由服务:
./mongod --port 27026 --configdb config/121.5.167.13:27023,121.5.167.13:27024,121.5.167.13:27025 --bind_ip 0.0.0.0
登录mongos服务
mongo --port 27026
use admin
添加分片信息:
db.runCommand({addshard:"r0/121.5.167.13:27017,121.5.167.13:27018","allowLocal:true"});
db.runCommand({addshard:"r1/121.5.167.13:27019,121.5.167.13:27020","allowLocal:true"});
db.runCommand({addshard:"r2/121.5.167.13:27021,121.5.167.13:27022","allowLocal:true"});
指定分片的数据库
db.runCommand({enablesharding:"baizhi"});
设置库的片键信息
db.runCommand({shardcollection:"baizhi.users",key:{_id:1}});
db.runCommand({shardcollection:"baizhi.emps",key:{_id:"hashed"}});
此处1代表启用。
hashed是哈希片键,是由mongodb自身分配的,分布会均匀,一般都用_id做片键。
网友评论