MongoDB快速上手教程

MongoDB

学过Redis或Mysql的理解起来比较清楚

介绍

【介绍】
MongoDB是一个开源的、高性能、无模式的文档型数据库,是NoSQL数据库产品中的一种,最像关系型数据库的非关系型数据库

【使用场景】
三高需求下使用mongodb:
1. 高并发
2. 海量数据
3. 高可拓展性(数据库表的字段是固定的,高可拓展性就可以忽略这个限制)和高可用性

总结使用场景:
社交场景、游戏场景、物流场景、物联网场景(智能设备的信息、汇报等)、视频直播
1. 数据量大  2. 读写频繁  3.价值较低的数据  4.不需要事物要求 

MongeDB与MySQL的对比

MongoDB快速上手教程_第1张图片

SQL MongoDB 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据库表记录行/文档
column field 数据库字段/域
index index 索引
table joins 嵌入文档 表连接/MDB不支持(通过嵌入式文档来代替多表连接)
primary key primary key 主键/MDB自动将_id字段设置为主键

默认数据库介绍

admin:存放用户或权限的数据库,一些特定的服务器端命令只能通过这个库运行
local:这个数据库永远不会被复制,可以用来存储限于本地单台服务器的任何集合
config:保存分片的相关信息

安装

安装包下载环节

MongoDB快速上手教程_第2张图片

MongoDB快速上手教程_第3张图片

MongoDB快速上手教程_第4张图片

Win

点下载,然后等待下载完成打开安装即可

Linux

#官方安装教程地址:https://docs.mongodb.com/master/administration/install-on-linux/

#Cen0S7,其他安装方法
#下载文件(上传文件也可以)
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.1.tgz

#解压
tar -zxvf mongodb-shell-linux-x86_64-rhel70-4.4.1.tgz

#将解压文件拷贝到指定目录
mv mongodb-linux-x86_64-rhel70-4.4.1/ /usr/local/mongodb

#创建数据和日志存放目录
mkdir -p /usr/local/mongodb/data/db /usr/local/mongodb/log

#两种选其中一种
#1.通过mongod创建配置
/usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/db --logpath=/usr/local/mongodb/logs/mongdb.log --logappend -port=27017 --fork
#2. 创建配置文件
vim /etc/mongodb.conf
#启动服务时需要通过-f 指定配置文件路径

#启动服务
#1.启动服务 -f指定使用配置文件
/usr/local/mongodb/bin/mongod -f /etc/mongodb.conf
#2.连接服务器 
/usr/local/mongodb/bin/mongo  


#检查是否启动成功/获取mongodb的进程号
ps -ef | grep mongodb

#关闭mongodb
kill -2 进程号

创建文件路径如下 /etc/mongodb.conf

#第一种 创建配置文件文件内容
#数据库路径
dbpath=/usr/local/mongodb/data/db

#日志路径
logpath=/usr/local/mongodb/log/mongodb.log

#端口号
port=27017

#先关闭, 创建好用户在启动
##auth = true 

#使用追加的方式写日志
logappend=true 

#以守护进程的方式运行,创建服务器进程
fork=true

#最大同时连接数
maxConns=100 

#不启用验证
noauth=true

#每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据),即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复
journal=true

#存储引擎有mmapv1、wiretiger、mongorocks
storageEngine=wiredTiger

#这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB
#如果是云主机这里填写的是私网地址,如阿里云,不然无法远程访问
bind_ip = localhost,0.0.0.0
#第二种 创建配置文件yaml文件内容
#https://blog.csdn.net/MatrixGod/article/details/82585778详细介绍
systemLog:
#MongoDE发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos日志文件的路径
path: "/usr/local/mongodb/log/mongod.1og"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目酣加到现有日志文件的末尾。
logAppend: true

storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
dbPath: "/usr/local/mongodb/data/db"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true

processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true

net:
#服务实例绑定的IP,默认是1ocalhost
bindIp: localhost
#绑定的端口,默认是27017
port: 27017

security:
#启用数据库用户验证(开启授权认证)
authorization: enabled


replication:
#副本集名称,不同的副本集使用的名字不一样
replSetName: myrs

sharding:
#分片角色,两种组件其中一种,shardsvr:分片,configsvr:调度
clusterRole: shardsvr
#配置路由组件时使用,指定配置节点副本集(指定"调度"组件的副本集以及要使用的"调度"副本集节点),注:ip写多少个看指定副本集里存在的节点有多少个
#路由的启动是通过mongos启动
configDB:副本集名/ip1:port1,ip2:port2,ip3:port3...

数据类型

【字符串】
格式:{"键名":"字符串"}
例子:{"X":"1aa"}

【对象id】
说明:对象id是文档的12字节的唯一ID
格式:{"键名":ObjectId()}
例子:{"id":ObjectId()}

【布尔型】
格式:{"键名":true/false}:
例子:{"X":true}

【数组】
格式:{"键名","[x,x2,x3...]"}
例子:{"arr1","[a1,a2,a3]"}

【32位整数】
说明:类型不可用。js仅支持64位浮点数,所以32会被自动转换64位

【64位整数】
说明:shell中的数字就是这种类型
格式:{"键名":数字}
例子:{"m":123.4}  {"m1":123}

【null】
格式:{"键名":null}
例子:{"x":null}

【undefined】
格式:{"键名":undefined}
例子:{"x":undefined}

【符号】
说明:shell不支持,shell会将数据库中的符号类型数据自动转成字符串

【正则表达式】
格式:{"键名":/正则表达式/}
例子:{"x":/[1234]?/}

【代码】
格式:{"键名":function(){...}}
例子:{"x":function(){...}}

【bit】
说明:二进制数据,不过shell不支持

【最大/最小值】
说明:BSON包括一个特殊的类型,表示可能的最大值。shell中没有这个类型

命令

增删改查

命令 参数 描述
数据库
show dbs/show databases 查看数据库
use xxx 创建或使用数据库
db 查看当前使用的数据库
use xxx
db.xxx.insert({“xxx”:“xxp”})
use 默认创建在内存中,只有插入数据后才会在硬盘上创建数据库 创建数据库
db.dropDatabase() 删除数据库
集合
show tables/show collections 查看集合
db.createCollection(“xxx”,[options]) options:可选参数, 指定有关内存大小及索引的选项
— capped:是否固定集合大小,达到最大时替换掉最早的数据
— size:最大大小
— autolndexld:自动在 _id 字段创建索引(3.2后已废弃)
— max:最大文档数量
创建集合(显式创建集合)
db.xxx.drop() 删除集合
文档(db.表名.方法名)
查询
db.xxx.findOne({query},{projection}) query:查询条件
没条件就是第一条文档
projection:指定查询结果字段
如 {x1:0/1,…} 显示为1 不显示为0或不设置,_id会自动显示就可以通过设置0来不显示
查询一条文档
db.xxx.find() 查看全部文档
db.xxx.find({query},{projection}) 通过条件查询文档
db.xxx.count({query},{options}) query:查询条件
options:可选参数, 指定有关内存大小及索引的选项
统计查询
db.xxx.find().limit(x) x:指定返回条目数
配合skip可以作分页查询
指定返回条目查询
db.xxx.find().skip(x) x:要跳过的文档数量,从跳过文档后开始查询 指定开头查询
db.xxx.find().sort({x:1/-1},…) x:字段名 ,-1降序,1升序 排序查询
db.xxx.find({x:/正则表达式/}) x:字段名 正则查询
db.xxx.find({x:{$gt:NumberInt(value)}}) $gt:> g t e : > = < b r / > gte:>=
gte>=<br/>
lt:< l t e : < = < b r / > lte:<=
lte<=<br/>
ne:!=
比较查询
db.xxx.find({x:{$in:[“a1”,“a2”,…]}) 多值查询,好比sql的in
db.xxx.find({$and:[{query},{query},…]}) $ a n d : 和 and:和 andor:或 条件查询
插入
db.xxx.insert({document},{document},…,{writeConcern,ordered}) 如果集合不存在就会自动创建集合
writeConcern:写入策略
ordered:指定是否按顺序写入,默认true
插入文档(隐式创建集合)
db.xxx.inserOne({document},{writeConcern,ordered}) 插入一条文档
db.xxx.insertMany({document},{document},…,{writeConcern,ordered}) 查看【注意点1】 插入多条文档
修改
db.xxx.update({query},{update},{upsert},{multi},{writeConcern}) query:查询条件
update:新的文档
upsert:不存在是否插入,默认是false
multi:是否更新全部查找到的数据,默认是false
writeConcern:抛出异常的级别
覆盖文档
db.xxx.update({query},{$set:{update}},{upsert},{multi}) 查看【注意点2】
$set:指定要修改的key,其他字段数据将保持不动
局部修改文档
db.xxx.update({query},{$unset:{“x”:null}}) x:字段名
$unset:修改/添加/删除字段(属性)
删除局部字段
db.xxx.save({document}) 新的document需要指定id,_id 主键存在就更新,不存在就插入。 替换文档
db.xxx.update({$inc:{x:NumberInt(value)}}) x:字段名 自增,属于局部修改
删除
db.xxx.remove({query},{justOne},{writeConcern}) query:查询条件
justOne:是否删除全部查找到的数据,默认1条
writeConcern:抛出异常的级别
条件为{}时就是删除全部
删除文档
#注意点
1. 当批量插入数据时,有某条数据插入失败会导致插入终止,成功的数据不会回滚
	——解决方法:用try{}catch(e){print(e)}包裹

2. 需要修改多条数据时一定要设置multi参数为true

索引

命令 参数 描述
索引
db.xxx.getIndexes() xxx:集合名 获取集合中所有的索引情况
db.xxx.createIndex({keys},{options}) keys:要创建索引的字段
({“xxx”:1/-1},{…}),1升序索引
options:可选,创建索引时的其他设置选项
—name:索引名称
—unique:索引是否唯一,默认false
—weights:权重
创建单字段或复合索引
db.xxx.dropIndex({index}) index:要删除的索引字段
({“xxx”:1}):创建时的样子
删除索引
db.xxx.dropIndex(索引名) 删除索引
db.xxx.dropIndexes() 删除全部索引,除了默认索引
db.xxx.find().explain({options}) options:可选
结果集里stage如果是COLLSCAN证明是全局扫描
查看执行计划

集群

命令 参数 描述
“path”/mongod -f “filepath”/xxx.conf path:mongodb的bin文件路径
-f filepath:使用指定配置文件
启动服务
“path”/mongo [-xxx=xxx] path:mongodb的bin文件路径
–host:服务器的ip,默认本机ip
–port:服务器的端口,默认27017
连接服务器
rs.initiate(configuration) configuration:可选,携带配置 初始化副本集
rs.conf(configuration) configuration:可选,携带配置 获取当前副本集配置文档
rs.status() 查看当前副本集状态
rs.add(host,arbiterOnly) host:输入字符串或文档其中一种,
字符串:输入host:port
文档:输入在members数组中找到的副本集成员配置文档
arbiterOnly:可选,仅在host是字符串时适用,如果为true,该节点是仲裁者
添加副本成员从节点到副本集
rs.remove(host) host:ip:port 从副本集中移除从节点
rs.addArb(host) host:ip:port 添加仲裁者从节点到副本集
rs.slaveOk(bool) bool:默认为true
4.0版本标识过时
是否同意成为从节点
rs.stepDown() 在主节点进行 手动将主节点降级为从节点
db.getMongo().
setReadPref(“nearest”)
nearest:最近的节点(当前节点)查询
secondary:只能在从节点查询
secondaryPreferred:优先从从节点查询
primary:只能在主节点查询
primaryPreferred:优先从主节点查询
设置查询级别
分片集群特有
sh.enableSharding(“数据库名”) 对数据库开启分片功能
sh.addShard(“host”) 在路由节点进行添加,host格式需要注意 分片集群添加到"调度"
sh.shardCollection(
namespace,key,unique)
在路由进行配置
namespace:"库名.集合名
key:{key:value},分片的规则,只能设置一个字段
unique:字段是否是唯一的,默认为false
对数据库集合进行分片
db.settings.save(xxx) 在路由进行配置
xxx:{_id:“chunsize,value:64”}
更改数据块大小
db.runCommand(shard) shard:{removeShard:“分片名/副本集名”} 移除分片
rs.initiate({文档})
文档内容:
rs.initiate({
"_id":"副本集名称",
"members":[
	{"_id":0,"host:ip:port","priority":3},
	{"_id":1,"host:ip:port","priority":1},
	{"_id":2,"host:ip:port","priority":1},
	{"_id":3,"host:ip:port","arbiterOnly":true}
	]
})
sh.addShard("host")
host内容: 注:ip写多少个看指定副本集里存在的节点有多少个
"分片副本集名/ip1:port1,ip2:port2,ip3:port3..."

sh.shardCollection(namespace,key,unique)
key里的value策略选择
【hashed】对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块.
在使用基于哈希分片的系统中,拥有”相近”片键的文档 很可能不会存储在同一个数据块中,因此数据的分离性更好一些.
【范围策略】假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点.MongoDB把这条直线划分为更短的不重叠的片段,并称之为数据块 ,每个数据块包含了片键在一定范围内的数据.
在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中.

角色

命令 参数 描述
db.createUser(
{user:“root”
,pwd:“password”,
roles:[“root”]})
要使用admin数据库进行 创建root/admin用户
db.updateUser( “admin”,{pwd:“password”}); admin:用户名 修改用户密码
db.changeUserPassword(
“admin”,“密码”)
修改密码
db.dropUser(“admin”) 删除用户
db.system.users.find() 查看已经创建了的用户情况
db.auth(“admin”,“password”) 验证用户是否添加成功 或 登入用户
# 创建用户,拥有articledb数据库的读写权限readwrite,密码是123456
db.createUser({user:"bobo",pwd:"123456",roles: [i role: "readwrite",db:"artic7edb"}]})

索引

定义:索引是为了加快数据库的查询效率,如果不设置索引的话,数据库会在遍历整个集合,也就是说每查找一条数据都会去遍历它的全部字段,当设置索引后会先判断查询条件是否包含索引字段,如果是会先在索引集合里找到满足查询条件里索引条件的文档,然后才去真正的集合抓取该文档所有字段返回,如果查询结果只需要索引字段,则会直接返回索引集合里的文档字段不会再去真正的集合里抓取,但如果查询条件没有使用索引就会去遍历整个集合。索引就是空间换时间。mongodb索引有了单字段索引复合索引其他索引(地理空间索引、文本索引、哈希索引)

地理空间索引(Geospatial Index)
为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。

文本索引(Text Indexes)
MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例l如the"、"a"、“or"),而将集合中的词作为词干,只存储根词。
虽然MongoDB提供了但效率上并不是很高,还是推荐使用

哈希索引(Hashed Indexes)
为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。

执行计划:分析查询性能通常使用执行计划来查看查询的情况,如查询消耗的时间、是否基于索引查询等。在这里可以用来查看建立的索引是否有效,效果如何

SpringBoot使用

正常使用

依赖

  <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-data-mongodbartifactId>
  dependency>

application.yaml文件修改

spring:
data:
#mongodb: 
#host: 39.108.54.110
#d#atabase: test
#port: 27017
mongodb:
uri: mongodb://39.108.54.110:27017/test

CommentRepository接口

//需要指定泛型里指定文档对应PO对象
public interface CommentRepository extends    MongoRepository<Person,String> {
}
//接口继承MongoRepository,在使用时会通过动态代理帮我们自动根据泛型生成MongoRepository实现类转bean对象

文档对应POJO类

@Document()
public class Person {
private String id;
private String name;
private int age;

public Person(String name, int age) {
  this.name = name;
  this.age = age;
}

public String getId() {
  return id;
}
public String getName() {
  return name;
}
public int getAge() {
  return age;
}

@Override
public String toString() {
  return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
@Document(collation="") //要使用的集合名,如果POJO类名首字母小写等于集合名可以忽略不写
@Field("") //指定属性要映射到文档的那个字段
@Id  //主键
...

使用mongodb

@Autowired
public class Acc {
@Autowired //简单的mogodb操作
private CommentRepository commentRepository;
	@Autowired //复杂的mongodb操作
private MongoTemplate mongoTemplate;

public List<Person> findAll(){
 System.out.println(commentRepository);
 return commentRepository.findAll();
}

public void addOne(){
 //commentRepository.insert(new Person("xx2","name",12));
}
}

分页查询

依赖

  <dependency>
      <groupId>org.springframework.bootgroupId>
      <artifactId>spring-boot-starter-data-mongodbartifactId>
  dependency>

application.yaml文件修改

spring:
data:
#mongodb:
#host: 39.108.54.110
#d#atabase: test
#port: 27017
mongodb:
uri: mongodb://39.108.54.110:27017/test

CommentRepository接口

public interface CommentRepository extends MongoRepository<Person,String> {
//findBy是固定写法,findBy后面跟着条件(必须要更)

//查询条件(userid == 传入参数的userid),Pageable用来接受分页的起始页,和返回条目
Page<Person> findByUserid(String userid, Pageable pageable);
//查询条件(userid不为空),Pageable用来接受分页的起始页,和返回条目
Page<Person> findByIdNotNull(Pageable pageable);
}

文档对应POJO类

@Document()
public class Person {
private String id;
@Field("id")
private String userid;
private String name;
private int age;

public String getId() {
  return id;
}
public String getName() {
  return name;
}
public int getAge() {
  return age;
}

public String getUserid() {
  return userid;
}

public Person(String id, String userid, String name, int age) {
  this.id = id;
  this.userid = userid;
  this.name = name;
  this.age = age;
}

@Override
public String toString() {
  return "Person{" +
          "id='" + id + '\'' +
          ", userid='" + userid + '\'' +
          ", name='" + name + '\'' +
          ", age=" + age +
          '}';
}
}

使用

@Service
public class Acc {
@Autowired
private CommentRepository commentRepository;

//PageRequest.of()会返回一个Pageable类对象
//根据id查询后进行分页
public Page<Person> page(String id, int page, int size){
 return commentRepository.findByUserid(id, PageRequest.of(page-1,size));
}

//根据id不为空查询后进行分页
public Page<Person> page(int page, int size){
  return commentRepository.findByIdNotNull( PageRequest.of(page-1,size));
}
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
class SpringMongodbApplicationTests {

@Autowired
Acc acc;
@Test
void contextLoads() {
  /*
  	page.getContent()获取查询结果,返回结果类型为List,最多不超过参数的size
  	page.getTotalElements()获取查询到的数据总数量
  */
  Page<Person> page = acc.page("x1", 1, 2);
  System.out.println(page.getContent());
  System.out.println(page.getTotalElements());

  Page<Person> page1 = acc.page(3, 2);
  System.out.println(page1.getContent());
  System.out.println(page1.getTotalElements());
}
}

文档修改

依赖

  
      org.springframework.boot
      spring-boot-starter-data-mongodb
  

application.yaml文件修改

spring:
data:
#mongodb:
#host: 39.108.54.110
#d#atabase: test
#port: 27017
mongodb:
uri: mongodb://39.108.54.110:27017/test

CommentRepository接口

public interface CommentRepository extends MongoRepository<Person,String> {
}

文档对应POJO

@Document()
public class Person {
private String id;
@Field("id")
private String userid;
private String name;
private int age;

public String getId() {
  return id;
}
public String getName() {
  return name;
}
public int getAge() {
  return age;
}

public String getUserid() {
  return userid;
}

public Person(String id, String userid, String name, int age) {
  this.id = id;
  this.userid = userid;
  this.name = name;
  this.age = age;
}

@Override
public String toString() {
  return "Person{" +
          "id='" + id + '\'' +
          ", userid='" + userid + '\'' +
          ", name='" + name + '\'' +
          ", age=" + age +
          '}';
}
}

使用

@Service
public class Acc {
@Autowired //复杂操作用mongoTemplate
private MongoTemplate mongoTemplate;

public void updateByIdToAge(String id){
  //条件对象,链式编程,is是否存在
  Query query = Query.query(Criteria.where("userid").is(id));
  //修改对象,链式编程,inc自增1
  Update update = new Update();
  update.inc("age");

  //执行修改,updateFirst修改一条
  mongoTemplate.updateFirst(query, update,Person.class);
}

}

集群连接

spring:
data:
mongodb:
#uri: mongodb://host1,host2,.../集合名?connect=replicaSet&slave=true&replicaSet=副本集名称
uri: mongodb://39.108.54.110:27017,39.108.54.110:27018,39.108.54.110:27019/test?connect=replicaSet&slave=true&replicaSet=mysr

集群

主从复制

⭐主从复制
主从复制:拷贝源服务器的数据到新服务器,新服务器和源服务器一起对外提供服务。但这些服务器里只能有一台负责写的操作。
⭐两种类型
主节点(Primary): 主节点只有一个,写操作只能在主节点中进行,读操作在主节点或从节点都可以进行,主节点是由仲裁从节点海选出来的
从节点(Secondaries) :也叫次节点或辅助节点,默认的从节点是副本成员节点
⭐三种角色
主要成员(Primary): 接受所有写操作,就是主节点
副本成员(Replicate):主节点通过复制操作将数据到拷贝一份给副本成员,即备份数据,副本成员只负责读操作(需要配置)
仲裁者(Arbiter):不保留任何数据,只具有从副本成员从节点投票选举出新主节点的功能。仲裁者一般为奇数个。

副本成员和仲裁者需要同意才能成为从节点

⭐副本集:
副本集可以理解为一个容器,只有在同一个容器里的东西才能互相使用。起到隔离作用。
启用副本集,通常最少需要三个成员节点,最多可支持50个成员节点,其中最多可设置7个拥有主节点选举权的成员节点,运行时有且只有一个节点为主节点,当主节点(primary)不可用时,副本集根据预设的权值(priority)选出新的主节点。这种机制使得副本集,相对单节点应用,具有更高可用性。

【主从复制理论】
⭐复制集
复制集简单说就在副本集的基础上搭建主从复制的集群

⭐复制集同步写入机制
同步写入是单向的,只能由主节点到从节点。第一次写入为全量同步(所有数据都拷贝一份给从节点),之后的同步则是增量同步(有写操作时,让从节点也执行一样的写操作)。

⭐复制集状态同步机制(心跳机制)
是为了第一时间发现脑裂(脑裂:没宕机,就是网络不通)情况所使用的一种预防措施。MongoDB复制集(3.0版本)之间通过心跳信息来同步成员的状态信息,每个节点会周期性的向复制集内其它的成员发送心跳信息来获取状态,如rs.status()看到的复制集状态信息。简单说就是每隔一段时间,每个节点都会发送一次心跳请求给其他节点,其他节点作出心跳应答,确保两个节点是连通状态,如果某个节点被判定出现了问题,如果是主节点的话就通过海选得到新主节点,表示主节点着判定为可能是出现问题过段时间重新发送心跳请求。
详细介绍查看:https://mongoing.com/archives/2759,https://www.cnblogs.com/clsn/p/8214345.html

⭐触发选举机制
1. 主节点故障
2. 主节点网络不可达(默认心跳信息为10秒)
	—— 详细点就是如果有多个仲裁者,在"大多数"个仲裁者都认为主节点下线时候才会触发选举,只有一个仲裁者着直接触发选举
3. 人工干预(rs.stepDown(600))

⭐大多数原则
当前复制集中,存活节点的数量必须大于节点总数的1/2,这样才能触发选举,否则当从节点挂掉时主节点会降级为从节点;当主节点挂掉时从节点也不会升为主节点。

⭐选举的原理
节点类型分为标准(host)节点 、被动(passive)节点和仲裁(arbiter)节点。
1.只有标准节点可能被选举为主(primary)节点,有选举权,其他节点都没有
2. 标准节点与被动节点的区别:priority值高者是标准节点,低者则为被动节点,默认priority值是1。
3. 选举规则是在大多数原则不触发下,票数最高者获胜,priority是优先权为0~1000的值,相当于额外增加0~1000的票数。选举结果:票数高者获胜;若票数相同,数据新者获胜

分片集群

MongoDB快速上手教程_第5张图片

MongoDB快速上手教程_第6张图片

详细介绍:https://www.cnblogs.com/clsn/p/8214345.html
⭐分片集群
把完整的数据才分成多片,将拆分完的分片存储在不同的服务器里。还可以对分片集群继续做主从复制来保证不会有单点故障。

⭐组件
(1)mongos :提供对外应用访问,所有操作均通过mongos执行。mongos本身没有任何数据,他也不知道该怎么处理这数据,由它自动去找config server来处理
(2)config server:所有存、取数据的方式,所有shard节点的信息,分片功能的一些配置信息。可以理解为真实数据的元数据。3.4版本开始,必须将配置服务器部署为副本集(CSRS)
(3)Mongod/shard(分片):
存储应用数据记录即真正数据的存储位置。一般有多个Mongod节点,达到数据分片目的,以chunk为单位存数据。

【机制】
⭐分片键
你需要选择一个片键 , shard key 是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不同的数据块中,并将数据块均衡地分布到所有分片中.为了按照片键划分数据块,MongoDB使用 基于范围的分片方式 或者 基于哈希的分片方式
⭐数据均衡
当集群中数据的不均衡发生时,均衡器会将数据块从数据块数目最多的分片迁移到数据块最少的分片上,举例来讲:如果集合 users 在 分片1 上有100个数据块,在 分片2 上有50个数据块,均衡器会将数据块从 分片1一直向 分片2 迁移,一直到数据均衡为止.

⭐总结分片集群
搭建顺序:先"调度"或"分片"节点,最后"路由"
工作原理:
"路由"节点主要负责请求的接受并自动调度请求到"调度"节点
"调度"节点如果接受的是写的请求,会根据分区规则把请求和要求交给对应的"分片"节点,由"分片"节点存储数据到数据块里,如果是读请求会通过记录转发请求到对应的"分片"节点进行操作。

安全

MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。在实例启动时添加选项--auth或指定启动配置文件中添加选项auth=true

角色&权限

角色分两种,包括内置角色和自定义角色。角色的权限可以显示的指定,也可以通过继承其他角色的权限,或着两者都存在。
权限决定了角色的可操作范围。
角色 权限
数据库用户角色
read 可以读取指定数据库中任何数据。
readWrite 可以读写指定数据库中任何数据,包括创建、重命名、删除集合。
数据库管理角色
dbAdmin 可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。
dbOwner
userAdmin 可以在指定数据库创建和修改用户。
集群管理角色
clusterAdmin 可以对整个集群或数据库系统进行管理操作。
clusterManager
clusterMonitor
hostManager
备份恢复角色
backup 备份MongoDB数据最小的权限。
restore 从备份文件中还原恢复MongoDB数据(除了system.profile集合)的权限。
所有数据库角色
readAnyDatabase 可以读取所有数据库中任何数据(除了数据库config和local之外)。
readWriteAnyDatabase 可以读写所有数据库中任何数据(除了数据库config和local之外)。
userAdminAnyDatabase 可以在指定数据库创建和修改用户(除了数据库config和local之外)。
dbAdminAnyDatabase 可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作(除了数据库config和local之外)。
超级用户角色
root 超级用户,超级权限
#springboot连接配置
spring:
#数据源配置
data:
mongodb :
#主机地址
#host: 180.76.159.126
#数据库
#database: articledb
#默认端口是27017
#port: 27017
#帐号
#username: bobo
#密码
#password: 123456

#单机有认证的情况下,也使用字符串连接
uri: mongodb://bobo:[email protected]:27017/articledb

你可能感兴趣的:(mongodb)