MongoDB的安装和使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、 MongoDB在Linux的安装和使用
    • 1.安装
  • 二、 MongoDB命令
    • 1.基本操作
    • 2、MongoDB集合数据操作(CURD)
      • 1.插入数据
      • 2.数据查询
      • 3. 数据更新 调用update
      • 4. 数据删除
    • 3、MongoDB聚合操作
      • 1.单目聚合操作
      • 2.聚合管道
      • 3.MapReduce 编程模型
  • 三、 MongoDB索引
      • 1、 索引类型
        • 1)单键索引 (Single Field)
        • 2)复合索引(Compound Index)
        • 3)多键索引(Multikey indexes)
        • 4)地理空间索引(Geospatial Index)
        • 5)全文索引
        • 6) 哈希索引 Hashed Index
      • 2、 索引和explain 分析
        • 1)索引管理
        • 1) explain 分析
      • 3、MongoDB 索引底层实现原理分析
  • 四、 MongoDB 应用实战
      • 1. MongoDB的行业具体应用场景
      • 2. Java 访问MongoDB
      • 3. Spring 访问MongoDB
      • 4. SpringBoot 访问MongoDB
  • 五、 MongoDB 架构
      • 5.1 MongoDB的数据模型
      • 5.2 MongoDB存储引擎
        • 1. WiredTiger存储引擎优势
        • 2. WiredTiger引擎包含的文件和作用
        • 3. WiredTiger存储引擎实现原理
  • 六、 MongoDB 集群高可用
      • 6.1 MongoDB主从复制架构原理和缺陷
      • 6.2 复制集replica sets
      • 6.3 复制集集群架构原理
      • 6.4 复制集集群搭建
      • 6.5分片集群
      • 6.6分片集群搭建
  • 六、 MongoDB 安全认证
    • 7.1
    • 7.2 单机安全认证实现流程
    • 7.3 分片集群安全认证
  • 总结


前言

1.下载地址
链接: https://www.mongodb.com/try/download/community.


提示:以下是本篇文章正文内容,下面案例可供参考

一、 MongoDB在Linux的安装和使用

1.安装

1.下载社区版 MongoDB 4.1.3 去官网下载对应的MongoDB 然后上传到Linux虚拟机
2.将压缩包解压即可

tar -zxvf MongoDB-linux-x86_64-4.1.3.tgz

3.启动

[root@node1 mongodb-linux-x86_64-4.1.3]# mkdir -p /data/db
[root@node1 mongodb-linux-x86_64-4.1.3]# ./bin/mongod

4.指定配置文件方式的启动

./bin/mongod -f mongo.conf 
配置文件样例: 
dbpath=/data/mongo/ 
port=27017 
bind_ip=0.0.0.0 #监听IP地址,默认全部可以访问
fork=true #后台运行
logpath = /data/mongo/MongoDB.log
logappend = true #是否追加日志
auth=false #是开启用户密码登陆

5.mongo shell
启动mongo shell

./bin/mongo 

指定主机和端口的方式启动

 ./bin/mongo --host=远程服务器主机IP(本机可不用指定) --port=端口

Ctrl+C就可以退出

6.Mongou GUI
MongoDB的安装和使用_第1张图片
MongoDB的安装和使用_第2张图片

二、 MongoDB命令

1.基本操作

查看数据库 show dbs; 
切换数据库 如果没有对应的数据库则创建 use 数据库名; 
创建集合 db.createCollection("集合名") 
查看集合 show tables; show collections;
删除集合 db.集合名.drop();
删除当前数据库 db.dropDatabase();

2、MongoDB集合数据操作(CURD)

1.插入数据

db.lg_resume_prview.insert({name:"张3",birthday:new ISODate("2000-07-01"),expectSalary:15000,city:"beijing"})
  • 没有指定 _id 这个字段 系统会自动生成 当然我们也可以指定 _id
    ( _id 类型是ObjectId 类型是一个12字节 BSON 类型数据,有以下格式:前4个字节表示时间戳 ObjectId(“对象Id字符串”).getTimestamp() 来获取,接下来的3个字节是机器标识码,紧接的两个字节由进程id组成(PID)最后三个字节是随机数。)

2.数据查询

MongoDB的安装和使用_第3张图片
2.逻辑条件查询

  • and 条件
    MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件 db.集合名.find({key1:value1, key2:value2}).pretty()

  • or 条件
    db.集合名.find({$or:[{key1:value1}, {key2:value2}]}).pretty()

  • not 条件
    db.集合名.find({key:{$ not:{$操作符:value}}).pretty()

pretty()用作格式化

3.分页查询
db.集合名.find({条件}).sort({排序字段:排序方式})).skip(跳过的行数).limit(一页显示多少数据)

db.lg_resume_prview.find({expectSalary:{$gt:15000}}).sort({expectSalary:1}).skip(1).limit(2)

3. 数据更新 调用update

MongoDB的安装和使用_第4张图片

db.lg_resume_prview.update({expectSalary:30000},
{$set: {expectSalary:28888}},
{multi:false,upsert:false})

4. 数据删除

MongoDB的安装和使用_第5张图片

3、MongoDB聚合操作

1.单目聚合操作

单目的聚合命令常用的有:count() 和 distinct()

db.lg_resume_prview.find({}).count()

2.聚合管道

/**按照city进行分组**/
db.lg_resume_preview.aggregate([{$group: { _id: "$city",city_count:{$sum: 1}}}])
/**按照city进行分组,根据薪资计算平均值**/
db.lg_resume_preview.aggregate([{$group: { _id: "$city",avg_sal:{$avg: "$expectSalary"}}}])
/**按照city进行分组,将城市名放在一个集合**/
db.lg_resume_preview.aggregate([{$group: { _id: "$city",cityName:{$addToSet: "$city"}}}])
   

MongoDB 中使用 db.COLLECTION_NAME.aggregate([{},…]) 方法来构建和使用聚合管道,每个文档通过一个由一个或者多个阶段(stage)组成的管道,经过一系列的处理,输出相应的结果。

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作
是可以重复的。
这里我们介绍一下聚合框架中常用的几个操作:

  • $group:将集合中的文档分组,可用于统计结果。
  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $ match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。
db.lg_resume_preview.aggregate( [{$group : {_id: "$city", avgSal:{$avg:"$expectSalary"}}}, {$project : {city: "$city", salary : "$avgSal"}} ])

db.lg_resume_preview.aggregate( [{$group:{_id: "$city",count:{$sum : 1}}}, {$match:{count:{$gt:1}}} ])

3.MapReduce 编程模型

Pipeline查询速度快于MapReduce,但是MapReduce的强大之处在于能够在多台Server上并行执行复杂的聚合逻辑。MongoDB不允许Pipeline的单个聚合操作占用过多的系统内存,如果一个聚合操作消耗20%以上的内存,那么MongoDB直接停止操作,并向客户端输出错误消息。

MapReduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。

MongoDB的安装和使用_第6张图片
使用 MapReduce 要实现两个函数 Map 函数和 Reduce 函数,Map 函数调用 emit(key, value), 遍历collection 中所有的记录, 将 key 与 value 传递给 Reduce 函数进行处理。
参数说明:

  • map:是JavaScript 函数,负责将每一个输入文档转换为零或多个文档,生成键值对序列,作为reduce 函数参数
  • reduce:是JavaScript 函数,对map操作的输出做合并的化简的操作(将key-value变成key-values,也就是把values数组变成一个单一的值value)
  • out:统计结果存放集合
  • query: 一个筛选条件,只有满足条件的文档才会调用map函数。
  • sort: 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制
  • limit: 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)
  • finalize:可以对reduce输出结果再一次修改
  • verbose:是否包括结果信息中的时间信息,默认为fasle
db.lg_resume_preview.mapReduce(
    function(){emit(this.city,this.expectSalary);}, 
    function(key,value){return Array.avg(value);}, 
    {
        query:{expectSalary:{$gt:15000}}
        out:"cityAvgSal",
        finalize:function(key,value){
            return value-999;
        }
    })

db.cityAvgSal.find();

三、 MongoDB索引

1、 索引类型

1)单键索引 (Single Field)
db.lg_resume_preview.createIndex(
                  {"name": 1}
     )
db.lg_resume_preview.getIndexes()

特殊的单键索引 过期索引 TTL ( Time To Live)
TTL索引是MongoDB中一种特殊的索引, 可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,并且字段类型必须是日期类型。

db.集合名.createIndex({"日期字段":排序方式}, {expireAfterSeconds: 秒数})
2)复合索引(Compound Index)
db.集合名.createIndex( { "字段名1" : 排序方式, "字段名2" : 排序方式 } )

注意:方向(升序降序【1,-1】)和顺序(左原则)都会影响索引

3)多键索引(Multikey indexes)

针对属性包含数组数据的情况,MongoDB支持针对数组中每一个element创建索引,Multikey indexes支持strings,numbers和nested documents

4)地理空间索引(Geospatial Index)

针对地理空间坐标数据创建索引。

  • 2dsphere索引,用于存储和查找球面上的点
  • 2d索引,用于存储和查找平面上的点
    MongoDB的安装和使用_第7张图片
    上述例子不能使用2d,2d是平面的点,而loc是球面的点
5)全文索引

MongoDB提供了针对string内容的文本查询,Text Index支持任意属性值为string或string数组元素的索引查询。注意:一个集合仅支持最多一个Text Index,中文分词不理想 推荐ES。
也就是:one word one dream 根据这几个单词都能找到该文

db.集合.createIndex({"字段(description)": "text"}) 
db.集合.find({"$text": {"$search": "coffee"}})
6) 哈希索引 Hashed Index

针对属性的哈希值进行索引查询,当要使用Hashed index时,MongoDB能够自动的计算hash值,无需程序计算hash值。注:hash index仅支持等于查询,不支持范围查询。【只能对一个字段加索引,不能做组合索引】

db.集合.createIndex({"字段": "hashed"})

2、 索引和explain 分析

1)索引管理

MongoDB的安装和使用_第8张图片

1) explain 分析

使用js循环 插入100万条数据 不使用索引字段 查询查看执行计划 ,然后给某个字段建立索引,使用索引字段作为查询条件 再查看执行计划进行分析

/**向lg_resume中插入100万条数据**/

for(var i=0;i<1000000;i++){
    db.lg_resume.insert({id:1,name:"test"+i,salary:(Math.random()*20000).toFixed(2)});
}

db.lg_resume.count()

1、queryPlanner 默认参数
需要记住

参数 含义
namespace 要查询的集合(该值返回的是该query所查询的表)数据库.集合
winningPlan.stage 被选中执行计划的stage(查询方式),常见的有:COLLSCAN/全表扫描:(应该知道就是CollectionScan,就是所谓的“集合扫描”, 和mysql中table scan/heap scan类似,这个就是所谓的性能最烂最无奈的由来)、IXSCAN/索引扫描:(是IndexScan,这就说明我们已经命中索引了)、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询等
winningPlan.isMultiKey 是否是Multikey,此处返回是false,如果索引建立在array上,此处将是true。
winningPlan.direction 此query的查询顺序,此处是forward,如果用了.sort({字段:-1})将显示backward。
winningPlan.indexBounds winningplan所扫描的索引范围,如果没有制定范围就是[MaxKey,MinKey],这主要是直接定位到mongodb的chunck中去查找数据,加快数据读取。

.2、executionStats参数

参数 参数
executionSuccess 是否执行成功
nReturned 返回的文档数
executionTimeMillis 执行耗时
totalKeysExamined 索引扫描次数
totalDocsExamined 文档扫描次数
executionStages 这个分类下描述执行的状态
stage 扫描方式,具体可选值与上文的相同
nReturned 查询结果数量
executionTimeMillisEstimate 检索document获得数据的时间
works 工作单元数,一个查询会分解成小的工作单元
advanced 优先返回的结果数
docsExamined 文档检查数目,与totalDocsExamined一致。检查了总共的document 个数,而从返回上面的nReturned数量

3、executionStats返回逐层分析

  1. 第一层,executionTimeMillis最为直观explain返回值是executionTimeMillis值,指的是这条语句的执行时间,这个值当然是希望越少越好。
    其中有3个executionTimeMillis,分别是:
    executionStats.executionTimeMillis 该query的整体查询时间。
    executionStats.executionStages.executionTimeMillisEstimate 该查询检索document获得数据的时间。
    executionStats.executionStages.inputStage.executionTimeMillisEstimate 该查询扫描文档 index所用时间。
  2. 第二层,index与document扫描数与查询返回条目数 这个主要讨论3个返回项 nReturned、totalKeysExamined、totalDocsExamined,分别代表该条查询返回的条目、索引扫描条目、文档扫描条目。 这些都是直观地影响到executionTimeMillis,我们需要扫描的越少速度越快。 对于一个查询,我们最理想的状态是:nReturned=totalKeysExamined=totalDocsExamined
  3. 第三层,stage状态分析 那么又是什么影响到了totalKeysExamined和totalDocsExamined?是stage的类型。
    类型列举如下:
    COLLSCAN:全表扫描
    IXSCAN:索引扫描
    FETCH:根据索引去检索指定document
    SHARD_MERGE:将各个分片返回数据进行merge
    SORT:表明在内存中进行了排序
    LIMIT:使用limit限制返回数
    SKIP:使用skip进行跳过
    IDHACK:针对_id进行查询
    SHARDING_FILTER:通过mongos对分片数据进行查询
    COUNT:利用db.coll.explain().count()之类进行count运算
    TEXT:使用全文索引进行查询时候的stage返回
    PROJECTION:限定返回字段时候stage的返回
    对于普通查询,我希望看到stage的组合(查询的时候尽可能用上索引):
    Fetch+IDHACK
    Fetch+IXSCAN
    Limit+(Fetch+IXSCAN)
    PROJECTION+IXSCAN
    SHARDING_FITER+IXSCAN
    不希望看到包含如下的stage
    COLLSCAN(全表扫描)
    SORT(使用sort但是无index)
    COUNT 不使用index进行count)

4、慢查询分析

  1. 开启内置的查询分析器,记录读写操作效率
    db.setProfilingLevel(n,m),n的取值可选0,1,2
    0表示不记录
    1表示记录慢速操作,如果值为1,m必须赋值单位为ms,用于定义慢速查询时间的阈值
    2表示记录所有的读写操作
  2. 查询监控结果
    db.system.profile.find().sort({millis:-1}).limit(3)
  3. 分析慢速查询
    应用程序设计不合理、不正确的数据模型、硬件配置问题,缺少索引等
  4. 解读explain结果 确定是否缺少索引

3、MongoDB 索引底层实现原理分析

MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,
单次查询从结构上来看要快于MySql。
MongoDB的安装和使用_第9张图片
B-树的特点:
(1) 多路 非二叉树
(2) 每个节点 既保存数据 又保存索引
(3) 搜索时 相当于二分查找

Mysql B+树是B-树的变种
MongoDB的安装和使用_第10张图片
B+ 树的特点:
(1) 多路非二叉
(2) 只有叶子节点保存数据
(3) 搜索时 也相当于二分查找
(4) 增加了 相邻节点指针

MongoDB和MySql的差别
(1)B+树相邻接点的指针可以大大增加区间访问性,可使用在范围查询等,而B-树每个节点 key 和data 在一起 适合随机读写 ,而区间查找效率很差。
(2)B+树更适合外部存储,也就是磁盘存储,使用B-结构的话,每次磁盘预读中的很多数据是用不上的数据。因此,它没能利用好磁盘预读的提供的数据。由于节点内无 data 域,每个节点能索引的范围更大更精确。
(3)注意这个区别相当重要,是基于(1)(2)的,B-树每个节点即保存数据又保存索引 树的深度小,所以磁盘IO的次数很少,B+树只有叶子节点保存,较B树而言深度大磁盘IO多,但是区间访问比较好。

四、 MongoDB 应用实战

1. MongoDB的行业具体应用场景

  • 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新。
  • 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
  • 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
  • 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
  • 直播,使用 MongoDB 存储用户信息、礼物信息等。
    MongoDB的安装和使用_第11张图片

2. Java 访问MongoDB

1.dependency

 <dependency>
        <groupId>org.mongodbgroupId>
        <artifactId>mongo-java-driverartifactId>
        <version>3.10.1version>
    dependency>

2.java

MongoClient mongoClient = new MongoClient("192.168.142.128:27017");
        MongoDatabase mongoDatabase = mongoClient.getDatabase("lg_resume");
        MongoCollection<Document> collection = mongoDatabase.getCollection("lg_resume_preview");
        Document document = new Document();
        document.append("expectSalary", -1);
        //查找迭代的对象,根据expectSalary降序排序
        // FindIterable documents = collection.find(Document.parse("{expectSalary:{$gt:21000}}")).sort(document);
        FindIterable<Document> documents = collection.find(Filters.gt("expectSalary", 20000)).sort(document);
        for (Document document1 : documents) {
            System.out.println(document1);
        }
        mongoClient.close();

3. Spring 访问MongoDB

1.applicationContext.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd">
    
    <mongo:db-factory id="mongoDbFactory" client-uri="mongodb://192.168.142.128:27017/lg_resume">mongo:db-factory>
    
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg index="0" ref="mongoDbFactory">constructor-arg>
    bean>
    
    <context:component-scan base-package="com.qch">context:component-scan>
beans>

2.Dao

public interface ResumeDao {
    void insertResume(Resume resume);
     List<Resume> findByNameAndSa(String name,double expectSalary);
}

@Repository("resumeDao")
public class ResumeDaoImpl implements ResumeDao {
    @Autowired
    private MongoTemplate mongoTemplate;
    public void insertResume(Resume resume) {
        mongoTemplate.insert(resume,"lg_resume_preview");
    }

public List<Resume> findByNameAndSa(String name, double expectSalary) {
        Query query=new Query();
        query.addCriteria(Criteria.where("name").is(name).andOperator(Criteria.where("expectSalary").gt(expectSalary)));
        List<Resume> list = mongoTemplate.find(query,Resume.class,dbtable);
        return list;
    }
}

3.测试类

public static void main(String[] args) throws ParseException {
        //构建spring 容器
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        ResumeDao resumeDao=applicationContext.getBean("resumeDao",ResumeDao.class);
        Resume resume=new Resume();
        resume.setName("qq");
        String daf="yyyy-MM-dd hh:mm:ss";
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat(daf);
        Date parse = simpleDateFormat.parse("2021-09-30 12:34:11");
        resume.setBirthday(parse);
        resume.setCity("南京");
        resume.setExpectSalary(18000);
        resumeDao.insertResume(resume);
    }

4. SpringBoot 访问MongoDB

1.application.properties

spring.data.mongodb.host=192.168.142.128
spring.data.mongodb.port=27017
spring.data.mongodb.database=lg_resume

2.repository

@Document("lg_resume_preview")
public class Resume
public interface ResumeRepository extends MongoRepository<Resume,String>{
    List<Resume> findByNameEquals(String name);
}

五、 MongoDB 架构

5.1 MongoDB的数据模型

  • 内嵌( 应用场景:数据对象之间有包含关系,数据对象之间有一对多或者一对一的关系)
    内嵌的方式指的是把相关联的数据保存在同一个文档结构之中。MongoDB的文档结构允许一个字段或者一个数组内的值作为一个嵌套的文档。

  • 引用(应用场景:当内嵌数据会导致很多数据的重复,表达比较复杂的多对多关系)
    引用方式通过存储数据引用信息来实现两个不同文档之间的关联,应用程序可以通过解析这些数据引用来访问相关数据。

5.2 MongoDB存储引擎

存储引擎是MongoDB的核心组件,负责管理数据如何存储在硬盘和内存上。MongoDB支持的存储引擎有 MMAPv1 ,WiredTiger和InMemory(适合数据不持久化,用于缓存)

1. WiredTiger存储引擎优势

MongoDB的安装和使用_第12张图片

2. WiredTiger引擎包含的文件和作用

MongoDB的安装和使用_第13张图片

  • WiredTiger.basecfg: 存储基本配置信息,与 ConfigServer有关系
  • WiredTiger.lock: 定义锁操作
  • table*.wt: 存储各张表的数据
  • WiredTiger.wt: 存储table* 的元数据
  • WiredTiger.turtle: 存储WiredTiger.wt的元数据
  • journal: 存储WAL(Write Ahead Log)
3. WiredTiger存储引擎实现原理

WiredTiger的写操作会默认写入 Cache ,并持久化到 WAL (Write Ahead Log),每60s或Log文件达到2G做一次 checkpoint (当然我们也可以通过在写入时传入 j: true 的参数强制 journal 文件的同步 ,writeConcern { w: , j: , wtimeout: }) 产生快照文件。WiredTiger初始化时,恢复至最新的快照状态,然后再根据WAL恢复数据,保证数据的完整性。

checkpoint流程
1.对所有的table进行一次checkpoint,每个table的checkpoint的元数据更新至WiredTiger.wt
2.对WiredTiger.wt进行checkpoint,将该table checkpoint的元数据更新至临时文件 WiredTiger.turtle.set
3.将WiredTiger.turtle.set重命名为WiredTiger.turtle。
4.上述过程如果中间失败,WiredTiger在下次连接初始化时,首先将数据恢复至最新的快照状态,然后根 据WAL恢复数据,以保证存储可靠性。

Journaling
在数据库宕机时 , 为保证 MongoDB 中数据的持久性,MongoDB 使用了 Write Ahead Logging 向磁盘上的 journal 文件预先进行写入。除了 journal 日志,MongoDB 还使用检查点(checkpoint)来保证数据的一致性,当数据库发生宕机时,我们就需要 checkpoint 和 journal 文件协作完成数据的恢复工作。

  1. 在数据文件中查找上一个检查点的标识符
  2. 在 journal 文件中查找标识符对应的记录
  3. 重做对应记录之后的全部操作

六、 MongoDB 集群高可用

6.1 MongoDB主从复制架构原理和缺陷

主从结构没有自动故障转移功能,需要指定master和slave端,不推荐在生产中使用。

6.2 复制集replica sets

MongoDB的安装和使用_第14张图片
复制集是由一组拥有相同数据集的mongod实例做组成的集群。 复制集是一个集群,它是2台及2台以上的服务器组成,以及复制集成员包括Primary主节点,secondary从 节点和投票节点。
复制集提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,保证数据的安全性。
1.采用复制集的原因

  • 高可用:能自动切换主从
  • 灾难恢复:可从从节点恢复,用于备份
  • 功能隔离:我们可以在备节点上执行读操作,减少主节点的压力 比如:用于分析、报表,数据挖掘,系统任务等。

6.3 复制集集群架构原理

oplog 具有幂等性,即无论执行几次其结果一致,这个比 mysql 的二进制日志更好用。
oplog的组成结构
MongoDB的安装和使用_第15张图片
复制集数据同步分为初始化同步和keep复制同步。初始化同步指全量从主节点同步数据,如果Primary节点数据量比较大同步时间会比较长。而keep复制指初始化同步过后,节点之间的实时同步一般是增量同步。

初始化同步有以下两种情况会触发:
(1) Secondary第一次加入。
(2) Secondary落后的数据量超过了oplog的大小,这样也会被全量复制。

MongoDB的Primary节点选举基于心跳触发。一个复制集N个节点中的任意两个节点维持心跳,每个节点维护其他N-1个节点的状态。
MongoDB的安装和使用_第16张图片主节点选举触发的时机:

  • 第一次初始化一个复制集
  • Secondary节点权重比Primary节点高时,发起替换选举
  • Secondary节点发现集群中没有Primary时,发起选举
  • Primary节点不能访问到大部分(Majority)成员时主动降级

当触发选举时,Secondary节点尝试将自身选举为Primary。主节点选举是一个二阶段过程+多数派协
议。

6.4 复制集集群搭建

MongoDB的安装和使用_第17张图片
1.文件准备

[root@node1 mongodb-linux-x86_64-4.1.3]# mkdir /data/mongo/data/server1 -p
[root@node1 mongodb-linux-x86_64-4.1.3]# mkdir /data/mongo/data/server2 -p
[root@node1 mongodb-linux-x86_64-4.1.3]# mkdir /data/mongo/data/server3 -p
[root@node1 mongodb-linux-x86_64-4.1.3]# mkdir /data/mongo/logs -p
[root@node1 mongodb-linux-x86_64-4.1.3]# cp mongo_37017.conf mongo_37018.conf 

2.主节点配置 mongo_37017.conf

# 主节点配置 
dbpath=/data/mongo/data/server1
bind_ip=0.0.0.0 port=37017
fork=true
logpath=/data/mongo/logs/server1.log
replSet=lagouCluster

从节点同上

3.进入其中一台客户端进行配置

[root@node1 mongodb-linux-x86_64-4.1.3]# ./bin/mongo --port 37017

var cfg ={"_id":"lagouCluster", "protocolVersion" : 1, "members":[ {"_id":1,"host":"192.168.142.128:37017","priority":10}, {"_id":2,"host":"192.168.142.128:37018"} ] }

rs.initiate(cfg)
rs.status()

4.节点的动态增删

增加节点 
rs.add("192.168.211.133:37019") 
删除slave 节点 
rs.remove("192.168.211.133:37019")

5.从节点读数据设置

lagouCluster:SECONDARY> rs.slaveOk()

6.仲裁节点
必须再主节点上设置

// 重新装载配置,并重新生成集群节点。 
rs.reconfig(cfg)

或者以动态增加节点的方式

注入节点 执行 rs.addArb("IP:端口");
rs.addArb("192.168.211.133:37020")

6.5分片集群

1.分片的工作原则
MongoDB的安装和使用_第18张图片分片集群由以下3个服务组成:

  • Shards Server: 每个shard由一个或多个mongod进程组成,用于存储数据。
  • Router Server: 数据库集群的请求入口,所有请求都通过Router(mongos)进行协调,不需要在应用程 序添加一个路由选择器,Router(mongos)就是一个请求分发中心它负责把应用程序的请求转发到对应的 Shard服务器上。
  • Config Server: 配置服务器。存储所有数据库元信息(路由、分片)的配置。(路由规则必须单独存在一个服务器)

2.分片策略

  • 范围分片(Range based sharding)
    MongoDB的安装和使用_第19张图片
    范围分片是基于分片主键的值切分数据,每一个区块将会分配到一个范围。
    范围分片适合满足在一定范围内的查找,例如查找X的值在[20,30)之间的数据,mongo 路由根据Config server中存储的元数据,可以直接定位到指定的shard的Chunk中。
    缺点: 如果shard key有明显递增(或者递减)趋势,则新插入的文档多会分布到同一个chunk,无法扩展写的能力。【导致热块-》5000个用户都用到这个值】

  • hash分片(Hash based sharding)

MongoDB的安装和使用_第20张图片
相邻的值不一定再一个块
缺点:查询费劲
优化:
组合片键 A + B(散列思想,不能是直接hash)
数据库中没有比较合适的片键供选择,或者是打算使用的片键基数太小(即变化少如星期只有7天可变化),可以选另一个字段使用组合片键,甚至可以添加冗余字段来组合。一般是粗粒度+细粒度进行组合。【A控制shard,B控制chunk】

6.6分片集群搭建

MongoDB的安装和使用_第21张图片

1.配置 并启动config 节点集群(3个)

# 数据库文件位置
dbpath=config/config1
#日志文件位置
logpath=config/logs/config1.log
# 以追加方式写入日志
logappend=true
# 是否以守护进程方式运行
fork = true 
bind_ip=0.0.0.0
port = 17017
# 表示是一个配置服务器
configsvr=true
#配置服务器副本集名称
replSet=configsvr

启动配置节点

./bin/mongod -f config/config-17017.conf
./bin/mongod -f config/config-17018.conf
./bin/mongod -f config/config-17019.conf

进入任意节点的mongo shell 并添加 配置节点集群 注意use admin

./bin/mongo --port 17017 
use admin 
var cfg ={"_id":"configsvr", "members":[ {"_id":1,"host":"192.168.142.128:17017"}, {"_id":2,"host":"192.168.142.128:17018"}, {"_id":3,"host":"192.168.142.128:17019"}] };
rs.initiate(cfg)

rs.reconfig(cfg)

2.配置shard集群
shard1集群搭建37017到37019

dbpath=shard/shard1/shard1-37017
bind_ip=0.0.0.0
port=37017
fork=true
logpath=shard/shard1/shard1-37017.log
replSet=shard1
shardsvr=true

启动每个mongod 然后进入其中一个进行集群配置

 var cfg ={"_id":"shard1", "protocolVersion" : 1, "members":[ {"_id":1,"host":"192.168.142.128:37017"}, {"_id":2,"host":"192.168.142.128:37018"}, {"_id":3,"host":"192.168.142.128:37019"} ,
 {"_id":4,"host":"192.168.211.133:37020","arbiterOnly":true}]};
 rs.initiate(cfg) 
 rs.status()
 rs.addArb("192.168.211.133:37020")
 
 var cfg ={"_id":"shard2", "protocolVersion" : 1, "members":[ {"_id":1,"host":"192.168.142.128:47017"}, {"_id":2,"host":"192.168.142.128:47018"}, {"_id":3,"host":"192.168.142.128:47019"} ]};

补充:仲裁节点
有仲裁节点复制集搭建
和上面的配置步骤相同 只是增加了 一个特殊的仲裁节点
注入节点 执行 rs.addArb(“IP:端口”);
rs.addArb(“192.168.211.133:37020”)

3.配置和启动 路由节点
/route/route-27017.conf

port=27017
bind_ip=0.0.0.0
fork=true
logpath=route/logs/route.log configdb=configsvr/192.168.142.128:17017,192.168.142.128:17018,192.168.142.128:17019

[root@node1 mongo_shard_cluster]# ./bin/mongos -f route/route-27017.conf 

mongos(路由)中添加分片节点
进入路由mongos

mongos> sh.status()
sh.addShard("shard1/192.168.142.128:37017,192.168.142.128:37018,192.168.142.128:37019"); sh.addShard("shard2/192.168.142.128:47017,192.168.142.128:47018,192.168.142.128:47019");

开启数据库和集合分片(指定片键)
继续使用mongos完成分片开启和分片大小设置

为数据库开启分片功能 
sh.enableSharding("lagou_resume") 
为指定集合开启分片功能 sh.shardCollection("lagou_resume.lagou_resume_datas",{"片键字段名如 name":索引说 明})

sh.shardCollection(“lagou_resume.lagou_resume_datas”,{“name”:“hashed”})

4.向集合中插入数据测试

use lagou_resume; 
for(var i=1;i<= 1000;i++){ db.lagou_resume_datas.insert({"name":"test"+i, salary:(Math.random()*20000).toFixed(2)}); }

六、 MongoDB 安全认证

7.1

  • 7.1.1
shard2:PRIMARY> db.createUser({user:"myroot",pwd:"123",roles:[{role:"root",db:"laagou_resume"}]});
2021-04-22T12:42:05.726+0800 E QUERY    [js] Error: couldn't add user: No role named root@laagou_resume :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.createUser@src/mongo/shell/db.js:1408:15
@(shell):1:1
shard2:PRIMARY> db.createUser({user:"myroot",pwd:"123",roles:[{role:"root",db:"admin"}]})
Successfully added user: {
	"user" : "myroot",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}

user:创建的用户名称,如 admin、root 、lagou
pwd:用户登录的密码
roles:为用户分配的角色,不同的角色拥有不同的权限,参数是数组,可以同时设置多个
role:角色,MonngoDB 已经约定好的角色,不同的角色对应不同的权限 后面会对role做详细解释
db:数据库实例名称,如 MongoDB 4.0.2 默认自带的有 admin、local、config、test 等,即为哪个数据库实例 设置用户

  • 7.1.2 修改密码
    db.changeUserPassword( ‘root’ , ‘rootNew’ );

  • 7.1.3 用户添加角色
    db.grantRolesToUser( ‘用户名’ , [{ role: ‘角色名’ , db: ‘数据库名’}])

  • 7.1.4 以auth 方向启动mongod
    ./bin/mongod -f conf/mongo.conf --auth
    (也可以在mongo.conf 中添加auth=true 参数)

  • 7.1.5 验证用户
    db.auth(“账号”,“密码”)

  • 7.1…删除用户
    db.dropUser(“用户名”)

7.2 单机安全认证实现流程

  1. 创建管理员
    MongoDB 服务端开启安全检查之前,至少需要有一个管理员账号,admin 数据库中的用户都被视为管理员如果 admin 库没有任何用户的话,即使在其他数据库中创建了用户,启用身份验证,默认的连接方式依然会有超级权限,即仍然可以不验证账号密码照样能进行 CRUD,安全认证相当于无效。
>use admin 
switched to db admin
> db.createUser(  {user:"root",pwd:"123456", roles:[{role:"root",db:"admin"}] })
  1. 创建普通用户
    如下所示 lg_resume是自己新建的数据库,没安全认证之前可以随意 CRUD,其余的都是 mongoDB4.0.2 自带的数据库
    为 admin 库创建管理员之后,现在来为 普通数据库创建普通用户,以 lg_resume为例,方式与创建管理员一致,切换到指定数据库进行创建即可。

如下所示,为 lg_resume数据库创建了两个用户,zhangsan 拥有读写权限,lisi 拥有只读权限,密码都是 123456.

> use lg_resume
switched to db lg_resume
> db.createUser({user:"zhangsan",pwd:"123456",roles:[{role:"readWrite",db:"lg_resume"}]})

> db.createUser({user:"lisi",pwd:"123456",roles:[{role:"readWrite",db:"lg_resume"}]})

  1. MongoDB 安全认证方式启动
    mongod --dbpath=数据库路径 --port=端口 --auth
    也可以在配置文件中 加入 auth=true
    MongoDB的安装和使用_第22张图片
> use admin
switched to db admin
> db.auth("root","123456")

7.3 分片集群安全认证

1.开启安全认证之前 进入路由创建管理员和普通用户

mongos> use admin
switched to db admin
mongos> db.createUser({user:"root",pwd:"123456", roles:[{role:"root",db:"admin"}]})
Successfully added user: {
	"user" : "root",
	"roles" : [
		{
			"role" : "root",
			"db" : "admin"
		}
	]
}
mongos> use lg_resume
switched to db lg_resume
mongos> db.createUser({user:"lagou_gx",pwd:"abc321",roles:[{role:"readWrite",db:"lg_resume"}]})
Successfully added user: {
	"user" : "lagou_gx",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "lg_resume"
		}
	]
}


2.关闭所有的配置节点 分片节点 和 路由节点

#安装psmisc 
yum install psmisc
 #安装完之后可以使用killall 命令 快速关闭多个进程 
 killall mongod

3.生成密钥文件 并修改权限

openssl rand -base64 756 > data/mongodb/testKeyFile.file 
chmod 600 data/mongodb/keyfile/testKeyFile.file

4.配置节点集群和分片节点集群开启安全认证和指定密钥文件

auth=true 
keyFile=data/mongodb/testKeyFile.file

5.在路由配置文件中 设置密钥文件

keyFile=data/mongodb/testKeyFile.file

6.启动所有的配置节点 分片节点 和 路由节点 使用路由进行权限验证
可以编写一个shell 脚本 批量启动

./bin/mongod -f config/config-17017.conf 
./bin/mongod -f config/config-17018.conf 
./bin/mongod -f config/config-17019.conf 
./bin/mongod -f shard/shard1/shard1-37017.conf 
./bin/mongod -f shard/shard1/shard1-37018.conf 
./bin/mongod -f shard/shard1/shard1-37019.conf 
./bin/mongod -f shard/shard2/shard2-47017.conf 
./bin/mongod -f shard/shard2/shard2-47018.conf 
./bin/mongod -f shard/shard2/shard2-47019.conf 
./bin/mongos -f route/route-27017.conf

加执行权限

[root@node1 mongo_shard_cluster]# vi startup.sh
[root@node1 mongo_shard_cluster]# chmod +x startup.sh

执行命令

[root@node1 mongo_shard_cluster]# ./startup.sh

7.Spring boot 连接安全认证的分片集群

spring.data.mongodb.host=192.168.142.128
spring.data.mongodb.port=27017
spring.data.mongodb.database=lagou_resume
spring.data.mongodb.username=zhangsan
spring.data.mongodb.password=123456
   #spring.data.mongodb.uri=mongodb://账号:密码@IP:端口/数据库名

root超级管理员权限不可用


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

你可能感兴趣的:(分布式集群搭建)