MongoDB 基础
MongoDB 是什么
MongoDB 是一个基于分布式文件存储的开源NoSQL数据库系统,由 C++ 编写的。
MongoDB 提供了面向文档的存储方式,支持**“无模式”的数据建模,可以存储比较复杂的数据类型,是一款非常流行的文档类型数据库**。
MongoDB 天然支持水平扩展和高可用,可以很方便地添加更多的节点/实例,以保证服务性能和可用性。
MongoDB 的存储结构
主要由如下三部分构成:
-
文档(DOcument):最基本的单元,由 BSON 键值对(key-value)组成,类似于关系型数据库中的行(Row)。
-
集合(Collection):一个集合可以包含多个文档,类似于关系型数据库中的表(Table)。
-
数据库(Database):一个数据库可以包含多个集合,可以在 MongoDB 中创建多个数据库,类似于关系型数据库中的数据库(Database)。
BSON 是 JSON 的二进制表示方式,并且具有比 JSON 更丰富的数据类型。
MongoDB stores data records as BSON documents. BSON is a binary representation of JSON documents, though it contains more data types than JSON.
SQL | MongoDB |
---|---|
表(Table) | 集合(Collection) |
行(Row) | 文档(Document) |
列(Col) | 字段(Field) |
主键(Primary Key) | 对象ID(Objectid) |
索引(idnex) | 索引(index) |
嵌套表(Embedded Table) | 嵌入式文档(Embedded Document) |
文档
MongoDB 中的记录就是一个 BSON 文档,是由键值对组成的数据结构,类似与 JSON 对象。
文档的键可以是任意 UTF-8 字符串。(但不能是\0
(空字符)、.
、$
以及以_
开头)
BSON 支持将文档和数组嵌入到其他文档和数组中,还包含允许表示不属于 JSON 规范的数据类型的扩展。更多关于 BSON 值的类型可以参考BSON 类型
集合
MongoDB 的集合是无模式的,可以往集合中插入不同格式和类型的数据,但通常来说同一集合中的数据具有一定的关联性。
集合不需要事先创建,在插入第一个文档或索引时,若集合不存在,则会自动创建集合。
集合名可以是满足下列条件的任意 UTF-8 字符串:
- 不能是空串
""
。 - 不能含有
\0
(空字符),这个字符表示集合名的结尾。 - 不能以
system.
开头,这是为系统集合保留的前缀。 - 不能包含
$
。 - 必须以下划线或者字母符号开始
数据库
数据库用于存储所有集合,而集合用于存储所有文档。
一个 MongoDB 可以创建多个数据库,每一个数据库都有自己的集合和权限。
MongoDB 的预留数据库:
-
admin:admin 数据库主要是保存 root 用户和角色。例如,system.users 表存储用户,system.roles 表存储角色。一般不建议用户直接操作这个数据库。将一个用户添加到这个数据库,且使它拥有 admin 库上的名为 dbAdminAnyDatabase 的角色权限,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如关闭服务器。
-
local:local 数据库是不会被复制到其他分片的,因此可以用来存储本地单台服务器的任意 collection。一般不建议用户直接使用 local 库存储任何数据,也不建议进行 CRUD 操作,因为数据无法被正常备份与恢复。
-
config:当 MongoDB 使用分片设置时,config 数据库可用来保存分片的相关信息。
-
test:默认创建的测试库,连接 mongod 服务时,如果不指定连接的具体数据库,默认就会连接到 test 数据库。
数据库名可以是满足以下条件的任意 UTF-8 字符串:
-
不能是空字符串
""
。 -
不得含有
' '
(空格)、.
、$
、/
、\
和\0
(空字符)。 -
应全部小写。
-
最多 64 字节。
MongoDB 的特点
-
数据记录为文档:数据记录被存储为 BSON 文档,由键值对组成的数据结构。
-
模式自由:集合不需要定义任何模式,能用更少的数据对象表现复杂的领域模型对象。
-
支持多种查询方式:支持读写操作(CRUD)及数据聚合、文本搜索和地理空间查询。
-
支持 ACID 事务:通常 NoSQL 是不支持事务的,但 MongoDB 支持。
-
高效的二进制存储:存储在集合中的文档,以键值对的形式存在。键用于唯一标识一个文档,一般是 Objectid 类型,值是以 BSON 形式存在的。
-
支持多种类型的索引:单字段索引、符合索引、多键索引、哈希索引、文本索引、地理位置索引等。
-
支持 failover:提供自动故障恢复功能,主节点发生故障时,自动从从节点选举出一个新的主节点,客户端无感知。
-
支持分片集群:支持集群自动切分数据,让集群存储更多的数据,具备更强的性能。在数据插入和更新时,能自动路由和存储。
-
支持存储大文件:单文档存储空间要求不超过 16 MB。对于大文件提供了 GridFS 来存储,通过 GridFS 可以将大型数据分块处理,然后将切分后的小数据存储到数据库中。
MongoDB 的适用场景
**MongoDB 的优势在于其数据模型和存储引擎的灵活性、架构的可扩展性以及对强大的索引支持。**从以上三方面来考虑。
MongoDB 存储引擎
MongoDB 支持哪些存储引擎
同 MySQL 一样,MongoDB 采用的也是 插件式的存储引擎架构,支持不同类型的存储引擎。在创建数据库或集合时,可以指定存储引擎。
在存储引擎刚出来的时候,默认是使用 MMAPV1 存储引擎,MongoDB4.x 版本不再支持 MMAPv1 存储引擎。
现在主要有下面这两种存储引擎:
-
WiredTiger 存储引擎:自 MongoDB 3.2 以后,默认的存储引擎为 WiredTiger 存储引擎。非常适合大多数工作负载,建议用于新部署。WiredTiger 提供文档级并发模型、检查点和数据压缩等功能。WiredTiger 默认是基于 B+ 树的,也可以使用 LSM(Log Structured Merge) 树作为存储结构。
-
In-Memory 存储引擎:In-Memory 存储引擎在 MongoDB Enterprise 中可用。它不是将文档存储在磁盘上,而是将它们保留在内存中以获得更可预测的数据延迟。
此外,MongoDB 3.0 提供了 可插拔的存储引擎 API ,允许第三方为 MongoDB 开发存储引擎。
MongoDB 基本常用命令
数据库相关
-
查看当前数据库:
db
-
查看所有数据库:
show databases
或show dbs
-
选择数据库(不存在不会报错,会隐式创建:在后期数据库有数据时自动创建):
use 数据库名
-
删除数据库(先选中):
db.dropDatabase()
集合相关
-
查看所有集合:
show collections
-
创建集合(插入数据会隐式创建):
db.createCollection('集合名')
-
删除集合:
db.集合名.drop()
CRUD
-
插入文档:
db.集合名.insert(数据)
,mongodb会自动给每条数据创建全球唯一的_id键。 -
删除文档:
db.集合名.remove(条件 [, 是否删除一条])
,默认删除全部。 -
修改文档:
db.集合名.update(条件, 新数据 [, 是否新增, 是否修改多条])
,默认新数据替换旧数据,默认未匹配到时不新增,默认只修改一条-
若需要进行修改,格式为:
{修改器: {key: value}}
。修改器:$inc
递增,$rename
重命名列,$set
修改列值,$unset
删除列。 -
举例:
db.people.update({name:"n1"},{name:"n2"})
将 name 为 n1 的文档替换为 {name:“n2”}。db.people.update({name:"n1"},{$set:{name:"n3"}})
将 name 为 n1 的文档中 name 字段的值改为 n3。
-
-
查询文档:
db.集合名.find(条件 [, 查询的列])
,db.集合名.find(条件 [, 查询的列])
-
查询所有数据时条件为
{}
或不写 -
查询指定要求数据时条件为
{key:value}
或{key:{运算符:value}}
。-
运算符:
$gt
大于,$gte
大于等于,$lt
小于,$lte
小于等于,$ne
不等于,$in
包含,$nin
不包含。 -
多个条件 AND,用逗号拼接条件即可。
{key1: value1, key2: value2}
-
多个条件 OR,用
$or
关键字。db.col.find({$or: [{key1: value1}, {key2: value2}]})
-
-
查询指定的列:
db.集合名.find({}, {"title": 1, id_: 0})
,如果 id_ 不指定为 0 则默认会返回,其他字段,不指定则不返回。 -
格式化数据,添加 pretty() 方法:
db.集合名.find().pretty()
-
查询指定数量时,添加 limit() 方法:
db.集合名.find().limit(num)
-
需要跳过一定数量的记录,添加 skip() 方法:
db.集合名.find().skip(num)
-
排序,添加 sort() 方法,指定字段 1 为升序,-1 为降序:
db.集合名.find().sort({KEY: 1})
-
MongoDB 索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB 在读取数据时必须扫描集合中的每个文档并选取那些符合查询条件的记录。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
虽然索引可以显著缩短查询时间,但是使用索引、维护索引是有代价的。在执行写入操作时,除了要更新文档之外,还必须更新索引,这必然会影响写入的性能。因此,当有大量写操作而读操作少时,或者不考虑读操作的性能时,都不推荐建立索引。
MongoDB 支持的索引类型
-
单字段索引:建立在单个字段上的索引,索引创建的排序顺序无所谓。
-
复合索引:建立在多个字段上的索引,也可以称之为组合索引、联合索引。
-
对复合索引来说,字段的顺序以及字段的值的排序方式都会影响索引是否能被应用。
-
复合索引遵循左前缀原则,即只要从左侧开始的前缀匹配,即可使用索引。
-
-
多键索引:MongoDB 的一个字段可能是数组,在对这种字段创建索引时,就是多键索引。MongoDB 会为数组的每个值创建索引。就是说你可以按照数组里面的值做条件来查询,这个时候依然会走索引。
-
哈希索引:按数据的哈希值索引,用在哈希分片集群上。
-
文本索引:支持对字符串内容的文本搜索查询。文本索引可以包含任何值为字符串或字符串元素数组的字段。一个集合只能有一个文本搜索索引,但该索引可以覆盖多个字段。MongoDB 虽然支持全文索引,但是性能低下,暂时不建议使用。
-
地理位置索引:基于经纬度的索引,适合 2D 和 3D 的位置查询。
-
唯一索引:确保索引字段不会存储重复值。
-
TTL 索引:TTL 索引提供了一个过期机制,允许为每一个文档设置一个过期时间 expireAfterSeconds,当一个文档达到预设的过期时间之后就会被删除。
TTL 索引运行原理:MongoDB 会开启一个每 60S 执行删除操作的后台线程,该线程读取该 TTL 索引的值来判断文档是否过期,如果删除的数据量较大,会存在上一次的删除未完成,而下一次的任务已经开启的情况,导致过期的数据也会出现超过了数据保留时间 60 秒以上的现象。对于副本集而言,TTL 索引的后台进程只会在 Primary 节点开启,在从节点会始终处于空闲状态,从节点的数据删除是由主库删除后产生的 oplog 来做同步。
-
TTL 索引限制:
-
TTL 索引是单字段索引。
-
_id
字段不支持 TTL 索引。 -
无法在上限集合(Capped Collection)上创建 TTL 索引,因为 MongoDB 无法从上限集合中删除文档。
-
如果某个字段已经存在非 TTL 索引,那么在该字段上无法再创建 TTL 索引。
-
覆盖索引查询
如果一个查询满足一下三个条件,即可称为覆盖索引查询:
-
所有的查询字段都是索引的一部分;
-
结果中返回的所有字段都在同一索引中;
-
查询中没有字段等于 NULL。
PS:若索引中没有 _id 字段,_id 需要在查询时被显式排除(_id: 0)
创建索引
MongoDB 使用 createIndex() 方法来创建索引。db.集合名.createIndex(keys, options)
,keys 为要创建的字段集合 {key1: value1, key2: value2},key 为字段名,value 可以取 1 升序,-1 降序排列。
在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。
可选参数:
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. |
实例:db.values.createIndex({open: 1, close: 1}, {background: true})
MongoDB 聚合
实际项目中,我们经常需要将多个文档甚至是多个集合汇总到一起计算分析(比如求和、取最大值)并返回计算后的结果,这个过程被称为聚合操作。
MongoDB 提供的聚合方法
MongoDB 提供了两种执行聚合的方法:
-
聚合管道(Aggregation Pipeline):执行聚合操作的首选方法。
-
单一目的的聚合方法(Single purpose aggregation methods):单一作用的聚合函数,如:
count()
、distinct()
、estimatedDocumentCount()
。
还有 map-reduce 这种聚合方法。不过,从 MongoDB 5.0 开始,map-reduce 已经不被官方推荐使用了,替代方案是聚合管道。聚合管道提供比 map-reduce 更好的性能和可用性。
MongoDB 聚合管道由多个阶段组成,每个阶段在文档通过管道时转换文档。每个阶段接收前一个阶段的输出,进一步处理数据,并将其作为输入数据发送到下一个阶段。
常用阶段操作符:
操作 | 符简述 |
---|---|
$match | 匹配操作符,用于对文档集合进行筛选 |
$project | 投射操作符,用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段 |
$sort | 排序操作符,用于根据一个或多个字段对文档进行排序 |
$limit | 限制操作符,用于限制返回文档的数量 |
$skip | 跳过操作符,用于跳过指定数量的文档 |
$count | 统计操作符,用于统计文档的数量 |
$group | 分组操作符,用于对文档集合进行分组 |
$unwind | 拆分操作符,用于将数组中的每一个值拆分为单独的文档 |
$lookup | 连接操作符,用于连接同一个数据库中另一个集合,并获取指定的文档,类似于 populate |
更多操作符介绍详见官方文档:https://docs.mongodb.com/manual/reference/operator/aggregation/
阶段操作符用于 db.collection.aggregate 方法里面,数组参数中的第一层。
分组操作符($group)支持一系列聚合的表达式:
表达式 | 描述 |
---|---|
$sum | 计算总和。 |
$avg | 计算平均值 |
$min | 获取集合中所有文档对应值得最小值。 |
$max | 获取集合中所有文档对应值得最大值。 |
$push | 将值加入一个数组中,不会判断是否有重复的值。 |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 |
$first | 根据资源文档的排序获取第一个文档数据。 |
$last | 根据资源文档的排序获取最后一个文档数据 |
db.collection.aggregate( [ { 阶段操作符:表述 }, { 阶段操作符:表述 }, ... ] )
# 以下是官方实例
db.orders.aggregate([
# 第一阶段:$match阶段按status字段过滤文档,并将status等于"A"的文档传递到下一阶段。
{ $match: { status: "A" } },
# 第二阶段:$group阶段按cust_id字段将文档分组,以计算每个cust_id唯一值的金额总和。
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
]);
# 其他实例
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
]);
db.article.aggregate(
{ $project : {
_id : 0 ,
title : 1 ,
author : 1
}});
MongoDB 高可用
复制集群
什么是复制集群
MongoDB 的复制集群是一组维护相同数据集合的 mongod 进程。
客户端连接到整个 Mongodb 复制集群,主节点机负责整个复制集群的写,从节点可以进行读操作,但默认还是主节点负责整个复制集群的读。主节点发生故障时,自动从从节点中选举出一个新的主节点,确保集群的正常使用,这对于客户端来说是无感知的。
通常来说,一个复制集群包含 1 个主节点(Primary),多个从节点(Secondary)以及零个或 1 个仲裁节点(Arbiter)。
-
主节点 :整个集群的写操作入口,接收所有的写操作,并将集合所有的变化记录到操作日志中,即 oplog。主节点挂掉之后会自动选出新的主节点。
-
从节点 :从主节点同步数据,在主节点挂掉之后选举新节点。不过,从节点可以配置成 0 优先级,阻止它在选举中成为主节点。
-
仲裁节点 :这个是为了节约资源或者多机房容灾用,只负责主节点选举时投票不存数据,保证能有节点获得多数赞成票。
主从之间通过oplog(操作日志)来同步数据的。oplog 是 local 库下的一个特殊的上限集合(Capped Collection),用来保存写操作所产生的增量日志,类似于 MySQL 中 的 Binlog。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
上限集合类似于定长的循环队列,数据顺序追加到集合的尾部,当集合空间达到上限时,它会覆盖集合中最旧的文档。上限集合的数据将会被顺序写入到磁盘的固定空间内,所以,I/O 速度非常快,如果不建立索引,性能更好。
如果当前主节点不可用,一个选举会抉择出新的主节点。MongoDB 的节点选举规则能够保证在 Primary 挂掉之后选取的新节点一定是集群中数据最全的一个。
为什么要用复制集群
-
实现 failover:提供自动故障恢复的功能。
-
实现读写分离:可以设置从从节点上读取,主节点仅写入,实现读写分离,减轻了主节点读写压力过大的问题。
使用复制集群
启动一个副本集要添加 --replSet "REPLICA_SET_INSTANCE_NAME"
参数
mongod --port "PORT" --dbpath "YOUR_DB_DATA_PATH" --replSet "REPLICA_SET_INSTANCE_NAME"
用客户端连接服务后,使用命令 rs.initiate()
来启动一个新的副本集。
可以使用 rs.status()
来查看副本集的状态,使用 rs.conf()
来查看副本集的配置。
使用 rs.add(HOST_NAME:PORT)
添加副本集的成员(其他MongoDB服务)。MongoDB 只能从主节点添加 MongoDB 服务到副本集,可以使用 db.isMaster()
方法判断当前 Mongo 服务是否为主节点。
分片集群
什么是分片集群
分片集群是 MongoDB 的分布式版本,数据被均衡的分布在不同的分片中, 不仅大幅提升了整个集群的数据容量上限,也将读写的压力分散到不同分片,以解决副本集性能瓶颈的难题。
MongoDB 的分片集群由以下三部分组成:
-
Routers:路由服务,不存具体数据,从 Config 获取集群配置将请求转发到特定的分片,并且整合分片结果返回给客户端。
-
Config Servers:配置服务器,本质上是一个 MongoDB 的副本集,负责存储集群的各种元数据和配置,如分片地址、Chunks 等。
-
Shard:用于存储实际的数据块,每个分片是整体数据的一部分子集。从MongoDB3.6版本开始,每个Shard必须部署为副本集(replica set)架构,实际生产环境中一个shard server角色可由几台机器组个一个replica set(副本集)承担,防止主机单点故障
什么是分片键
分片键(Shard Key) 是数据分区的前提,实现数据分发到不同服务器上,减轻服务器的负担的关键。分片键决定了集合内的文档如何在集群的多个分片间的分布状况。
分片键就是文档里面满足以下要求的的一个字段:
-
它必须在所有文档中都出现。
-
它必须是集合的一个索引,可以是单索引或复合索引的前缀索引,不能是多索引、文本索引或地理空间位置索引。
-
它的大小不能超过 512 字节。
-
MongoDB 4.2 之前的版本,文档的分片键字段值不可变。MongoDB 4.2 版本开始,除非分片键字段是不可变的 _id 字段,否则您可以更新文档的分片键值。MongoDB 5.0 版本开始,实现了实时重新分片(live resharding),可以实现分片键的完全重新选择。
如何选择分片键
选择合适的片键对 sharding 效率影响很大,主要基于如下四个因素:
-
取值基数 取值基数建议尽可能大,如果用小基数的片键,因为备选值有限,那么块的总数量就有限,随着数据增多,块的大小会越来越大,导致水平扩展时移动块会非常困难。例如:选择年龄做一个基数,范围最多只有100个,随着数据量增多,同一个值分布过多时,导致 chunck 的增长超出 chuncksize 的范围,引起 jumbo chunk,从而无法迁移,导致数据分布不均匀,性能瓶颈。
-
取值分布 取值分布建议尽量均匀,分布不均匀的片键会造成某些块的数据量非常大,同样有上面数据分布不均匀,性能瓶颈的问题。
-
查询带分片 查询时建议带上分片,使用分片键进行条件查询时,mongos 可以直接定位到具体分片,否则 mongos 需要将查询分发到所有分片,再等待响应返回。
-
避免单调递增或递减 单调递增的 sharding key,数据文件挪动小,但写入会集中,导致最后一篇的数据量持续增大,不断发生迁移,递减同理。
分片策略有哪些
- 基于范围的分片:
MongoDB 按照分片键(Shard Key)的值的范围将数据拆分为不同的块(Chunk),每个块包含了一段范围内的数据。当分片键的基数大、频率低且值非单调变更时,范围分片更高效。
-
优点:Mongos 可以快速定位请求需要的数据,并将请求转发到相应的 Shard 节点中。
-
缺点:可能导致数据在 Shard 节点上分布不均衡,容易造成读写热点,且不具备写分散性。
-
适用场景:分片键的值不是单调递增或单调递减、分片键的值基数大且重复的频率低、需要范围查询等业务场景。
- 基于 Hash 值的分片
MongoDB 计算单个字段的哈希值作为索引值,并以哈希值的范围将数据拆分为不同的块(Chunk)。
-
优点:可以将数据更加均衡地分布在各 Shard 节点中,具备写分散性。
-
缺点:不适合进行范围查询,进行范围查询时,需要将读请求分发到所有的 Shard 节点。
-
适用场景:分片键的值存在单调递增或递减、片键的值基数大且重复的频率低、需要写入的数据随机分发、数据读取随机性较大等业务场景。
分片数据如何存储
Chunk(块) 是 MongoDB 分片集群的一个核心概念,其本质上就是由一组 Document 组成的逻辑数据单元。每个 Chunk 包含一定范围片键的数据,互不相交且并集为全部数据。
默认情况下,一个 Chunk 的最大值默认为 64MB(可调整,取值范围为 1~1024 MB。如无特殊需求,建议保持默认值),进行数据插入、更新、删除时,如果此时 Mongos 感知到了目标 Chunk 的大小或者其中的数据量超过上限,则会触发 Chunk 分裂。
数据的增长会让 Chunk 分裂得越来越多。这个时候,各个分片上的 Chunk 数量可能会不平衡。Mongos 中的 均衡器(Balancer) 组件就会执行自动平衡,尝试使各个 Shard 上 Chunk 的数量保持均衡,这个过程就是 再平衡(Rebalance)。默认情况下,数据库和集合的 Rebalance 是开启的。
如下图所示,随着数据插入,导致 Chunk 分裂,让 AB 两个分片有 3 个 Chunk,C 分片只有一个,这个时候就会把 B 分配的迁移一个到 C 分片实现集群数据均衡。
Chunk 只会分裂,不会合并,即使 chunkSize 的值变大。
Rebalance 操作是比较耗费系统资源的,我们可以通过在业务低峰期执行、预分片或者设置 Rebalance 时间窗等方式来减少其对 MongoDB 正常使用所带来的影响。
启动分片集群
- 启动Shard Server
mkdir -p /www/mongoDB/shard/s0
mkdir -p /www/mongoDB/shard/s1
mkdir -p /www/mongoDB/shard/s2
mkdir -p /www/mongoDB/shard/s3
mkdir -p /www/mongoDB/shard/log
mongod --port 27020 --dbpath=/www/mongoDB/shard/s0 --logpath=/www/mongoDB/shard/log/s0.log --logappend --fork
......
mongod --port 27023 --dbpath=/www/mongoDB/shard/s3 --logpath=/www/mongoDB/shard/log/s3.log --logappend --fork
- 启动Config Server
mkdir -p /www/mongoDB/shard/config
mongod --port 27100 --dbpath=/www/mongoDB/shard/config --logpath=/www/mongoDB/shard/log/config.log --logappend --fork
前两步完全和启动普通服务一样。
- 启动Route Process
mongos --port 40000 --configdb localhost:27100 --fork --logpath=/www/mongoDB/shard/log/route.log --chunkSize 500
在启动 Router 的时候,使用的命令是 mongos
,指定了之前开启的配置服务 localhost:27100,指定了 chunk 的大小为 500,单位为 MB,默认是 200MB。
- 配置Sharding
使用MongoDB Shell登录到mongos,添加Shard节点
mongo admin --port 40000
# 添加 shard 节点
mongos> db.runCommand({ addshard:"localhost:27020" })
{ "shardAdded" : "shard0000", "ok" : 1 }
......
mongos> db.runCommand({ addshard:"localhost:27023" })
{ "shardAdded" : "shard0004", "ok" : 1 }
mongos> db.runCommand({ enablesharding:"test" }) #设置分片存储的数据库
{ "ok" : 1 }
mongos> db.runCommand({ shardcollection: "test.log", key: { id:1,time:1}}) # 指定集合及片键
{ "collectionsharded" : "test.log", "ok" : 1 }
- 程序代码无需修改,像链接普通 mongo 数据库哪样,将接入端口改为 40000 即可。