Fork me on Gitee

【MongoDB】MongoDB原理分析、集群搭建(Docker)与简单使用

一、MongoDB 简介

MongoDB是一个基于分布式文件存储的数据库,介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的。其目的是为WEB应用提供可扩展的高性能数据存储解决方案。

1.MongoDB简单结构

{
    "_id": ObjectId("611cbe00de4c000098000885"),
    "name": "熊二",
    "skill": {
        "Program": "well",
        "English": "CET-4"
    },
    "Sort": NumberInt("1"),
    "IsDeleted": false,
}

2.为什么用MongoDB?

  1. 可以较为容易的实现动态的表结构字段。
  2. 比普通数据库高数倍甚至是数十倍的读写速度和并发量。
  3. 在需求不明确/需求变化频繁(表结构不明确)的情况下,使用MongoDB的开发和维护成本最低

3.MongoDB的性能测试

分别开启100个线程、每个线程插入100条 userInfo(userid、username、address、age) 数据

List<Task> tasks = new List<Task>();
Parallel.For(0, 100, (i) =>
{
    tasks.Add(Task.Run(() =>
    {
        try
        {
            // MySqlHelper.ExecuteNonQuery(MySqlHelper.Conn, System.Data.CommandType.Text, sqls);  Mysql
            collection.InsertManyAsync(userinfos); // mongo
            Console.WriteLine($"已插入100条数据");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw;
        }
    }));
});

不同线程数测试结果 (单位:秒)

线程数 Mysql时间 Mongo时间
100 8 0.6
300 18 0.9
500 31 1.4
1000 60 2
2000 error 4
5000 error 8
20000 error 18

   

二、Mongodb 深入了解

1.优点

  1. 扩展性强,MongoDB是分布式集群,可以平行扩展,也使得大量的并发可以通过几个甚至几十个节点的集群同时实现。
  2. 数据字段都是动态的,每条数据的字段都可以不一样。
  3. 读写速度极快,写数据只要在内存里完成就可以返回,保存到硬盘的操作则在后台异步完成,而读数据在日志硬盘文件中读取,这个文档数据数据都是顺序存储的,不用像MySql要耗费磁头寻道时间。

有细心的人可能注意到了,mongodb每60秒刷一次数据到硬盘上,系统断电了、宕机了数据彻底不就彻底丢失了吗?

其实mongodb还有一个Journal日志的东西,MongoDB会先把数据更新写入到Journal 里然后再更新内存数据,然后再返回应用端。Journal会以100ms的间隔批量刷到盘上。这样的情况下,即使出现断电数据尚未保存到文件,由于有Journal文件的存在,MongoDB会自动根据Journal里面的操作历史记录来对数据文件重新进行追加。

2.缺点

  1. 很难胜任极其复杂的业务环境,各种语言对其支持不深入。
  2. 占用空间大,比如事务这个东西就是靠数据大量冗余而做到的。
  3. 单机MongoDB的可靠性较差,且不会有事务。

3.存储特点

MongoDB使用文档的方式存储数据,很像 JavaScript 中定义的 JSON 格式,也类似于elasticsearch,同样支持索引。不过数据在存储的时候 MongoDB 数据库为文档增加了序列化的操作,最终存进磁盘的其实是一种叫做 BSON 的格式,即 Binary-JSON。

4.存储形式

  1. 文档:它是由字段和值对组成的数据结构。
  2. 集合:集合就是多个文档,类似于关系数据库中的表。
  3. 数据库:MongoDB中多个文档组成集合,多个集合组成数据库。
    PS. MongoDB进行连表查询的时候,两张表可能在不同的分片上,会影响查询的性能,所以MongoDB不推荐连表查询,而采用文档循环嵌套的方法。

4.持久化方式

MongoDB 的所有数据实际上是存放在硬盘的,所有要操作的数据通过 mmap 的方式映射到内存某个区域内。MongoDB就在这块区域里面进行数据修改,在内存中修改了数据后,mmmap 数据更新到硬盘之前,系统宕机了,数据就会丢失。


   

三、MongoDB的安装及简单操作

1.基本概念

副本集:mongodb里的副本集就是集群的意思,mongodb通过大量的数据冗余实现高可用,有主从和仲裁两种模式。

分片:当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。

2.使用Docker安装MongoDB集群环境(无密码)

docker pull mongo

#创建三个mongodb容器
docker run --name mongo1 -p 27017:27017 -v /usr/local/docker/mongo1/db:/data/db -d mongo --replSet "rs0"
docker run --name mongo2 -p 27018:27017 -v /usr/local/docker/mongo2/db:/data/db -d mongo --replSet "rs0"
docker run --name mongo3 -p 27019:27017 -v /usr/local/docker/mongo3/db:/data/db -d mongo --replSet "rs0"

#进入主节点容器
docker exec -it mongo1 bash
#连接客户端
mongo

# 初始化集群 
rs.initiate({ 
    _id:"rs0",
    members:[  
        {_id:0,host:"47.107.64.24:27017"}, 
        {_id:1,host:"47.107.64.24:27018"}, 
        {_id:2,host:'47.107.64.24:27019',arbiterOnly:true}
    ]
})
# arbiterOnly:true 设为仲裁节点

#查看配置
rs.conf()
#查看状态
rs.status()

3.简单增删改查

// 插入
db.Userinfo.insert({name:'司马',age:25})
db.Userinfo.insert({name:'熊二',skill:{Program:'well',English:'CET-4'}})  

// 保存数据 与insert不同的是,如果文档的_id存在则修改,如果文档的_id不存在则添加 
db.集合名称.save(document) 

// 查找
db.Userinfo.find() 
db.UserInfo.findOne()  
db.Userinfo.find({name:'司马'},{name:1,age:1,_id:0})  
db.Userinfo.find({"name":/司/})  //全模糊

// 修改
db.Userinfo.update({name:"山治"},{name:"路飞"})   // 直接替换
db.Userinfo.update({name:"司马"},{$set:{name:"sima"}})  // 更新部分字段

// 删除删除一个或者多个
db.Userinfo.remove(doc,IsSingle)
posted @ 2021-08-22 17:20  Roushan_IT  阅读(641)  评论(0编辑  收藏  举报