论文部分内容阅读
摘要:当今数据已渗透到各行业领域,社会发展已进入“大数据”时代,针对大数据进行管理、处理的新技术不断涌现。数据资源种类多、容量大,会造成非IT技術人员进行数据应用困难,数据的潜在价值难以体现,同时大数据的处理都是基于大平台,平时一般的数据分析人员在处理数据时很少能在大平台中进行数据分析,因此急需一套高可用高性能的亿级数据快速查询应用方法。
该文通过研究MongoDB的存储原理和实现机制,讨论了提升数据库可用性和存储查询性能的方法,并设计了高可用高性能的数据库集群方案,为海量数据的业务应用奠定了基础。
关键词:MongoDB;大数据;高性能;集群
中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2017)31-0008-03
1 概述
随着web2.0时代的到来,传统的关系型数据库在面对超大规模的数据和高并发动态网页生成任务时,显得非常吃力。关系型数据库具有严格的ACID特性(Atomicity原子性、Consistency一致性、Isolation隔离性、Durability持久性),因此会产生一些例如表连接等操作,这样会大大降低系统的性能。NoSQL的概念提出于20世纪80年代,当时是关系型数据库的天下,并没有现实的使用需求和应用场景,更多的是为了跟关系型数据库的概念相区别。但是,进入21世纪之后,随着国内互联网产业的高速发展和一批以百度、腾讯、阿里巴巴为代表的互联网巨头企业的诞生,带动了一大批创新行企业并改变了人们的生活方式,互联网已成为不可或缺的一部分。这样,网民不仅是信息消费者,也成为信息创建者,随着数据规模扩大和大批非结构化数据的产生,NoSQL数据库有了特定需求场景。
近年来,NoSQL数据库得到快速发展,具有代表性的就是MongoDB。目前国内对于MongoDB的研究还比较少。张路路研究了基于MongoDB的大数据存储方法,对典型的内存优化技术和布式存储技等大数据存储技术进行研究分析[1]。吴德宝对关系与非关系数据库进行了比较与分析,并对它们的主要典型代表Microsoft SQL Server和Mongo DB进行实验测试,对它们的性能做定量的对比和分析[2]。仝义明、黄蔚、李戴维等人设计并实现了一个基于MongoDB的多源信息集成系统,通过数据集成将存放在不同地点的数据进行数据采集与转化,利用MongoDB集群分布式存储海量数据并提供统一检索,实现了数据的共享[3]。
目前而言,国内研究主要在存储和基于MongoDB设计应用系统以及与传统关系数据库进行对比研究。本文的侧重点有所不同,主要研究利用MongoDB实现数据的高可用性和数据查询的高性能。
2 MongoDB简介
关系型数据库建立在关系模型的基础上,以数据表为单位进行存储,擅长结构化数据的存储、查询、删除、连接、交集、并集、差集等操作,仍是各个领域主要在用的数据库类型,在此不做赘述。
NoSQL(Not Only SQL)是非关系型数据存储的广义定义,得到广泛认同。在目前主要的NoSQL数据库中,有MongoDB、HBase、HyperTable、Cassandra等,而其中MongoDB是功能最丰富,最像关系数据库的。
MongoDB是一款强大、灵活,且易于扩展的通用型数据库[4]。相比关系型数据库,MongoDB是一个面向文档(document-oriented)的数据库,它有很多特点和优势,主要体现在以下几个方面:
1) 去除了关系型数据库的关系特征,面向集合存储,使得数据十分易于扩展;
2) 具有很好的读写性能,在海量数据下,性能表现同样非常优秀,这主要因为其结构简单,不受关系型数据库中表间关系的束缚;
3) 不需要预先创建数据字段,在集合中可以随时存入自定义的数据格式,可以轻而易举地增加或者删除字段;
4) 实现高可用架构的同时,不会对性能产生较大影响;
基于以上特点,本文选择MongoDB作为研究对象和候选工具,以解决处理海量数据时遇到的性能瓶颈问题。
3 高可用性研究
3.1 分片与副本集
我们知道,单台服务器的资源存储和计算能力都是有限的,当数据量和计算量达到一定程度时,进行垂直扩展会产生高昂的成本,这时就需要使用分布式存储进行横向扩展。
MongoDB实现的分布式技术,主要在于数据的分片(Shard)以及副本集,分片是集群中负责某一子集的一台或多台服务器[5]。简单来说,分片就是将数据集分割存储在不同的服务器上,以此来提高数据容量和读写吞吐量。MongoDB的分片以集合(Collection,集合的概念与关系型数据库中数据表Table类似)作为最小的单位,一个集合中的数据通过片键被分配到不同的分片节点存储。为了提高单个分片的可用性,每个分片需要有多个副本,存储在不同服务节点上,同一分片的多个副本组成一个副本集(Replica Set)。集合、分片和副本集的关系如图1所示。
3.2 高可用集群设计
MongoDB集群的高可用性是通过副本集来实现的,这种数据冗余机制是可以灵活配置的,可以设置每个分片的副本数量。一个副本集中的节点是有主从之分的,与传统的主从集群的不同之处在于它的主节点是不固定的,主节点是由集群推举产生,节点之间通过心跳机制检测活跃度,当主节点宕机或者停止时会自动将其他节点切换为主节点,因此具有很好的故障自动恢复功能。
通常情况下,搭建MongoDB高可用集群需要多台服务器实现,限于实验条件限制,本文使用Docker虚拟化技术模拟服务器完成搭建。在整个集群中,包含以下功能节点:
Mongos:集群的路由节点,用来处理分发客户机发起的数据库请求,它掌握着每个分片的内容记录,会将数据请求转发到对应的分片节点并负责聚合分片服务器的结果集,返回给客户端。这样客户端就可以像使用单机服务器一样进行正常的请求,同时数据库实现了系统负载均衡。 Configdb:集群的配置节点,用来存储整个集群的配置文件,每个数据块的片键范围等,也负责新的分片服务器的加入和认证。
Shards:集群的分片服務器节点,用来存储真实的业务数据,每个分片可以存在多个副本。
根据以上研究,每个分片保存两个副本,使用两个以上配置节点和两个以上路由节点,即可保证整个集群的高可用性。其中任何一个节点宕机,都不会影响数据库的正常服务。集群架构如图2所示。
3.3 可用性实验
首先,需要配置和启动集群中的各个节点。
(1) 配置和启动shard1的脚本如下:
[dbpath=/MongoDB/data/shard1
logpath=/MongoDB/log/shard1.log
pidfilepath=/MongoDB/pid/shard1.pid
directoryperdb=true
logappend=true
replSet=shard1
port=10010
fork=true
shardsvr=true
journal=true ]
同理,启动shard1副本节点和shard2、shard3类似,仅修改部分参数即可。
(2) 配置和启动配置节点的脚本如下
[dbpath=/MongoDB/config/config1
logpath=/MongoDB/log/config1.log
pidfilepath=/MongoDB/pid/config1.pid
directoryperdb=true
logappend=true
port=10040
fork=true
configsvr=true
journal=true ]
同理,启动其他config节点与此类似,仅修改部分参数即可。
(3) 配置和启动路由节点的脚本如下
[configdb=mongo0:10040,mongo1:10040,mongo2:10040
pidfilepath=/MongoDB/pid/route.pid
port=10050
chunkSize=1
logpath=/MongoDB/log/route.log
logappend=true
fork=true ]
同理,启动其他路由节点与此类似,仅修改部分参数即可。需要说明的是,脚本中的mongo0,mongo1和mongo2分别为三个配置节点服务器的IP地址,实验时需要替换为相应的值。
然后,需要登录到路由节点,配置分片和片键。创建vehicle表做分片,车辆的ID为它的VIN码,因此将VIN字段作为片键且唯一。
设置片键命令如下:
db.runCommand( { shardcollection : "testdata.vehicle",key : {vin: 1},unique : true } )
最后,通过路由节点,插入百万条数据。脚本如下
[for( var i=1; i<=1000000; i )
db.vehicle.save({vin : i, volumn1 : “123456”, volumn2 : i*5}); ]
此时可以停掉任意个分片节点服务器,通过db.vehicle.stats()命令,即可查看车辆表的状态。实验表明,只要分片的副本集内,有一个节点服务器正常工作,整个集群的数据服务就不会中断,MongoDB集群完全满足高可用性要求。
4 高性能研究
截至目前,MongoDB社区版的最新版本为3.4.9。在MongoDB版本3.0之前,其性能存在诸多问题,与2.x的版本相比,MongoDB3增加了高性能、可伸缩的数据存储引擎WiredTiger,从而使得MongoDB3性能得到了极大的提升,尤其是写性能和对硬件资源的利用率。MongoDB 2.6及更早的版本,使用MMAP存储引擎,基于内存映射技术;MongoDB3支持两个引擎:支持集合级锁的MMAP和支持压缩和文档级锁的WiredTiger存储引擎。MongoDB3.0在多线程、批量插入场景下较之于MongoDB2.6有大约7倍的增长[6],如图3所示。
4.1 wiredTiger存储引擎
wiredTiger(简称WT)支持的存储方式有三种:行存储、列存储以及LSM。MongoDB在使用时,只是把它作为普通的KV存储引擎来使用,MongoDB的每个集合对应一个WT的table,table里包含多个Key-value pairs,以B树形式存储。同时,WT改进了锁粒度和灵活性,并且提供了snappy(默认)和zlib两种压缩方式。经测试,WT的平均压缩率可达20%以上。
MongoDB 3.0支持用户自定义存储引擎,用户可配置使用mmapv1或者wiredTiger存储引擎[7]。
下面测试插入100w条数据时,WT引擎与mmapv1引擎的性能差异。
使用的Python代码如下:
[import datetime
ISOTIMEFORMAT = ’%Y-%m-%d %X’
from pymongo import MongoClient
该文通过研究MongoDB的存储原理和实现机制,讨论了提升数据库可用性和存储查询性能的方法,并设计了高可用高性能的数据库集群方案,为海量数据的业务应用奠定了基础。
关键词:MongoDB;大数据;高性能;集群
中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2017)31-0008-03
1 概述
随着web2.0时代的到来,传统的关系型数据库在面对超大规模的数据和高并发动态网页生成任务时,显得非常吃力。关系型数据库具有严格的ACID特性(Atomicity原子性、Consistency一致性、Isolation隔离性、Durability持久性),因此会产生一些例如表连接等操作,这样会大大降低系统的性能。NoSQL的概念提出于20世纪80年代,当时是关系型数据库的天下,并没有现实的使用需求和应用场景,更多的是为了跟关系型数据库的概念相区别。但是,进入21世纪之后,随着国内互联网产业的高速发展和一批以百度、腾讯、阿里巴巴为代表的互联网巨头企业的诞生,带动了一大批创新行企业并改变了人们的生活方式,互联网已成为不可或缺的一部分。这样,网民不仅是信息消费者,也成为信息创建者,随着数据规模扩大和大批非结构化数据的产生,NoSQL数据库有了特定需求场景。
近年来,NoSQL数据库得到快速发展,具有代表性的就是MongoDB。目前国内对于MongoDB的研究还比较少。张路路研究了基于MongoDB的大数据存储方法,对典型的内存优化技术和布式存储技等大数据存储技术进行研究分析[1]。吴德宝对关系与非关系数据库进行了比较与分析,并对它们的主要典型代表Microsoft SQL Server和Mongo DB进行实验测试,对它们的性能做定量的对比和分析[2]。仝义明、黄蔚、李戴维等人设计并实现了一个基于MongoDB的多源信息集成系统,通过数据集成将存放在不同地点的数据进行数据采集与转化,利用MongoDB集群分布式存储海量数据并提供统一检索,实现了数据的共享[3]。
目前而言,国内研究主要在存储和基于MongoDB设计应用系统以及与传统关系数据库进行对比研究。本文的侧重点有所不同,主要研究利用MongoDB实现数据的高可用性和数据查询的高性能。
2 MongoDB简介
关系型数据库建立在关系模型的基础上,以数据表为单位进行存储,擅长结构化数据的存储、查询、删除、连接、交集、并集、差集等操作,仍是各个领域主要在用的数据库类型,在此不做赘述。
NoSQL(Not Only SQL)是非关系型数据存储的广义定义,得到广泛认同。在目前主要的NoSQL数据库中,有MongoDB、HBase、HyperTable、Cassandra等,而其中MongoDB是功能最丰富,最像关系数据库的。
MongoDB是一款强大、灵活,且易于扩展的通用型数据库[4]。相比关系型数据库,MongoDB是一个面向文档(document-oriented)的数据库,它有很多特点和优势,主要体现在以下几个方面:
1) 去除了关系型数据库的关系特征,面向集合存储,使得数据十分易于扩展;
2) 具有很好的读写性能,在海量数据下,性能表现同样非常优秀,这主要因为其结构简单,不受关系型数据库中表间关系的束缚;
3) 不需要预先创建数据字段,在集合中可以随时存入自定义的数据格式,可以轻而易举地增加或者删除字段;
4) 实现高可用架构的同时,不会对性能产生较大影响;
基于以上特点,本文选择MongoDB作为研究对象和候选工具,以解决处理海量数据时遇到的性能瓶颈问题。
3 高可用性研究
3.1 分片与副本集
我们知道,单台服务器的资源存储和计算能力都是有限的,当数据量和计算量达到一定程度时,进行垂直扩展会产生高昂的成本,这时就需要使用分布式存储进行横向扩展。
MongoDB实现的分布式技术,主要在于数据的分片(Shard)以及副本集,分片是集群中负责某一子集的一台或多台服务器[5]。简单来说,分片就是将数据集分割存储在不同的服务器上,以此来提高数据容量和读写吞吐量。MongoDB的分片以集合(Collection,集合的概念与关系型数据库中数据表Table类似)作为最小的单位,一个集合中的数据通过片键被分配到不同的分片节点存储。为了提高单个分片的可用性,每个分片需要有多个副本,存储在不同服务节点上,同一分片的多个副本组成一个副本集(Replica Set)。集合、分片和副本集的关系如图1所示。
3.2 高可用集群设计
MongoDB集群的高可用性是通过副本集来实现的,这种数据冗余机制是可以灵活配置的,可以设置每个分片的副本数量。一个副本集中的节点是有主从之分的,与传统的主从集群的不同之处在于它的主节点是不固定的,主节点是由集群推举产生,节点之间通过心跳机制检测活跃度,当主节点宕机或者停止时会自动将其他节点切换为主节点,因此具有很好的故障自动恢复功能。
通常情况下,搭建MongoDB高可用集群需要多台服务器实现,限于实验条件限制,本文使用Docker虚拟化技术模拟服务器完成搭建。在整个集群中,包含以下功能节点:
Mongos:集群的路由节点,用来处理分发客户机发起的数据库请求,它掌握着每个分片的内容记录,会将数据请求转发到对应的分片节点并负责聚合分片服务器的结果集,返回给客户端。这样客户端就可以像使用单机服务器一样进行正常的请求,同时数据库实现了系统负载均衡。 Configdb:集群的配置节点,用来存储整个集群的配置文件,每个数据块的片键范围等,也负责新的分片服务器的加入和认证。
Shards:集群的分片服務器节点,用来存储真实的业务数据,每个分片可以存在多个副本。
根据以上研究,每个分片保存两个副本,使用两个以上配置节点和两个以上路由节点,即可保证整个集群的高可用性。其中任何一个节点宕机,都不会影响数据库的正常服务。集群架构如图2所示。
3.3 可用性实验
首先,需要配置和启动集群中的各个节点。
(1) 配置和启动shard1的脚本如下:
[dbpath=/MongoDB/data/shard1
logpath=/MongoDB/log/shard1.log
pidfilepath=/MongoDB/pid/shard1.pid
directoryperdb=true
logappend=true
replSet=shard1
port=10010
fork=true
shardsvr=true
journal=true ]
同理,启动shard1副本节点和shard2、shard3类似,仅修改部分参数即可。
(2) 配置和启动配置节点的脚本如下
[dbpath=/MongoDB/config/config1
logpath=/MongoDB/log/config1.log
pidfilepath=/MongoDB/pid/config1.pid
directoryperdb=true
logappend=true
port=10040
fork=true
configsvr=true
journal=true ]
同理,启动其他config节点与此类似,仅修改部分参数即可。
(3) 配置和启动路由节点的脚本如下
[configdb=mongo0:10040,mongo1:10040,mongo2:10040
pidfilepath=/MongoDB/pid/route.pid
port=10050
chunkSize=1
logpath=/MongoDB/log/route.log
logappend=true
fork=true ]
同理,启动其他路由节点与此类似,仅修改部分参数即可。需要说明的是,脚本中的mongo0,mongo1和mongo2分别为三个配置节点服务器的IP地址,实验时需要替换为相应的值。
然后,需要登录到路由节点,配置分片和片键。创建vehicle表做分片,车辆的ID为它的VIN码,因此将VIN字段作为片键且唯一。
设置片键命令如下:
db.runCommand( { shardcollection : "testdata.vehicle",key : {vin: 1},unique : true } )
最后,通过路由节点,插入百万条数据。脚本如下
[for( var i=1; i<=1000000; i )
db.vehicle.save({vin : i, volumn1 : “123456”, volumn2 : i*5}); ]
此时可以停掉任意个分片节点服务器,通过db.vehicle.stats()命令,即可查看车辆表的状态。实验表明,只要分片的副本集内,有一个节点服务器正常工作,整个集群的数据服务就不会中断,MongoDB集群完全满足高可用性要求。
4 高性能研究
截至目前,MongoDB社区版的最新版本为3.4.9。在MongoDB版本3.0之前,其性能存在诸多问题,与2.x的版本相比,MongoDB3增加了高性能、可伸缩的数据存储引擎WiredTiger,从而使得MongoDB3性能得到了极大的提升,尤其是写性能和对硬件资源的利用率。MongoDB 2.6及更早的版本,使用MMAP存储引擎,基于内存映射技术;MongoDB3支持两个引擎:支持集合级锁的MMAP和支持压缩和文档级锁的WiredTiger存储引擎。MongoDB3.0在多线程、批量插入场景下较之于MongoDB2.6有大约7倍的增长[6],如图3所示。
4.1 wiredTiger存储引擎
wiredTiger(简称WT)支持的存储方式有三种:行存储、列存储以及LSM。MongoDB在使用时,只是把它作为普通的KV存储引擎来使用,MongoDB的每个集合对应一个WT的table,table里包含多个Key-value pairs,以B树形式存储。同时,WT改进了锁粒度和灵活性,并且提供了snappy(默认)和zlib两种压缩方式。经测试,WT的平均压缩率可达20%以上。
MongoDB 3.0支持用户自定义存储引擎,用户可配置使用mmapv1或者wiredTiger存储引擎[7]。
下面测试插入100w条数据时,WT引擎与mmapv1引擎的性能差异。
使用的Python代码如下:
[import datetime
ISOTIMEFORMAT = ’%Y-%m-%d %X’
from pymongo import MongoClient