mongodb架构模式及部署简介

  • 1. mongodb简介
  • 1.1 mongodb概念
  • 1.2 mongodb主要特点
  • 1.3 mongodb限制
  • 2. mongodb架构模式
  • 2.1 副本集Replica Set
  • 2.2 分片Shard
  • 2.3 持久化
  • 3. mongodb结构以及数据类型
  • 3.1 结构与关系数据库比对
  • 3.2 BSON数据类型
  • 4. mongodb集群搭建
  • 4.1 部署环境
  • 4.2 单机部署
  • 4.3 高可用部署步骤
  • 5. springboot 集成使用mongodb
  • 5.1 引入jar包
  • 5.2 配置
  • 5.3 简单增删改查操作
  • 6. 参考文献


参与的项目中在使用mongodb做图片视频等文档的存储使用工具,目前运行正常,此处对mongodb相关概念、架构模式、结构与数据类型、单机部署以及高可用部署步骤等进行汇总总结,以利于后期持续深入学习!文中不免疏漏之处,望读者给予指正,感激之至!

1. mongodb简介

1.1 mongodb概念

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

1.2 mongodb主要特点

mongodb的主要特点

(1)mongodb提供了一个面向文档存储,操作起来比较简单和容易的非关系型数据库。
(2)可以在mongodb记录中设置任何属性的索引来实现更快的排序。
(3)可以通过本地或者网络创建数据镜像,这使得mongodb含有更强的扩展性。
(4)如果负载的增加(需要更多的存储空间和更强的处理能力),它可以分布在计算机网络中的其它节点上,这就是所谓的分片。
(5)mongodb支持丰富的查询表达式,查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象和数组。
(6)mongodb中的Map/Reduce主要是用来对数据进行批量处理和聚合操作,Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传递给Reduce函数进行处理。另外Map函数和Reduce函数是使用JavaScript编写的,所以可以通过db.runCommand和mapreduce命令来执行MapReduce操作。
(7)GridFS是mongodb中的一个内置功能,可以用于存放大量小文件。
(8)mongodb允许在服务端执行脚本,可以用JavaScript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
(9)mongodb支持各种编程语言:JAVA、RUBY、PYTHON、C++、PHP、C#等多种语言并且MongoDB的安装也非常简单。

1.3 mongodb限制

mongodb的使用也会有一些限制:

(1)mongodb不支持事务操作(最主要的缺点)
(2)mongodb占用空间过大
(3)mongodb没有如 MySQL 那样成熟的维护工具,这对于开发和IT运营都是个值得注意的地方。

2. mongodb架构模式

2.1 副本集Replica Set

(1)概念

MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制还允许您从硬件故障和服务中断中恢复数据。

MongoDB复制结构图如下所示:

.net mongodb架构 mongodb部署架构_数据


(2)结构

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
MongoDB复制是主从结构:一主一从或一主多从
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

(3)主从节点设置

启动一个MongoDB服务,连接后使用命令rs.initiate()来启动一个新的副本集
使用rs.conf()来查看副本集的配置,使用rs.status()命令查看副本集状态
添加从节点:使用rs.add(HOST_NAME:PORT)方法来添加副本集的成员
使用命令db.isMaster()判断当前运行的Mongo服务是否为主节点

MongoDB中只能通过主节点将Mongo服务添加到副本集中,主从在主机宕机后所有服务将停止,而副本集在主机宕机后,副本会接管主节点成为主节点,不会出现宕机的情况。

2.2 分片Shard

(1)概念

在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求。
当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。
这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。

.net mongodb架构 mongodb部署架构_副本集_02


(2)主要组件

Shard:
用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障
Config Server:
mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息。
Query Routers:
前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

(3)配置操作

1)常规启动shard节点与config server节点
如下文,单机节点启动方式

2)路由节点启动
mongos --port 端口号 --configdb configserverIP:configserverPort --fork --logpath=日志路径 --chunkSize 500
chunkSize这一项是用来指定chunk的大小的,单位是MB,默认大小为200MB

3)路由节点添加分片节点
db.runCommand({ addshard:"shardIP:shardPORT" })
db.runCommand({ enablesharding:"databaseNAME" }) #指定数据库分片生效
db.runCommand({shardcollection: "databaseNAME.collectionName",key : {"fieldName": 1} } )  # 指定数据库里需要分片的集合和片键

4)客户端使用
连接 路由节点即可

2.3 持久化

Mongodb在1.8版本之后开始支持journal,就是我们常说的redo log,用于故障恢复和持久化。
当系统启动时,mongodb会将数据文件映射到一块内存区域,称之为Shared view,在不开启journal的系统中,数据直接写入shared view,然后返回,系统每60s刷新这块内存到磁盘,这样,如果断电或down机,就会丢失很多内存中未持久化的数据。

当系统开启了journal功能,系统会再映射一块内存区域供journal使用,称之为private view,mongodb默认每100ms刷新privateView到journal,也就是说,断电或宕机,有可能丢失这100ms数据,一般都是可以忍受的,如果不能忍受,那就用程序写log吧。这也是为什么开启journal后mongod使用的虚拟内存是之前的两倍。

Mongodb的隔离级别是read_uncommitted,不管使用不使用journal,都是以内存中的数据为准,只不过,不开启journal,数据从shared view读取,开启journal,数据从private view读取。

3. mongodb结构以及数据类型

3.1 结构与关系数据库比对

关系数据库

MongoDB

对比

Database

Database

数据库/数据库

Table

Collection

数据库表/集合

Row

Document

数据库记录行/文档

Column

Field

数据列/数据字段

Index

Index

索引/索引

Table join

表关联/MongoDB不支持

Primary key

Object ID

主键/MongoDB自动将_id设为主键

3.2 BSON数据类型

BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。
BSON可以做为网络数据交换的一种存储形式,这个有点类似于Google的Protocol Buffer,但是BSON是一种schema-less的存储形式,它的优点是灵活性高、具有轻量性、可遍历性、高效性,但它的缺点是空间利用率不是很理想。

4. mongodb集群搭建

4.1 部署环境

操作系统: CentOS Linux release 7.2.1511
mongodb版本:mongodb-linux-x86_64-rhel70-5.0.2

4.2 单机部署

(1)mongodb下载:https://www.mongodb.com/try/download/community,选择版本、系统、tgz;
mongodb-linux-x86_64-rhel70-5.0.2.tgz

(2)解压文件,创建data/log/conf文件夹
tar -zvxf mongodb-linux-x86_64-rhel70-5.0.2.tgz
mv mongodb-linux-x86_64-rhel70-5.0.2 mongodb
cd mongodb
mkdir data
mkdir log
mkdir conf

(3)创建配置文件mongodb.conf,以及添加相关配置项
# 数据存储
dbpath=/root/mongodb/data
# 日志文件路径
logpath=/root/mongodb/log/mongodb.log
# 追加
logappend=true
# 端口号
port=27017
# 后台进程
fork=true
# 允许远程访问
bind_ip=0.0.0.0
# 是否账号密码访问,创建用户以及密码后可设置为true
auth=false

(4)启动mongodb
cd bin
./mongod -f ../conf/mongodb.conf

(5)验证启动结果
ps -ef | grep mongo

4.3 高可用部署步骤

1)创建副本集
一个分片副本集中的一个副本:
replSet=rs1
shardsvr=true

设置副本集:
登录第一个副本,
mongo rsIP1:Port1/admin
config = { _id:"rs1", members:[
      {_id:0,host:"rsIP1:Port1"},
      {_id:1,host:"rsIP2:Port2"},
      {_id:2,host:"rsIP3:Port3",arbiterOnly:true}
    ]
   }
 注意:这里id rs1 需要与副本集中的名称一样即replSet的值

rs.initiate(config)
{ "ok" : 1 }
 提示这个说明初始化成功

同样操作:第二个分片副本集 rs2,第三个分片副本集 rs3。

2)mongos指定config server
config Server配置项:configsvr=true
mongos设置配置项: configdb=configServerIp1:Port1,Ip2:Port2,Ip3:Port3

3) mongos设置分片
连接到第一个mongos上
mongo mongosIP1:mongosPort1/admin
db.runCommand({addshard:"rs1/rs1IP1:Port1,rs1IP2:Port2,rs1IP3:Port3",allowLocal:true}); 
db.runCommand({addshard:"rs2/rs2IP1:Port1,rs2IP2:Port2,rs2IP3:Port3"});
db.runCommand({addshard:"rs3/rs3IP1:Port1,rs3IP2:Port2,rs3IP3:Port3"});
  
# 将第一个分片的所有副本全部加入
# 如里shard是单台服务器,用 db.runCommand( { addshard : "[: ]" } )这样的命令加入
#  如果shard是副本集,用db.runCommand( { addshard : "replicaSetName/[:port][,serverhostname2[:port],…]" });这样的格式表示.

4)指定数据库分片生效
db.runCommand({enablesharding:"databaseName"});
# 指定databaseName分片生效

5. springboot 集成使用mongodb

5.1 引入jar包

compile 'org.springframework.boot:spring-boot-starter-data-mongodb:2.2.2.RELEASE'

5.2 配置

spring.data.mongodb.uri=mongodb://userName:pwd@192.168.65.153:27017/databaseName?authSource=admin&authMechanism=SCRAM-SHA-1

5.3 简单增删改查操作

(1)引入MongoTemplate
@Autowired
private MongoTemplate mongoTemplate;

(2)新增
TestEntity testEntity1 = mongoTemplate.save(testEntity,"Collection-Name");

(3)删除
Query query = new Query(Criteria.where("id").is(id));
DeleteResult deleteResult = mongoTemplate.remove(query,TestEntity.class,"Collection-Name");

(4)修改
Query query = new Query(Criteria.where("id").is(testEntity.getId()));
Update update = new Update();
update.set("name", testEntity.getName());
UpdateResult updateResult = mongoTemplate.updateFirst(query,update,TestEntity.class,"Collection-Nam");

(5)查询
Query query = new Query(Criteria.where("id").is(id));
TestEntity testEntity = mongoTemplate.findOne(query,TestEntity.class,"Collection-Name");

6. 参考文献

[1] https://www.mongodb.org.cn/
[2] https://www.runoob.com/mongodb/mongodb-tutorial.html
[3] https://www.jb51.net/article/167276.htm