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复制结构图如下所示:
(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存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量。
这时,我们就可以通过在多台机器上分割数据,使得数据库系统能存储和处理更多的数据。
(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