MongoDB

 

mongodb入门

基本介绍

MongoDB:是一个数据库 ,高性能、无模式、文档性,目前nosql中最热门的数据库,开源产品,基于c++开发。是nosql数据库中功能最丰富,最像关系数据库的。 java

为何mongodb很耗内存?读和写都是基于内存的linux

特性

1.面向集合文档的存储:适合存储Bson(json的扩展)形式的数据c++

2.格式自由,数据格式不固定,生产环境下修改结构均可以不影响程序运行; 正则表达式

3.强大的查询语句,面向对象的查询语言,基本覆盖sql语言全部能力算法

4.完整的索引支持,支持查询计划spring

5.支持复制和自动故障转移sql

6.支持二进制数据及大型对象(文件)的高效存储mongodb

7.使用分片集群提高系统扩展性shell

8.使用内存映射存储引擎,把磁盘的IO操做转换成为内存的操做数据库

相对关系型数据库结构

mongo实例->库->集合->文档

基础概念

数据库

集合

文档:最大16M 索引

数据类型

null  {"key":null}   null表示空值或者不存在该字段 

布尔   {"key","true"}  布尔类型表示真或者假 

32位整数  {"key":8}  存储32位整数,但再shell界面显示会被自动转成64位浮点数 

64位整数  {"key":{"floatApprox":8}}  存储64位整数,floatApprox意思是使用64位浮点数近似表示一个64位整数 

对象ID  {"key":ObjectId()}  12字节的惟一ID 

日期  {"key":new Date()} 

代码  {"key":function(){}} 

二进制数据 

未定义  {"key":undefined} 

数组  {"key":[16,15,17]} 

内嵌文档  {"user":{"name":"lison"}} 

Decimal128  {"price":NumberDecimal("2.099")} 

mongodb进阶

启动配置文件

storage:

   dbPath: "/usr/local/apache/mongoDB/mongodb-linux-x86_64-rhel70-3.4.10/data"

systemLog:

   destination: file

   path: "/usr/local/apache//mongoDB/mongodb-linux-x86_64-rhel70-3.4.10/logs/mongodb.log"

net:

   port: 27017

   http:

      RESTInterfaceEnabled: true

processManagement:

   fork: false

 

经常使用命令

show dbs :显示数据库列表 

show collections :显示集合列表 

db : 显示当前数据库 

db.stats() :显示数据库信息 

db.serverStatus() : 查看服务器状态 

db.dropDatabase():删除数据库 

db.help(),db.collection.help():内置帮助,显示各类方法的说明; 

db.users.find().size(),db.users.count():获取查询集合的数量;  

db.users.drop():删除集合包括索引; 

db.users.remove(); 仅删除集合的数据

db.shutdownServer()   优雅关机

nohup ./mongod -f mongodb.conf &   :配置文件方式启动mongo

./mongo localhost:27022   指定ip端口链接mongo

./mongod --shutdown -f mongodb.conf  优雅关机 

./mongodump -h localhost:27022 -d dbname -o dataPath    备份数据  原理执行查询,而后写入文件..

./mongorestore -h localhost:27022 -d  dbname dataPath --drop  恢复数据 --drop 已存在lison库则删除原数据库,去掉--drop则是合并

./mongoexport -h localhost:27022 -d dbname -c collection -f id,username,age,salary --type=csv -o dataPath   数据导出 -c :指定导出的集合; -f :要导出的字段; --type:导出的文件格式类型[csv,json]

./mongoexport -h localhost:27022 -d dbname -c collection dataPath --upsert   数据导入 --upsert 表示更新现有数据,若是不适用—upsert,则导入时已经存在的文档会报id重复,数据再也不插入,也可使用—drop删除原有数据

spring集成配置

xml

<!-- mongodb链接池配置-->
<mongo:mongo-client host="192.168.1.129" port="27017">
<mongo:client-options 
      write-concern="ACKNOWLEDGED"
      connections-per-host="100"
      threads-allowed-to-block-for-connection-multiplier="5"
      max-wait-time="120000"
  connect-timeout="10000"/> 
</mongo:mongo-client>>
 
<!-- mongodb数据库工厂配置-->
<mongo:db-factory dbname="lison" mongo-ref="mongo" />
 
<!-- mongodb模板配置-->
<bean id="anotherMongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<property name="writeResultChecking" value="EXCEPTION"></property>
</bean>

 

链接池配置

writeConcern

写入安全机制,是一种客户端设置,用于控制写入安全的级别:
ACKNOWLEDGED 默认选项,数据写入到Primary就向客户端发送确认
0 Unacknowledged 对客户端的写入不须要发送任何确认,适用于性能要求高,但不关注正确性的场景;
1 W1 数据写入后,会等待集群中1台发送确认
2 W2 数据写入后,会等待集群中两台台发送确认
3 W3 数据写入后,会等待集群中3台台发送确认
JOURNALED 确保全部数据提交到 journal file
MAJORITY 等待集群中大多数服务器提交后确认;

默认值:ACKNOWLEDGED

codecRegistry  编解码类,实现Codec接口:MongoClient.getDefaultCodecRegistry()  

minConnectionsPerHost  最小链接数,connections-per-host 

connectionsPerHost  最大链接数 :100

threadsAllowedToBlockForConnectionMultiplier  此参数跟connectionsPerHost的伺机为一个线程变为可用的最大阻塞数,超过此伺机数以后的全部线程将及时获取一个异常:5 

maxWaitTime 一个线程等待连接可用的最大等待毫秒数,0表示不等待 :1000 * 60 * 2 

maxConnectionIdleTime  设置池链接的最大空闲时间,0表示没有限制 :0

maxConnectionLifeTime  设置池链接的最大使用时间,0表示没有限制 :0

connectTimeout  链接超时时间 :1000*10 

alwaysUseMBeans  是否打开JMX监控 :false

heartbeatFrequency  设置心跳频率。 这是驱动程序尝试肯定群集中每一个服务器的当前状态的频率。 :10000

minHeartbeatFrequenc  设置最低心跳频率。 若是驱动程序必须常常从新检查服务器的可用性,那么至少要等上一次检查以免浪费:500

heartbeatConnectTimeout  心跳检测链接超时时间:20000

heartbeatSocketTimeout  心跳检测Socket超时时间:20000

mongodb客户端驱动

compass

robo 3t

studio 3t

增删改查与聚合

新增

insert

insertOne

insertMany

更新

替换更新

db.users.update({"username":"lison"},{"country":"USA"})

操做符更新

db.users.update({"username":"james"},{"$set":{"country":"USA"}})

query 查询条件,相似sql update查询内where后面的; 

update update的对象和一些更新的操做符(如$,$inc...)等,也能够理解为sql update查询内set后面的

$inc 指定值自增 

$set更新指定字段

$unset 将指定字段删除 

$rename 更新字段名称 

$ 定位到某一个元素 

$push 添加值到数组中,默认放在数组最后 

$addToSet 添加值到数组中,有重复则不处理 

$pop 删除数组第一个或者最后一个 

$pull从数组中删除匹配查询条件的值 

$pullAll 从数组中删除多个值 

$each 与$push和$addToSet等一块儿使用来操做多个值 

$slice 与$push和$each一块儿使用来操做用来缩小更新后数组的大小 

$sort 与$push、$each和$slice一块儿使用来对数组进行排序 

upsert  可选,这个参数的意思是,若是不存在update的记录,是否插入,true为插入,默认是false,不插入 
multi 可选,mongodb 默认是false,只更新找到的第一条记录,若是这个参数为true,就把按条件查出来多条记录所有更新
writeConcern  可选,写策略配置。 

注意

mongodb的更新都是原子的,mongodb全部的写操做都是有锁的。mongoDB 2.2以前锁级别为实例级别,mongoDB 2.23.2以前的版本锁级别为数据库级别,mongoDB 3.2之后,WiredTiger的锁级别是文档级别;
findAndModify命令:在同一往返过程当中原子更新文档并返回它;

删除(不会删除索引)

deleteOne

deleteMany

查询

经常使用查询选择器

范围

$eq  等于

$lt 小于

$gt 大于

$lte 小于等于

$gte 大于等于

$in 判断元素是否在指定的集合范围里  db.users.find({"username":{"$in":["lison", "mark", "james"]}}).pretty()
查询姓名为lison、mark和james这个范围的人

$all 判断数组中是否包含某几个元素,无关顺序 

$nin 判断元素是否不在指定的集合范围里 

布尔运算 

$ne 不等于,不匹配参数条件 

$not 不匹配结果   db.users.find({"lenght":{"$not":{"$gte":1.77}}}).pretty()
查询高度小于1.77或者没有身高的人
not语句 会把不包含查询语句字段的文档 也检索出来

$or有一个条件成立则匹配

$nor 全部条件都不匹配 

$and 全部条件都必须匹配 

$exists 判断元素是否存在   db.users.find({"lenght":{"$exists":true}}).pretty()
判断文档有没有关心的字段

其余 

. 子文档匹配

$regex 正则表达式匹配  

普通查询

映射

字段选择并排除其余字段:db.users.find({},{'username':1})
字段排除:db.users.find({},{'username':0})

排序

sort():db.users.find().sort({"username":1}).pretty()
1:升序 -1:降序

跳过和限制 

skip(n):跳过n条数据
limit(n):限制n条数据
e.g: db.users.find().sort({"username":1}).limit(2).skip(2)

查询惟一值

distinct():查询指定字段的惟一值,e.g:db.users.distinct("username")

示例

db.collection.find(query, projection)

db.users.find({"$and":[{"username":"lison"},{"age":18}]},{"username":0,"age":0})

db.collection.findOne(query, projection)

db.users.find({"$and":[{"username":"lison"},{"age":18}]},{"username":0,"age":0})

数组查询

字符串数组

数组单元素查询 

db.users.find({"favorites.movies":"蜘蛛侠"})
查询数组中包含"蜘蛛侠"

数组精确查找 

db.users.find({"favorites.movies":[ "杀破狼2", "战狼", "雷神1" ]},{"favorites.movies":1})
查询数组等于[ "杀破狼2", "战狼", "雷神1" ]的文档,严格按照数量、顺序;

数组多元素查询 

  • db.users.find({"favorites.movies":{"$all":[ "雷神1", "战狼" ]}},{"favorites.movies":1})
    查询数组包含["雷神1", "战狼" ]的文档,跟顺序无关,跟数量有关
  • db.users.find({"favorites.movies":{"$in":[ "雷神1", "战狼" ]}},{"favorites.movies":1})
    查询数组包含["雷神1", "战狼" ]中任意一个的文档,跟顺序无关,跟数量无关

索引查询

db.users.find({"favorites.movies.0":"妇联4"},{"favorites.movies":1})
查询数组中第一个为"妇联4"的文档

返回数组子集 

db.users.find({},{"favorites.movies":{"$slice":[1,2]},"favorites":1})
$slice能够取两个元素数组,分别表示跳过和限制的条数;

对象数组
单元素查询 

db.users.find({"comments":{
"author" : "lison6",
"content" : "lison评论6","commentTime" : ISODate("2017-06-06T00:00:00Z")}})
备注:对象数组精确查找

查找lison1 或者 lison12评论过的user ($in查找符)

db.users.find({"comments.author":{"$in":["lison1","lison12"]}}).pretty()
备注:跟数量无关,跟顺序无关;

查找lison1 和 lison12都评论过的user 

db.users.find({"comments.author":{"$all":["lison12","lison1"]}}).pretty()
备注:跟数量有关,跟顺序无关;

.查找lison5评语为包含"苍老师"关键字的user($elemMatch查找符)  

db.users.find({"comments":{"$elemMatch":{"author" : "lison5",
"content" : { "$regex" : ".苍老师."}}}}) .pretty()
备注:数组中对象数据要符合查询对象里面全部的字段,$全元素匹配,和顺序无关;

聚合查询

db.collection.aggregate()

$project:投影,指定输出文档中的字段; 

$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操做 

$limit:用来限制MongoDB聚合管道返回的文档数。 

$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。 

$unwind:将文档中的某一个数组类型字段拆分红多条,每条包含数组中的一个值。 

$group:将集合中的文档分组,可用于统计结果。 

$sort:将输入文档排序后输出。 

角色安全控制

角色分类

数据库通常角色(Database User Roles) 

每一个数据库都包含的通常角色;

read  

提供读取全部非系统集合和部分系统集合的数据的能力,系统集合包括:system.indexes,system.js和system.namespaces集合。

readWrite 

提供read角色的全部权限以及修改全部非系统集合和system.js集合上的数据的能力。

数据库管理角色(Database Administration Roles) 

每一个数据库都包含的数据库管理角色;

dbAdmin 

提供执行管理任务的能力,如与模式相关的任务,索引,收集统计信息。 此角色不授予用户和角色管理的权限。

userAdmin 

提供在当前数据库上建立和修改角色和用户的能力。

dbOwner 

提供对数据库执行任何管理操做的能力。 此角色结合了readWrite,dbAdmin和userAdmin角色授予的权限。

集群管理角色(Cluster Administration Roles) 

在admin数据库建立,用于管理整个数据库集群系统而不是特定数据库的角色。 这些角色包括但不限于副本集和分片群集管理功能。

clusterManager

在集群上提供管理和监视操做。 具备此角色的用户能够分别访问在分片和复制中使用的config和local数据库。

clusterMonitor 

为监控工具(如MongoDB Cloud Manager和Ops Manager监控代理)提供只读访问权限。

hostManager 

提供监视和管理服务器的能力。

clusterAdmin 

提供权限最高的群集管理访问。 此角色结合了由clusterManager,clusterMonitor和hostManager角色授予的权限。 此外,该角色还提供了dropDatabase操做。

备份和恢复角色(Backup and Restoration Roles) 

在admin数据库建立,用于专门的备份和恢复的角色

backup

提供备份数据所需的权限。 此角色提供足够的权限来使用MongoDB Cloud Manager备份代理,Ops Manager备份代理或使用mongodump。

restore

提供使用mongorestore恢复数据所需的权限

全数据库角色(All-Database Roles) 

在admin数据库建立,适用于除mongod实例中的local和config以外的全部数据库:

readAnyDatabase

提供与读取相同的只读权限,除了适用于群集中除本地和配置数据库之外的全部权限。 该角色还提供了整个集群上的listDatabases操做。

readWriteAnyDatabase 

提供与readWrite相同的读取和写入权限,除了它适用于群集中除本地和配置数据库之外的全部数据。 该角色还提供了整个集群上的listDatabases操做。

userAdminAnyDatabase

提供与userAdmin相同的用户管理操做访问权限,除了适用于群集中除本地数据库和配置数据库外的全部数据。

dbAdminAnyDatabase

提供与dbAdmin相同的数据库管理操做访问权限,除了它适用于除集群中的本地数据库和配置数据库之外的全部数据库管理操做。 该角色还提供了整个集群上的listDatabases操做。

超级角色(Superuser Roles)

全部资源的完整权限

root

提供对readWriteAnyDatabase,dbAdminAnyDatabase,userAdminAnyDatabase,clusterAdmin,还原和备份相结合的操做和全部资源的访问。

mogno服务开启安全认证方式

1.服务器启动加上auth参数,开启安全验证  ./mongod -f mongodb.conf --auth

2.数据库增长安全模式后,初始化一个“userAdminAnyDatabase“,经过客户端链接,使用admin数据库, 执行脚本

db.createUser({'user':'boss', 'pwd':'boss', 'roles':[{'role':'userAdminAnyDatabase', 'db':'admin'}]})

3.使用刚建立成功的用户登陆:db.auth("boss","boss"); 

4.切换到lison数据库,建立读写权限用户

use lison
db.createUser({'user':'lison','pwd':'lison','roles':[{'role':'readWrite','db':'lison'}]})

5.使用读写权限用户lison登陆,db.auth("lison","lison"),登陆后测试; 

代码安全模式链接方式

spring

<mongo:mongo-client host="192.168.1.142" port="27022" credentials="lison:lison@lison">
</mongo:mongo-client>

java代码

public void init() {
        MongoCredential createCredential = 
                MongoCredential.createCredential("lison", "lison", "lison".toCharArray());
        MongoClientOptions mco = MongoClientOptions.builder()
                .writeConcern(WriteConcern.JOURNALED)
                .connectionsPerHost(100)
                .readPreference(ReadPreference.secondary())
                .threadsAllowedToBlockForConnectionMultiplier(5)
                .maxWaitTime(120000).connectTimeout(10000).build();
        List<ServerAddress> asList = Arrays.asList(
                new ServerAddress("116.62.222.124",27022));
        this.client = new MongoClient(asList, createCredential,mco);
        db = client.getDatabase("lison");
        collection = db.getCollection("users");
    }

mongodb高级知识

存储引擎

MMAPV1

在3.2版本以前MMAPV1是默认的存储引擎

wiredTiger

3.4以上版本默认的存储引擎是wiredTiger,相对于MMAPV1其有以下优点:

读写操做性能更好,WiredTiger能更好的发挥多核系统的处理能力;

MMAPV1引擎使用表级锁,当某个单表上有并发的操做,吞吐将受到限制。WiredTiger使用文档级锁,由此带来并发及吞吐的提升

相比MMAPV1存储索引时WiredTiger使用前缀压缩,更节省对内存空间的损耗;

提供压缩算法,能够大大下降对硬盘资源的消耗,节省约60%以上的硬盘资源;

写入数据原理

 

Journaling

3.4以上版本默认的存储引擎是wiredTiger,相对于MMAPV1其有以下优点:

读写操做性能更好,WiredTiger能更好的发挥多核系统的处理能力;

MMAPV1引擎使用表级锁,当某个单表上有并发的操做,吞吐将受到限制。WiredTiger使用文档级锁,由此带来并发及吞吐的提升

相比MMAPV1存储索引时WiredTiger使用前缀压缩,更节省对内存空间的损耗;

提供压缩算法,能够大大下降对硬盘资源的消耗,节省约60%以上的硬盘资源;

写策略配置

写配置说明

 

Java代码实现写策略 

Q1:写策略配置相关的类是?

答:com.mongodb.WriteConcern,其中有以下几个经常使用写策略配置:
UNACKNOWLEDGED:不等待服务器返回或确认,仅能够抛出网络异常;
ACKNOWLEDGED:默认配置,等待服务器返回结果;
JOURNALED:等待服务器完成journal持久化以后返回;
W1 :等待集群中一台服务器返回结果;
W2 :等待集群中两台服务器返回结果;
W3 :等待集群中三台服务器返回结果;
MAJORITY:等待集群中多数服务器返回结果;

Q2:Java代码中如何加入写策略

答:Java客户端能够按两种方式来设置写策略:
在MongoClient初始化过程当中使用MongoClientOptions. writeConcern(writeConcern)来进行配置;
在写操做过程当中,也可动态的指定写策略,mongodb能够在三个层次来进行写策略的配置,既MongoClient、 MongoDatabase 、MongoCollection这三个类均可以经过WriteConcern方法来设置写策略;

Spring中如何配置写策略?

<mongo:mongo-client id="mongo" host="127.0.0.1" port="27017" >

        <mongo:client-options

            write-concern="NONE"

            />

    </mongo:mongo-client>

配置文件配置引擎

storage:
      journal:
            enabled: true
      dbPath: /data/zhou/mongo1/
      ##是否一个库一个文件夹
      directoryPerDB: true
      ##数据引擎
      engine: wiredTiger
      ##WT引擎配置
      wiredTiger:
           engineConfig:
                 ##WT最大使用cache(根据服务器实际状况调节)
                 cacheSizeGB: 1
                 ##是否将索引也按数据库名单独存储
                 directoryForIndexes: true
                 journalCompressor:none(默认snappy
           ##表压缩配置,性能: none>snappy>zlib,压缩比:zlib>snappy>none
           collectionConfig:
                 blockCompressor: zlib (默认snappy,还可选nonezlib)
           ##索引配置
           indexConfig:
                 prefixCompression: true

索引

索引管理

新增

db.collection.createIndex(keys, options)
语法中 Key 值为要建立的索引字段,1为指定按升序建立索引,若是你想按降序来建立索引指定为-1,也能够指定为hashed(哈希索引)。
语法中options为索引的属性,属性说明见下表

属性名

类型

说明

background

boolean

是否后台构建索引,在生产环境中,若是数据量太大,构建索引可能会消耗很长时间,为了避免影响业务,能够加上此参数,后台运行同时还会为其余读写操做让路

unique

boolean

是否为惟一索引

name

string

索引名字

sparse

boolean

是否为稀疏索引,索引仅引用具备指定字段的文档。

单键惟一索引:db.users.createIndex({username :1},{unique:true}); 

单键惟一稀疏索引:db.users. createIndex({username :1},{unique:true,sparse:true}); 

复合惟一稀疏索引:db.users. createIndex({username:1,age:-1},{unique:true,sparse:true}); 

建立哈希索引并后台运行:db.users. createIndex({username :'hashed'},{background:true}); 

删除

根据索引名字删除某一个指定索引:db.users.dropIndex("username_1"); 

删除某集合上全部索引:db.users.dropIndexs(); 

重建某集合上全部索引:db.users.reIndex(); 

查询集合上全部索引:db.users.getIndexes(); 

索引分类

单键索引 

在某一个特定的属性上创建索引,例如:db.users. createIndex({age:-1});
mongoDB在ID上创建了惟一的单键索引,因此常常会使用id来进行查询;
在索引字段上进行精确匹配、排序以及范围查找都会使用此索引;

复合索引 

在多个特定的属性上创建索引,例如:db.users. createIndex({username:1,age:-1,country:1});
复合索引键的排序顺序,能够肯定该索引是否能够支持排序操做;
在索引字段上进行精确匹配、排序以及范围查找都会使用此索引,但与索引的顺序有关;
为了内存性能考虑,应删除存在与第一个键相同的单键索引

多键索引 

在数组的属性上创建索引,例如:db.users. createIndex({favorites.city:1});针对这个数组的任意值的查询都会定位到这个文档,既多个索引入口或者键值引用同一个文档

哈希索引

不一样于传统的B-树索引,哈希索引使用hash函数来建立索引。
例如:db.users. createIndex({username : 'hashed'});
在索引字段上进行精确匹配,但不支持范围查询,不支持多键hash;
Hash索引上的入口是均匀分布的,在分片集合中很是有用; 

查询优化

1.开启慢查询

开启内置的查询分析器,记录读写操做效率:
db.setProfilingLevel(n,{m}),n的取值可选0,1,2;
0是默认值表示不记录;
1表示记录慢速操做,若是值为1,m必须赋值单位为ms,用于定义慢速查询时间的阈值;
2表示记录全部的读写操做;
例如:db.setProfilingLevel(1,300)

2.查询监控结果 

监控结果保存在一个特殊的盖子集合system.profile里,这个集合分配了128kb的空间,要确保监控分析数据不会消耗太多的系统性资源;盖子集合维护了天然的插入顺序,可使用$natural操做符进行排序,如:db.system.profile.find().sort({'$natural':-1}).limit(5)

盖子集合 Tips:
大小或者数量固定;
不能作update和delete操做;
容量满了之后,按照时间顺序,新文档会覆盖旧文档

3.分析慢速查询 

找出慢速查询的缘由比较棘手,缘由可能有多个:应用程序设计不合理、不正确的数据模型、硬件配置问题,缺乏索引等;接下来对于缺乏索引的状况进行分析:
使用explain分析慢速查询
例如:db.orders.find({'price':{'$lt':2000}}).explain('executionStats')
explain的入参可选值为:
"queryPlanner" 是默认值,表示仅仅展现执行计划信息;
"executionStats" 表示展现执行计划信息同时展现被选中的执行计划的执行状况信息;
"allPlansExecution" 表示展现执行计划信息,并展现被选中的执行计划的执行状况信息,还展现备选的执行计划的执行状况信息

explain结果

queryPlanner(执行计划描述)
winningPlan(被选中的执行计划)
stage(可选项:COLLSCAN 没有走索引;IXSCAN使用了索引)
rejectedPlans(候选的执行计划)
executionStats(执行状况描述)
nReturned (返回的文档个数)
executionTimeMillis(执行时间ms)
totalKeysExamined (检查的索引键值个数)
totalDocsExamined (检查的文档个数)

优化目标 Tips:
根据需求创建索引
每一个查询都要使用索引以提升查询效率, winningPlan. stage 必须为IXSCAN ;
追求totalDocsExamined = nReturned

索引的注意事项

1.   索引颇有用,可是它也是有成本的——它占内存,让写入变慢;

2.   mongoDB一般在一次查询里使用一个索引,因此多个字段的查询或者排序须要复合索引才能更加高效;

3.   复合索引的顺序很是重要,例如此脚本所示:

4.   在生成环境构建索引每每开销很大,时间也不能够接受,在数据量庞大以前尽可能进行查询优化和构建索引;

5.   避免昂贵的查询,使用查询分析器记录那些开销很大的查询便于问题排查;

6.   经过减小扫描文档数量来优化查询,使用explain对开销大的查询进行分析并优化;

7.   索引是用来查询小范围数据的,不适合使用索引的状况:

1.   每次查询都须要返回大部分数据的文档,避免使用索引

2.   写比读多

 

高可用

部署模型

 

可复制集

概念

可复制集是跨多个MongDB服务器(节点)分布和维护数据的方法。mongoDB能够把数据从一个节点复制到其余节点并在修改时进行同步,集群中的节点配置为自动同步数据;旧方法叫作主从复制,mongoDB 3.0之后推荐使用可复制集;

优势

1.   避免数据丢失,保障数据安全,提升系统安全性;(最少3节点,最大50节点)

2.   自动化灾备机制,主节点宕机后经过选举产生新主机;提升系统健壮性;(7个选举节点上限)

3.   读写分离,负载均衡,提升系统性能;

4.   生产环境推荐的部署模式

 

原理

 

oplog(操做日志)  保存操做记录、时间戳 。是盖子集合,大小是能够调整的,默认是所在硬盘5%;

数据同步  从节点与主节点保持长轮询;1.从节点查询本机oplog最新时间戳;2.查询主节点oplog晚于此时间戳的全部文档;3.加载这些文档,并根据log执行写操做

阻塞复制 与writeconcern相关,不须要同步到从节点的策略(如: acknowledged Unacknowledged 、w1),数据同步都是异步的,其余状况都是同步

心跳机制 成员之间会每2s 进行一次心跳检测(ping操做),发现故障后进行选举和故障转移

选举制度  主节点故障后,其他节点根据优先级和bully算法选举出新的主节点,在选出主节点以前,集群服务是只读的

搭建

1.安装好3个以上节点的mongoDB

2.配置mongodb.conf,增长跟复制相关的配置

replication:
  replSetName: configRS  //集群名称
  oplogSizeMB: 50 //oplog集合大小

3.在primary节点切换到admin库上运行可复制集的初始化命令,初始化可复制集

//复制集初始化,在主节点上执行,ip禁止使用localhost
rs.initiate({
      _id: "configRS",
      version: 1,
      members: [{ _id: 0, host : "192.168.0.128:27017" }]});
rs.add("192.168.0.128:27018");//有几个节点就执行几回方法
rs.add("192.168.0.128:27019");//有几个节点就执行几回方法

4.在每一个节点运行rs.status()或isMaster()命令查看复制集状态.

只此时能在主节点查询数据,但若是想在副节点查询到数据需运行rs.slaveOk();

5.测试数据复制集效果

6.测试故障失效转移效果

代码链接复制集

java原生驱动 

List<ServerAddress> asList = Arrays.asList(
                            new ServerAddress("116.62.222.124", 27018), 
                            new ServerAddress("116.62.222.124", 27017), 
                            new ServerAddress("116.62.222.124", 27019));
client = new MongoClient(asList);

Spring配置

<mongo:mongo-client   
replica-set="116.62.222.124:27017,116.62.222.124:27018,116.62.222.124:27019">
</mongo:mongo-client>

tips

配置Tips:
关注Write Concern参数的设置,默认值1能够知足大多数场景的需求。W值大于1能够提升数据的可靠持久化,但会下降写性能。
在options里添加readPreference=secondaryPreferred便可实现读写分离,读请求优先到Secondary节点,从而实现读写分离的功能

分片

概念

分片是把大型数据集进行分区成更小的可管理的片,这些数据片分散到不一样的mongoDB节点,这些节点组成了分片集群.
mongoDB分片集群推荐的模式是:分片集合,它是一种基于分片键的逻辑对文档进行分组,分片键的选择对分片很是重要,分片键一旦肯定,mongoDB对数据的分片对应用是透明的

分片理解:使用一个字段作分片,通过hash后肯定数据存储在哪一个服务器的哪块区域上。

 

分片迁移

随着数据量的的增大,分片会分割和迁移,以知足数据的均匀分布

请求分流:经过路由节点将请求分发到对应的分片和块中; 

数据分流:内部提供平衡器保证数据的均匀分布,数据平均分布式请求平均分布的前提

块的拆分:3.4版本块的最大容量为64M或者10w的数据,当到达这个阈值,触发块的拆分,一分为二

块的迁移:为保证数据在分片节点服务器分片节点服务器均匀分布,块会在节点之间迁移。通常相差8个分块的时候触发; 

分片模型

 

优势

1.数据海量增加,须要更大的读写吞吐量 → 存储分布式 

2.单台服务器内存、cpu等资源是有瓶颈的 → 负载分布式 

tips:分片集群是个双刃剑,在提升系统可扩展性和性能的同时,增大了系统的复杂性,因此在实施以前请肯定是必须的。

分片搭建

结构图

 

步骤

1.分片服务器配置:给27020、27021以及复制集(2701七、2701八、27019)的配置文件增长 

sharding: 
clusterRole: shardsvr

2.config服务器配置:给复制集(2702二、2702三、27024)的配置文件增长

sharding:
       clusterRole: configsvr

3.配置存储数据的分片复制集

rs.initiate({
_id: "dataRS",
version: 1,
members: [{ _id: 0, host : "192.168.0.128:27024" }]});
rs.add("192.168.0.128:27025");//有几个节点就执行几回方法
rs.add("192.168.0.128:27026");//有几个节点就执行几回方法

4.配置config的数据集

rs.initiate({
_id: "configRS",
version: 1,
members: [{ _id: 0, host : "192.168.0.128:27028" }]});
rs.add("192.168.0.128:27029");//有几个节点就执行几回方法
rs.add("192.168.0.128:27030");//有几个节点就执行几回方法

5.修改mongos路由节点的配置文件。mongos的配置文件(mongodb.conf),没有“storage”“http.RESTInterfaceEnabled”这些配置,但增长以下配置

sharding:
  configDB: configRS/192.168.0.128:27028,192.168.0.128:27029,192.168.0.128:27030
 
这是配置路由节点须要链接的配置服务器的复制集地址;

6.使用 ./mongos -f mongodb.conf 启动路由节点;

7.配置分片sharding

链接mongos: mongo --port 27025

增长分区
use admin;
sh.addShard("192.168.0.128:27023");
sh.addShard("192.168.0.128:27027");
//configRS这个是复制集的名称
sh.addShard("dataRS/192.168.0.128:27024,192.168.0.128:27025,192.168.0.128:27026");

经过sh.status()或图形化工具查看分片结果

对lison数据库启用分片:sh.enableSharding("lison")

对ordersTest集合进行分片,分片键为{"useCode":1,"_id":1}
sh.shardCollection("lison.orders",{"useCode":"hashed"});

 

tips

分片注意点

  • 热点 :某些分片键会致使全部的读或者写请求都操做在单个数据块或者分片上,致使单个分片服务器严重不堪重负。自增加的分片键容易致使写热点问题;
  • 不可分割数据块:过于粗粒度的分片键可能致使许多文档使用相同的分片键,这意味着这些文档不能被分割为多个数据块,限制了mongoDB均匀分布数据的能力;
  • 查询障碍:分片键与查询没有关联,形成糟糕的查询性能。

 

建议

 

    • 不要使用自增加的字段做为分片键,避免热点问题;
    • 不能使用粗粒度的分片键,避免数据块没法分割;
    • 不能使用彻底随机的分片键值,形成查询性能低下;
    • 使用与经常使用查询相关的字段做为分片键,并且包含惟一字段(如业务主键,id等);
    • 索引对于分区一样重要,每一个分片集合上要有一样的索引,分片键默认成为索引;分片集合只容许在id和分片键上建立惟一索引;
相关文章
相关标签/搜索