文章目录

  • mongdb基础
    • 简介
    • 与其他数据产品的对比
    • 基础概念
    • 常用的数据类型
    • 简单的CIUD
    • 高级管道查询 Aggregate
    • 高级MapReduce
    • 索引
  • 设计应用
    • 反范式化
    • skip深度分页性能
    • 分片
    • Chunk 数据块
  • 服务器管理
    • 副本集介绍
    • 副本集读写
    • 集群架构
    • 集群选举
    • 集群的搭建
    • 常用的语句整理

mongdb基础

简介

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的Bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
MongoDB 3.2 支持多表关联查询
MongoDB 4.0 引入的事务功能,支持多文档ACID特性
MongoDB 4.0 支持副本集多文档事务,并计划在 4.2 版本支持分片集群事务功能。

与其他数据产品的对比


基础概念

文档:
文档就是键值对的一个有序集,是MongoDB中数据的基本单元,非常类似于关系型数据库管理系统中的行,但更具表现力。
文档是无模式的,所以可以支持各种数据结构,内嵌模型也叫做非规格化模型
集合:
集合就是一组文档,如果将MongoDB中的一个文档比喻为关系型数据库中的一行,那么一个集合就相当于一张表的概念。

MongoDB使用了BSON这种结构来存储数据和网络数据交换
BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。

常用的数据类型

null
null用于表示空值或者不存在的字段:
{“data”:null}
布尔型
布尔类型只有两个值,true和false:
{“data”:true}、{“data”:false}
字符串
字符串类型的数据是由UTF-8字符组成:
{“data”:“pingan”}
正则表达式
查询时,使用正则表达式作为限定条件,语法和javascript的正则表达 式一样:
{“data”:/pingan/i}
对象_id:
对象id是一个12字节(24字符)的ID,是文档的唯一标识。ObjectId 是_id的默认数据类型,轻量级 全局唯一 适应分片环境
{“data”:ObjectId()}
数值
shell默认使用64位的浮点型数值,即Double类型。对于整型值,可以使用NumberInt类(4字节带符号整数)或NumberLong类(8字节带符号整数)。
{“data”:3.33},表示Double类型
{“data”:NumberInt(“3”)},表示Int类型
{“data”:NumberLong(“3”)},表示Long类型
数组
数据列表或者数据集都可以表示为数组。数组的元素可以是数值、字符串等等其他基本数据类型,元素之间用英文逗号分隔开。
{“data”:[1,2,3]}、{“data”:[“a”,“b”,“c”]}
日期
都是先转换为UTC时间,然后存储到数据库中 (也可以存时间戳与时区无关,也可存字符串)
{“data”:new Date()}
内嵌文档
文档可以嵌套其他文档,被嵌套的文档作为父文档的值:
{“data”:{“company”:“pingan”}}
二进制数据
二进制数据是一个任意字节的字符串,要将非UTF-8字符保存到数据库中,二进制数据是唯一的方式。比如保存图片的数据。但是不能直接在shell中使用。

简单的CIUD

MongoDB有一个很大的优势—它使用js管理数据库,所以也能够使用js脚本进行复杂的管理
mongodb 的shell是javascript实现的,如果直接使用js实现相应的功能则显得很直观和简便。
比如我们对一些数据进行 统计计算,除了使用mapreduce之外,直接使用js也是很好的选择。

 insert
for(var i =2; i<100; i++){db.getCollection('user').insert({"_id":i,"age":20+i})}
Remove
db.getCollection('user').remove({"_id":5})Find
db.getCollection('user').find({"_id":6})explain(true)


stage状态分析
COLLSCAN:全表扫描
IXSCAN:索引扫描
FETCH:根据索引去检索指定document
SHARD_MERGE:将各个分片返回数据进行merge
SORT:表明在内存中进行了排序
LIMIT:使用limit限制返回数
SKIP:使用skip进行跳过
IDHACK:针对_id进行查询
SHARDING_FILTER:通过mongos对分片数据进行查询
COUNT:利用db.coll.explain().count()之类进行count运算
COUNTSCAN:count不使用Index进行count时的stage返回
COUNT_SCAN:count使用了Index进行count时的stage返回
SUBPLA:未使用到索引的$or查询的stage返回
TEXT:使用全文索引进行查询时候的stage返回
PROJECTION:限定返回字段时候stage的返回

对于普通查询,我希望看到stage的组合(查询的时候尽可能用上索引):
Fetch+IDHACK
Fetch+ixscan
Limit+(Fetch+ixscan)
PROJECTION+ixscan
SHARDING_FITER+ixscan
COUNT_SCAN
不希望看到包含如下的stage:
COLLSCAN(全表扫描),SORT(使用sort但是无index),不合理的 SKIP,SUBPLA(未用到index的$or),COUNTSCAN(不使用index进行count)

update$set 修改器
db.getCollection('user').update({"_id":4},{"$set":{"age":2}})没有的字段会自动添加
db.getCollection('user').update({"_id":4},{"$set":{"email":"45612348945"}})
$inc 字段自增1,没有该字段就初始化字段数值为1
db.getCollection('user').update({"_id":4},{"$inc":{"age":1}})
一对一或一对多的关系可以用数组来表示$addToSet 重复的不在添加
db.getCollection('user').update({"_id":7},{"$addToSet":{"roles": { id: 1, name: "yuangong5"}}})$push可以重复添加
db.getCollection('user').update({"_id":7},{"$push":{"roles": { id: 1, name: "yuangong5"}}})循环 排序 取前三个
db.getCollection('user').update({ _id: 7 },{$push: {roles: {$each: [ { id: 1, name: "yuangong1" }, {id: 2, name: "yuangong2"  }, { id: 3, name: "yuangong3"  } ,{ id: 4, name: "yuangong4" }],$sort: { id: -1 },$slice: 3}}}
)$elemMatch 遍历每个数组匹配条件
db.getCollection('user').find({"roles": {$elemMatch:{"name" : "yuangong3"} }})
db.getCollection('user').find({"roles.name":"yuangong4"})

db.getCollection('user').find({"roles.name":"yuangong4"},{"roles.$":1})

$pop操作符移除数组中的第一个或者最后一个元素(1为最后一个元素,
-1为第一个元素)
db.getCollection('user').update({"_id":7},{"$pop":{"roles": -1}})$pull操作符从现有数组中移除与指定条件匹配的值或值的所有实例
db.getCollection('user').update({"_id":7},{"$pull":{"roles": {"name" : "yuangong3","id":3}}},{multi: true})

高级管道查询 Aggregate

管道操作符作为“键”,所对应的“值”叫做管道表达式。 {match:{status:”A”}}
$match称为管道操作符,而{status:”A”}称为管道表达式

$project 可以从子文档中提取字段,可以重命名字段,可以移除字段

db.getCollection('user').aggregate([
{$project: {“_id”:0,                          // 不显示“sex”:1,                           // 显示“newname”:“$age“      // 重命名}}
])db.getCollection('user').aggregate([
{$match :{ "_id":{"$gt":90}}},
{
$group: { _id: {sex: ‘$sex’},     // 根据sex字段分组count: {$sum: 1},total:{$sum:"$age"},maxAge:{$max:"$age"},minage:{$min:"$age"},avg:{$avg:"$age"}}
}
])

`

求最大 最小 平均
db.getCollection('user').aggregate([
{$match :{ "_id":{"$gt":90}}},
{
$group: { _id: {age: '$age'},count: {$sum: 1},total:{$sum:"$age"},maxAge:{$max:"$age"},minage:{$min:"$age"},avg:{$avg:"$age"}}
},
{$match: {avg: {$gt: 18}}},
{ $sort: { maxAge : -1 } },
{ $skip: 5 },
{ $limit: 10 }
])多表联合查询
db.getCollection('user').aggregate([
{$match:{"_id":{"$gte":20}}
},
{  $lookup:{from : "order",localField:"_id",foreignField:"user_id",as : "order"                }           },
{$match:{"order.price":{"$gte":50}}
}
])


特殊的语法


高级MapReduce

在用MongoDB查询返回的数据量很大的情况下,做一些比较复杂的统计和聚合操作做花费的时间很长的时候,可以用MongoDB中的MapReduce进行实现
MapReduce是一种编程模型,是个非常灵活和强大的数据聚合工具。它的好处是可以把一个聚合任务分解为多个小的任务,分配到多服务器上并行处理。MongoDB也提供了MapReduce,当然查询语肯定是JavaScript。
MongoDB中的MapReduce主要有以下几阶段:
Map:把一个操作Map到集合中的每一个文档
Shuffle: 根据Key分组对文档,并且为每个不同的Key生成一系列(>=1个)的值表(List of values)。
Reduce: 处理值表中的元素,直到值表中只有一个元素。然后将值表返回到Shuffle过程,循环处理,直到每个Key只对应一个值表,并且此值表中只有一个元素,这就是MR的结果。
Finalize:此步骤不是必须的。在得到MR最终结果后,再进行一些数据“修剪”性质的处理。

map: function(){emit(this.id,this.price);},
// 函数内部要调用内置的emit函数 根据id分组,把所有相同id的price放到一个数组里面reduce: function(key,values){ return Array.sum(values);},
//map中的数据传到reduce函数中 key是id price是valueout: <output>, // 输出到某一个集合中,注意本属性来还支持如果输出的集合如果已经存在了,那是替换,合并还是继续reduce? 另外还支持输出到其他db的分片中,具体用到时查阅文档,筛选出现的键名分别是_id和value;query: <document>, // 一个查询表达式,是先查询出来,再进行mapReduce的sort: <document>, // 发往map函数前先给文档排序limit: <number>, // 发往map函数的文档数量上限,该参数貌似不能用在分片模式下的mapreducefinalize: function(key, reducedValue) {return modifiedObject; }, // 从reduce函数中接受的参数key与reducedValue,并且可以访问scope中设定的变量scope: <document>, // 指定一个全局变量,能应用于finalize和reduce函数jsMode: <boolean>, // 布尔值,是否减少执行过程中BSON和JS的转换,默认true,true时BSON-->js-->map-->reduce-->BSON,false时 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可处理非常大的mapreduce。verbose: <boolean> // 是否产生更加详细的服务器日志,默认true

索引

单字段索引
MongoDB支持所有数据类型中的单个字段索引,并且可以在文档的任何用户定义字段上定义。需要注意的是,对于单个字段索引,索引键的排序顺序无关紧要,因为MongoDB可以在任一方向读取索引
创建
db.getCollection(‘user’).ensureIndex({“age”:1} )
查看
db.getCollection(‘user’).getIndexes()
删除
db.getCollection(‘user’).dropIndex(“age_1”)
复合索引
通常我们需要在多个字段的基础上搜索表/集合,这是非常频繁的。 如果是这种情况,我们可能会考虑在MongoDB中制作复合索引。 复合索引支持基于多个字段的索引,这扩展了索引的概念并将它们扩展到索引中的更大域。制作复合索引时要注意的一个重要事项是字段顺序很重要
db.getCollection(‘order’).ensureIndex({“user_id”:1,“price”:1} )

建立复合索引,索引中两字段前后顺序与查询条件字段在数量一致的情况下,顺序不影响使用索引查询;
当复合索引中的字段数量与查询条件字段数量不一致情况下,以复合索引字段前置优先规则;
排序的方向与索引的方向完全一致或完全相反时可以用到索引,其他情况用不到索引;

地理空间索引:
MongoDB允许我们通过使我们能够在文档中存储Geo-JSON集合来在我们的数据库中保存地理空间形状。 为了有效查询地理空间数据,MongoDB在内部提供了两种类型的索引:返回结果时使用平面几何的2d索引使用球面几何体返回结果的2d球体索引详细了解这些索引如何在这里工作。 通过我们数据库中的地理空间形状,我们可以轻松运行查询以查找当前位置附近的汉堡联合,而地理空间索引有助于更快地执行此搜索。
文本索引:
MongoDB还提供了在文本字段上创建索引的功能,该索引还支持在集合中搜索某些字符串内容。 应注意,这些索引不存储诸如“该”,“一个”,“或”之类的停用词。 在文本索引中,单词仅用于存储根词
文本索引是不区分大小写和不区分大小写的通过文本索引的高性能测量,
MongoDB对Elasticsearch提出了严峻的挑战,Elasticsearch是一个主要用于文本搜索查询的数据库。
哈希索引:
这种类型的索引允许我们对内容执行基于哈希的分片。 在这种类型的索引中,键的值被散列。 由于这个原因,这些索引只能支持相等匹配过滤器查询,并且不能在基于范围的查询上工作。如果我们想在索引上运行范围查询,我们可能必须在同一个字段上创建多个索引,其中一个可以是常规索引,另一个可以是散列索引。 最后,Hashed索引将浮点字段截断为整数。 应尽可能避免对散列字段使用浮点。
索引的属性
唯一的索引
这些索引可以通过规范使其成为唯一的。这样,当要求单个字段索引保持唯一时,它将拒绝该密钥的集合中已存在的值。 MongoDB中的任何索引都可以是唯一的。在复合索引中,索引值的唯一性通过与组成复合索引的键对应的值的组合来维持。
部分索引
如果您知道只需要为指定的键或一组键索引某些文档,我们可以通过指定过滤器查询将索引转换为部分索引。只有通过此过滤器的文档才会在指定字段上编制索引。这样,部分索引具有更低的存储要求,并且比正常索引快得多,因为数据量较少。需要注意的是,只有在部分索引可以满足完整查询的情况下,查询才会针对部分索引运行。
稀疏索引
索引的稀疏属性确保索引仅包含实际包含索引字段的文档的条目。稀疏索引完全跳过没有索引字段的文档。应注意,部分索引优于稀疏索引,因为稀疏索引的所有功能都可以通过具有更多添加的部分索引来实现
TTL索引
可以设置过期时间的索引,时间到了之后会自动删除该文档(可用作缓存);。
固定长度的集合

固定集合可以声明collection的容量大小,其行为类似于循环队列。数据插入时,新文档会被插入到队列的末尾,如果队列已经被占满,那么最老的文档会被之后插入的文档覆盖。
固定集合特性:固定集合很像环形队列,如果空间不足,最早的文档就会被删除,为新的文档腾出空间。一般来说,固定集合适用于任何想要自动淘汰过期属性的场景。
固定集合应用场景
比如日志文件,聊天记录,通话信息记录等只需保留最近某段时间内的应用场景,都会使用到MongoDB的固定集合。
固定集合的优点
1.写入速度提升。固定集合中的数据被顺序写入磁盘上的固定空间,所以,不会因为其他集合的一些随机性的写操作而“中断”,其写入速度非常快(不建立索引,性能更好)。
2.固定集合会自动覆盖掉最老的文档,因此不需要再配置额外的工作来进行旧文档删除。设置Job进行旧文档的定时删除容易形成性能的压力毛刺。
不同于普通集合,固定集合必须在使用前显式创建。
例如,创建固定集合coll_testcapped,大小限制为1024个字节。
db.createCollection(“coll_testcapped”,{capped:true,size:1024});
除了大小,创建时还可以指定固定集合中文档的数据量。
例如,创建固定集合coll_testcapped,大小限制为1024个字节,文档数量限制为100。
db.createCollection(“coll_testcapped2”,{capped:true,size:1024,max:100});
创建固定集合还有另一途径,就是将普通集合装换为固定集合,使用的命令是convertToCapped。
例如将testcol1集合转换为一个大小为1024字节的固定集合:
db.runCommand({“convertToCapped”:“testcol1”,“size”:1024})

设计应用

反范式化

1 冗余: 把需要的字段都冗余到一个文档里面
2 内嵌:文档里有一个数组字段.
一对多的场景, 一遍文章 多条评论 .
购物车 数量上限(固定长度的集合) 过期时间(TTL索引)
3 引用: 多对多的关系

优化数据的操作:
优化文档的增长
如果一个文档的增长是可知的,第一次保存时创建一个占用空间较大的字段, 以后更新操作的时候去掉这字段 $unset, 避免文档位置移动降低写的效率.

数据库分库
每个数据库都有自己的一个读写锁 每一个数据库在磁盘上有自己的一个文 件夹(意味着可以让不同的数据库存放在不同的磁盘分卷上)
MongoDB 3.4版本,写操作的锁定粒度在表中数据记录(document)级 别

skip深度分页性能


Sort 操作是把数据全都拿到内存当中再进行排序的,为了节约内存,默认给sort操作限制了最大的内存为32Mb.
查询语句db.getCollection(‘baiduNewsSynopsisDto’).find({}).sort({createDate:-1}).skip(50).limit(20)
查看索引 已经创建了createDate 字段的索引.
RAM:
随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质
原因: Skip 查询也是一条一条数的,索引用不了.
Mongdb的索引:B-树
缺点:B-树结构不能用于排名计算
优点: B-树是专门为外部存储器设计的,如磁盘,它对于读取和写入大块数据有良好的性能.
结论: 数据量大(超过50万)的时候分页不建议使用skip
方案一: 最多显示100页
方案二:
db.find({id:{&gt:20000}}).sort({id:-1}).limit(20)

分片

分片可以解决什么问题
高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量 会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的 内存而将压力转移到磁盘IO上。
为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。
  垂直扩展:增加更多的CPU和存储资源来扩展容量。
  水平扩展:将数据集分布在多个服务器上。水平扩展即分片。
复制与分片的区别:
复制时让多台服务器都拥有同样的数据副本,每一台服务器都是其他服务 器的镜像,而每一个分片都和其他分片拥有不同的数据子集。
1.对集群进行抽象,让集群“不可见”
  MongoDB自带了一个叫做mongos的专有路由进程。mongos就是掌握统一路口的路由器,其会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。
2.保证集群总是可读写
  MongoDB通过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就可以确保有服务器换掉时,其他的从库可以立即接替坏掉的部分继续工作。
3.使集群易于扩展
  当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。
片键:
数据的分片是以集合为基本单位的,集合中的数据通过片键(Shard key) 被分成多部分。其实片键就是在集合中选一个键,用该键的值作为数据拆 分的依据
没有被分片的集合所有的数据都是存在一个片中的, 用了分片的集合被分成 多个数据块存放在不同的位置.
注意事项:
分片键是不可变。
分片键必须有索引。
分片键大小限制512bytes。
分片键用于路由查询。
MongoDB不接受已进行collection级分片的collection上插入无 分片键的文档(也不支持空值插入)
片键的类型:
1.升序片键:
date 自增的ID 这些字段作为片键, 由于是自增的 每次数据都会 存放到 $maxKey 最大的数据块,这个块只能是位于一个分片上,
所以每次写的请求都是分发到同一个分片上,均衡器再去均衡,在不同的分片 上进行大块的均衡,正常来说应该只是小范围的均衡.
2.随机片键:
UUID 用户名 MD5散列 写入是随机分发的 个分片的数据比较均 衡, 缺点 随机访问超出RAM大小的数据时效率不高;
3.基于位置的片键:
可以使用户的IP,经纬度 或者地址 ,这里的位置比较抽象,数据会根据这个"位 置"分组,所有与该键值相近的文档都会存放在同一个块中

分片的策略
1.范围分片
MongoDB按照片键的范围把数据分成不同部分。在使用分片键做范围划分的系统中,相近的分片键文档很可能存储在同一个数据块中,因此也会存储在同一个分片中。
2.哈希分片
分片过程中利用哈希索引作为分片的单个键,且哈希分片的片键只能使用一个字段,而基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀.缺点
范围查询要分发到后端所有的Shard才能找出满足条件的文档。
3.组合分片
组合分片是比较好的一种分片的选择
coarseLocality:应该是一个大粒度的局部字段。比如MONTH月份升序字段。
search:是一个经常用来查找的字段。

Chunk 数据块

在一个分片内部,MongoDB还是会把数据分为chunks,每个chunk  代表这个shard server内部一部分数据使用chunk来存储数据
进群搭建完成之后,默认开启一个chunk,大小是64M,
存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设    置更大的chunk
chunk会被自动均衡迁移
use config
db.settings.save( { _id:"chunksize", value: <sizeInMB> } )

均衡器: 周期性的检查数据块的大小是否均衡,若不均衡 就拆分,每个mongs 都会不定期的把自己变成均衡器

如果一个chunk只包含一个分片键值,mongodb 就不会split这个chunk,即使这个chunk超过了 chunk需要split时的大小。所以分片键的选择非常重要。
这里举个例子,比如我们使用日期(精确到日) 作为分片键,当某一天的数据非常多时,这个分片键值(比如2019/12/12)的对应的chunk会非常大,
超过64M,但是这个chunk是不可分割的。这会造成数据在各个分片中不平衡,出现性能问题。

手动设置块存储数据的范围
$minKey $maxKey 位于这之间的数据就会存放到这个块.

服务器管理

副本集介绍

是一组服务器,其中一个主服务器和多个备份服务器,主挂掉 会自动选一个新的主.
备份节点默认不支持读的请求,(为了保证一致性),需要设置.
备份节点自动服复制功能在主节点复制,不支持写入的操作.

副本集的设计
大多数:选择主节点的时候需要大多数的备份节点,要超过一半以上的副本集才是大多数.
举例:5个副本集 挂掉3个, 2个好的 选不出来主节点,2个达不到大多数的要求
副本集的数量最好是奇数个(最小的组合 一主两从).

副本集读写

从应用程序链接副本集

链接集群与链接单台机器很像,可以提供一个副本集的列表,或者只有一个副本集的地址也可以,驱动程序链接到某一个子节点的时候,会通过子节点获取到其他成员的地址.
默认情况 所有的请求都将路由到主节点,副本集只在后台默默的备份.
服务器 配置子节点可读

应用程序驱动通过read reference来设定如何对复制集进行读写操作,默认客户端驱动所有的读操作都是直接访问primary节点的,从而保证了数据的严格一致性。
支持五种 read preference模式:
1.primary:主节点,默认模式,读操作只在主节点
2.primaryPreferred:首选主节点,大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点。
3.secondary:从节点,读操作只在从节点,如果从节点不可用,报错或者抛出异常。
4.secondaryPreferred:首选从节点,大多情况下读操作在从节点,特殊情况(如单主节点架构)读操作在主节点。
5.nearest:最邻近节点,读操作在最邻近的成员,可能是主节点或者从节点,关于最邻近的成员请参考。

集群架构



成员配置: 选举仲裁者,只参与选举不保存数据,优点满足大多数, 最多只有 一 个仲裁者
优先级: 表示一个节点想成为主节点的渴望程度, 取值0-100,默认是1,如果 是0 永不会成为主节点.
同步: mongdb的同步是基与日志是实现的,操作日志包含主节点的每一 次操作.
成员之间的状态与通信: 心跳.

集群选举

选举: 当一个成员与主节点无法到达时,它会申请成为主节点
选举的过程: 我能不能当主
a. 是否看见复制集中有Majority(大多数心跳链接)在线。 b. 自身priority大于0。 c. 自身不为arbiter(仲裁者:只参与选举)。 d. 自身opTime不能落后于最新节点10s以上(日志记录)。
为什么选着他当主
以下的判断:A. 复制集中存在主节点,投反对票。B.可参与选举的节点中有priority高于请求为主的节点存在时,投反对票。

总结:选举过程比较复杂 也比较耗时几秒到几十秒
mongdb也支持 传统的主从模式 缺点是 不会有故障转移,这种模式以后将会被废弃掉.可以从主从模式切换到副本集模式

集群的搭建

Centos7.0 linux
下载Linux版本的mong安装包
http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.0.4.tgz

Mongo的目录文件就是这些有些必要的文件需要手动创建
安装位置 usr/local/mongdb

  1. mkdir -p /usr/local/mongodb/data/ #创建数据存储目录
  2. mkdir -p / usr/local/mongodb/log/ #创建日志存储目录
  3. vi / usr/local/mongodb/bin/ mongdb.conf #启动需要用到的配置件

dbpath = /usr/local/mongodb/data/db #数据文件存放目录
logpath = /usr/local/mongodb/logs/mongodb.log #日志文件存放目录
port = 27017 #端口
fork = true #以守护程序的方式启用,即在后台运行
bind_ip=0.0.0.0 #任何ip都可以连接这个服务
启动服务(不需要验证)
bin/ mongod -f mongodb.conf
关闭服务 ps aux|grep mong
Kill PID
创建用户
Mongo
Use admin
db.createUser({user:“admin”,pwd:“123456”,roles:[{role:“userAdminAnyDatabase”,db:“admin”}]})

关闭防火墙 systemctl stop firewalld.service
客户端连接服务便可以使用了

roles:指定用户的角色,可以用一个空数组给新用户设定空角色;在roles字段,可以指定内置角色和用户定义的角色。role里的角色可以选:

Built-In Roles(内置角色):
1. 数据库用户角色:read、readWrite;
2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
4. 备份恢复角色:backup、restore;
5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
6. 超级用户角色:root
// 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)
7. 内部角色:__system

具体角色:

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

刚建立了 userAdminAnyDatabase 角色,用来管理用户,可以通过这个角色来创建、删除用户。

开启验证
mongod -f mongodb.conf --auth

mongdb副本集的安装教程
环境
192.168.118.22
192.168.118.32
192.168.118.24
1 在每台服务器上安装单机版的mongdb
2 每台服务器 修改启动时的配置文件
vi / usr/local/mongodb/bin/ mongdb.conf
添加一行关于副本集的设置 (最后一行)
dbpath = /usr/local/mongodb/data/db #数据文件存放目录
logpath = /usr/local/mongodb/logs/mongodb.log #日志文件存放目录
port = 27017 #端口
fork = true #以守护程序的方式启用,即在后台运行
bind_ip=0.0.0.0
replSet=rs0 #副本集名称

3 修改完成重新启动 连接任意一个shell 执行
conf=
{
“_id” : “rs0”,
“members” : [
{ “_id” : 0, “host” : “192.168.118.32:27017” },
{ “_id” : 1, “host” : “192.168.118.24:27017” },
{ “_id” : 2, “host” : “192.168.118.22:27017” }
]
}

rs.initiate(conf)
4 以上操作完成 副本集创建完成 查看结果
rs.conf()

各个副本集的信息都可以查看的到
rs.isMaster()

IsMaster 为true 说明是主节点
只有在主节点才可以插入 其他节点不可以插入

分片集群的搭建
MongoDB分片集群由mongos路由进程(轻量级且非持久化进程)、复制集组成的片shards(分片一般基于复制集故障转移和冗余备份功能)、一组配置服务器(存储元数据信息,一般冗余3台)构成。
192.168.118.22 分片0分片1 配置 路由
192.168.118.32 分片0分片1 配置
192.168.118.24 分片0分片1 配置

配置rs0分片
dbpath = /usr/local/mongodb/db_rs0/data/
logpath = /usr/local/mongodb/db_rs0/logs/1.log
logappend = true
journal = true
port = 40000
fork = true
maxConns = 5000
bind_ip = 0.0.0.0
replSet = rs0
shardsvr = true
auth = false

配置rs1分片
dbpath = /usr/local/mongodb/db_rs0/data/
logpath = /usr/local/mongodb/db_rs0/logs/1.log
logappend = true
journal = true
port = 40000
fork = true
maxConns = 5000
bind_ip = 0.0.0.0
replSet = rs1
shardsvr = true
auth = false

配置服务器

dbpath = /usr/local/mongodb/db_configs/data/
logpath = /usr/local/mongodb/db_configs/logs
logappend = true
port = 40002
maxConns = 5000
bind_ip = 0.0.0.0
replSet = cfgset
configsvr = true
auth = false
fork = true

路由服务器

logpath = /usr/local/mongodb/mongos/logs/
logappend = true
port = 40003
fork = true
maxConns = 5000
bind_ip = 0.0.0.0
configdb = cfgset/192.168.118.22:40002,192.168.118.24:40002,192.168.118.32:40002

  1. 启动所有的rs0 rs1 和 配置服务器

  2. mongod --config /usr/local/mongodb/db_rs0/config_rs0/rs0.conf

  3. mongod --config /usr/local/mongodb/db_rs1/config_rs1/rs1.conf

  4. mongod --config /usr/local/mongodb/db_configs/config_cfgservice/cfgserver.conf

  5. 初始化副本集rs0 rs1

rs.initiate({_id:“rs1”, members:[{_id:1,host:“192.168.118.22:40001”},{_id:2,host:“192.168.118.24:40001”},{_id:3,host:“192.168.118.32:40001”}]})
rs.initiate({_id:“rs0”, members:[{_id:1,host:“192.168.118.22:40000”},{_id:2,host:“192.168.118.24:40000”},{_id:3,host:“192.168.118.32:40000”}]})

  1. 初始化配置服务器

rs.initiate({_id:“cfgset”,configsvr:true, members:[{_id:1,host:“192.168.118.22:40002”},{_id:2,host:“192.168.118.24:40002”},{_id:3,host:“192.168.118.32:40002”}]})
查看执行结果rs.status()
{
“ok” : 1,
“operationTime” : Timestamp(1559547423, 1),
“gleStats":"lastOpTime":Timestamp(1559547423,1),"electionId":ObjectId("000000000000000000000000"),"gleStats" : { "lastOpTime" : Timestamp(1559547423, 1), "electionId" : ObjectId("000000000000000000000000") }, "gleStats":"lastOpTime":Timestamp(1559547423,1),"electionId":ObjectId("000000000000000000000000"),"clusterTime” : {
“clusterTime” : Timestamp(1559547423, 1),
“signature” : {
“hash” : BinData(0,“AAAAAAAAAAAAAAAAAAAAAAAAAAA=”),
“keyId” : NumberLong(0)
}
}
}
7. 启动路由服务 路由的启动方式不一样
mongos --config /usr/local/mongodb/db_mongo/cfg_mongo.conf

  1. 添加分片
    sh.addShard(“rs0/192.168.118.22:40000,192.168.118.24:40000,192.168.118.32:40000”)
    sh.addShard(“rs1/192.168.118.22:40001,192.168.118.24:40001,192.168.118.32:40001”)

  2. 分片的表和数据库要特殊处理 片键要有索引
    mongos> use chavin
    switched to db chavin
    mongos> db.users.insert({userid:1,username:“ChavinKing”,city:“beijing”})

sharding version: {
“_id” : 1,
“minCompatibleVersion” : 5,
“currentVersion” : 6,
“clusterId” : ObjectId(“5cf4f0a047ab8a12968ff2cb”)
}
shards:
{ “_id” : “rs0”, “host” : “rs0/192.168.118.22:40000,192.168.118.24:40000,192.168.118.32:40000”, “state” : 1 }
{ “_id” : “rs1”, “host” : “rs1/192.168.118.22:40001,192.168.118.24:40001,192.168.118.32:40001”, “state” : 1 }
active mongoses:
“3.6.11-22-g7861aff” : 1
autosplit:
Currently enabled: yes
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:
{ “_id” : “chavin”, “primary” : “rs1”, “partitioned” : false }//
False说明没有分片保存
{ “_id” : “config”, “primary” : “config”, “partitioned” : true }
config.system.sessions
shard key: { “_id” : 1 }
unique: false
balancing: true
chunks:
rs0 1
{ “_id” : { “KaTeX parse error: Expected 'EOF', got '}' at position 13: minKey" : 1 }̲ } -->> { "_id"…maxKey” : 1 } } on : rs0 Timestamp(1, 0)

10.创建索引
mongos> db.users.ensureIndex({city:1})
设置分片
10. mongos> sh.shardCollection(“chavin.users”,{city:1})
11. 保存数据
12. mongos> for(var i=1;i<10000;i++) db.users.insert({userid:i,username:“chavin”+i,city:“beijing”})
13. WriteResult({ “nInserted” : 1 })
14. mongos> for(var i=1;i<10000;i++) db.users.insert({userid:i,username:“dbking”+i,city:“changsha”})
15. WriteResult({ “nInserted” : 1 })
16. mongos> sh.status()

常用的语句整理

-- 修改数据
db.getCollection('crawlCommentDto').update({"crawlCommentInfoId":{$gt:152000}},{$set:{'isAnalyze':0}},{multi:true})
-- 创建联合唯一索引
db.getCollection('crawlCommentDto').ensureIndex({name:1,commentDate:1,baseMonitorMainId:1},{unique:true})
-- 创建索引
db.getCollection('crawlCommentDto').ensureIndex({brandId:1})
-- 删除数据
db.getCollection('82_1531878209641').remove({"monitoringObjectId":{$gt:186217}})
-- 循环遍历
db.getCollection('crawlCommentDto').find({"crawlCommentInfoId":{"$lt":187773}}).forEach( function(myDoc) { print( "user: " + myDoc.name ); } );
-- 分组统计重复的数据
db.crawlCommentDto.aggregate([
{ $match : { baseMonitorMainId : { $gt : 90, $lte : 18000 } } },
{
$group: { _id: {name: '$name',comment: '$comment',baseMonitorMainId: '$baseMonitorMainId'},count: {$sum: 1},dups: {$addToSet: '$_id'},}
},
{
$match: {count: {$gt: 1}}
}
],{
allowDiskUse: true
})-- 删除重复数据
db.crawlCommentDto.aggregate([
{ $match : { baseMonitorMainId : { $gt : 90, $lte : 18000 } } },
{
$group: { _id: {name: '$name',comment: '$comment',baseMonitorMainId: '$baseMonitorMainId'},count: {$sum: 1},dups: {$addToSet: '$_id'},}
},
{
$match: {count: {$gt: 1}}
}
],{
allowDiskUse: true
}).forEach(function(doc){doc.dups.shift();db.crawlCommentDto.remove({_id: {$in: doc.dups}});
})
-- 多表联合查询
db.getCollection('thumbsUp').aggregate([
{$match:{"_id":94}  },
{  $lookup:{from : "thumbsUpDto",localField:"_id",foreignField:"objId",as : "base"                }           }
])db.getCollection('crawlCommentDto').aggregate([
{ $match : {isAnalyze:1, 'createTime' : { '$gte' : ISODate('2017-04-20T00:00:00Z'),'$lte' : ISODate('2027-04-21T00:00:00Z') } }
},
{
$group: { _id: {baseMonitorMainId: '$baseMonitorMainId',brandId: '$brandId',type: '$type',dataSource: '$dataSource'},count: {$sum: 1},}
},{'$project' : {'baseMonitorMainId':'$_id.baseMonitorMainId' ,type:'$_id.type' , dataSource:'$_id.dataSource' , commentNum:'$count' ,_id:0,brandId:'$_id.brandId'}},])--- 分组后 按条件在统计 cond--> havingdb.getCollection('crawlCommentDto').aggregate([
{ $match : {isAnalyze:1,baseMonitorMainId:2008 }
},
{
$group: { _id: {baseMonitorMainId: '$baseMonitorMainId'},                good: { $sum: { $cond :  [{ $eq : ['$type', 1]}, 1, 0]} },middle: { $sum: { $cond :  [{ $eq : ['$type', 2]}, 1, 0]} },bad: { $sum: { $cond : [{ $eq : ['$type', 3]}, 1, 0]} },total: { $sum: 1 }}
},
{'$project' : {'baseMonitorMainId':'$_id.baseMonitorMainId',_id:0,good:1,middle:1,bad:1,total:1,name:1}
},
])

mongdb系列之最详细基础知识相关推荐

  1. Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  2. Python系列 之 matplotlib库 基础知识

    Python系列 之 matplotlib库 基础知识学习 Pyplot 简单示例 中文显示问题 注册全局字体 font_manager.FontProperties注册字体 Figure Figur ...

  3. 考试备战系列--软考--02基础知识复习

    这部分主要是计算机基础知识的概念介绍,相关系列文章如下所示. 考试备战系列--软考--01基础架构概念 考试备战系列--软考--02基础知识复习 考试备战系列--软考--03综合知识复习 考试备战系列 ...

  4. python详细基础知识笔记

    详细基础知识笔记 注: ·第一章 学习准备 1.1高级语言.机器语言.汇编语言 1.2 汇编.解释 1.3 静态语言.脚本语言 1.4 Python的历史 1.5 Python语言的优点.缺点 1.6 ...

  5. Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  6. 并发系列1:并发基础知识

    本文是Java并发系列的开篇,主要讲一些并发的计算机基础知识.本系列所讲的知识框架也是基于<Java并发编程的艺术>一书,所讲的内容也多围绕于并发concurrent包下的类. 正文 并发 ...

  7. 深入浅出Yolo系列之Yolov3Yolov4Yolov5核心基础知识完整讲解

    深入浅出Yolo系列之Yolov3&Yolov4&Yolov5核心基础知识完整讲解

  8. 硬件设计电源系列文章-DCDC转换器基础知识

    目录 概要 整体架构流程 技术名词解释 1.DCDC 2.同步整流: 3.异步整流 技术细节 1.开关稳压器的种类: 2.异步整流与同步整流的原理: 3.反馈控制方式 小结 概要 提示:这里可以添加技 ...

  9. Cisco系列第一节-----前提基础知识

    Cisco系列文章目录 第一章:前提基础知识链接 文章目录 Cisco系列文章目录 一.DTE与DCE 1.DTE 2.DCE 二.连接线缆的种类 三.思科模拟器的使用 四 基础实验过程体验 1.添加 ...

最新文章

  1. 计算机睡眠时间 win7,技术编辑帮你win7系统设置计算机睡眠时间的详细解法
  2. KMP模版 KMP求子串在主串出现的次数模版
  3. 常用损失函数(L1、L2、SSIM和MS-SSIM)对比简介
  4. 不断进化的分支和需求管理
  5. PID控制器改进笔记之三:改进PID控制器之正反作用
  6. ios vue 添加本地音乐_vue 项目,ios上audio音频 无法自动播放
  7. HTML5学习之视频与音频(三)
  8. gradle指令linux守护,gradle之gradlew最全指令攻略
  9. 【互联网周刊】2022年第6期摘录
  10. C# 自定义网格 dataGridView 三角箭头移动 获取当前行列序号 滚动条显示改变 滚动条定位索引
  11. 6.跑步者--并行编程框架 ForkJoin
  12. Reeder for Mac 5.1 优秀的RSS阅读器
  13. selenium基础自学七(获取超链接)
  14. 那些Explain参数代表着什么?
  15. 编程该学什么以及vc++一些心得
  16. 中国鼠标行业销售动态及营销形势分析报告(新版)2022-2027年
  17. P8大佬出书了!送送送!
  18. linux l7filter命令行,iptables--L7-filter实现高级管理
  19. 高中计算机阅卷要求,给考生:了解中考电脑阅卷规则,读完多拿20分!
  20. 计算机财务基础知识,电脑知识:文员,财务必备的电脑基础!

热门文章

  1. lua时间戳和日期转换
  2. 网络安全形势严峻:国内黑灰产业产值达千亿
  3. c语言共阴极数码管数字6,共阴数码管 显示数字 C语言程序
  4. C语言——解数独程序[源码]
  5. mysql数据库基础语句讲解
  6. 程序员vs计算机教师,薪资大PK!教师VS程序员,你想不到的事实!
  7. speedoffice(Excel)表格怎么一次插入多行?
  8. eclipse neon配置 maven
  9. 优化算法(四)——粒子群优化算法(PSO)
  10. 【Adobe】Photoshop :Windows 系统 Photoshop 软件更换许可指引