发明内容
针对现有技术的不足,本发明提出一种电力系统海量数据管理系统及其使用方法,本发明方法通过仿真数据分布式存储子系统与海量仿真数据处理子系统的构建来说明。
仿真数据分布式存储子系统将数据分散存储在多台独立的互联设备上。采用可扩展的系统结构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息,不但提高了系统的可靠性、可用性和存取效率,还易于扩展。
仿真数据分布式存储子系统采用集群方式来实现,集群通常包含两类节点:元数据服务器和文件服务器。元数据服务器通常只管理名字空间,权限等元数据信息,而底层的磁盘块分配释放则交由各个文件服务器单独管理。文件服务器提供给外界的是面向数据对象的访问接口,对象大小远大于磁盘块大小,且可以大小不一。客户端通常只在执行元数据操作(如打开、创建文件)时和元数据服务器交互,数据I/O操作则直接与文件服务器交互。该架构把磁盘块管理,数据I/O处理分散到多个文件服务器,从而提高了系统的可扩展性。
海量仿真数据处理子系统为了能够高效存储处理海量数据,需要根据数据之间的关联进行合理切分。数据切分(Sharding)的基本思想就要把一个数据库切分成多个部分放到不同的数据库(server)上,从而缓解数据存储在单一数据库所带来的性能问题。
数据切分可以是物理上的,对数据通过一系列的切分规则将数据分布到不同的数据库服务器上,通过路由规则路由访问特定的数据库。这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器的负载压力。数据切分也可以是数据库内的,对数据通过一系列的切分规则,将数据分布到一个数据库的不同表中。
本发明的目的是采用下述技术方案实现的:
一种电力系统海量数据管理系统,其改进之处在于,所述系统包括仿真数据分布式存储子系统和海量仿真数据处理子系统;
所述仿真数据分布式存储子系统将数据分散存储在多台独立的互联设备上;
所述仿真数据分布式存储子系统采用集群方式,其包含两类节点:元数据服务器master和文件服务器server;
所述海量仿真数据处理子系统对数据通过切分规则将数据分布到不同的数据库服务器上,通过路由规则路由访问特定的数据库;
所述海量仿真数据处理子系统包括数据访问层,数据管理层和数据存储层。
优选的,所述系统对电力系统海量仿真数据进行结构化与非结构化进行分类处理,通过仿真数据分布式存储子系统存储电力系统仿真计算分析非结构化数据,通过关系型数据库依据细分属性进行水平切分后分库分表存储与处理。
优选的,所述仿真数据分布式存储子系统由一个单一的元数据服务器和多个文件服务器组成,客户端client访问主节点;
在子系统中,每个文件拆成固定大小的块chunk;每一个块都由master根据块创建的时间产生一个64位的chunk handle标志;server在本地文件系统保存这些文件块,并且根据chunk handle和字节区间,通过操作系统文件系统读写这些块数据。
优选的,所述海量仿真数据处理子系统对于数据的切分包括垂直切分和水平切分;
所述垂直切分为把不同格式的数据,存储到不同的数据库;
所述水平切分为把相同的数据格式的数据,存储到不同的数据库。
优选的,所述数据访问层用于接受用户接入,等待用户输入,对输入语句进行输出转换和输入拆分,并保存拆分信息;
所述数据管理层负责调用底层接口,通过传递参数来进行管理;并接受数据访问层提取的输入信息,调用底层接口,获得所需数据;
所述数据存储层用于与操作系统对接,调用底层文件接口对文件进行操作。
本发明基于另一目的提供的一种电力系统海量数据使用方法,其改进之处在于,所述方法包括仿真数据分布式存储子系统数据处理方法和海量仿真数据处理子系统处理方法。
优选的,所述仿真数据分布式存储子系统数据处理方法包括
(1)写入过程;
(1.1)客户端向元数据服务器发送查找命令,检查所要创建文件的父目录下是否已有该文件名目录项,元数据服务器通过查询B+树检查是否有并返回结果;
(1.2)若此文件名不存在,客户端向元数据服务器发送信息在该目录下创建文件,指定文件名以及该文件的副本数,元数据服务器在名字空间中添加该文件名目录项,并向客户端返回该文件对应的文件句柄,该文件句柄代表这个文件;
(1.3)客户端准备向文件的某偏移量写入数据,先算得该偏移量位于第几个server,向元数据服务器发送定位命令创建该偏移量对应的chunk;
(1.4)元数据服务器为该chunk分配chunk号,并优选3个sever服务器来存放这个chunk,元数据服务器向被选中的3个server服务器发送写入信息,被选中的3个server服务器创建该chunk并返回成功;
(1.5)元数据服务器在接收到所有创建成功信息后向客户端返回成功;
(1.6)客户端向3个sever服务器写数据;
(2)读取过程;
(2.1)客户端向元数据服务器发送查找命令获取所要读取文件的文件句柄;
(2.2)向元数据服务器获取文件的布局信息;
(2.3)客户端向元数据服务器发送命令索取所要读取chunk的读租约,若可分配租约,则元数据服务器返回一个租约号;
(2.4)客户端根据位置信息,从中选择一个chunk服务器,向其发送读命令,开始读取据;
(2.5)在读取过程中,客户端还可向另外两个chunk服务器读数据,并发读取提高吞吐量;
(2.6)数据读完后,客户端向元数据服务器发送释放命令,释放租约。
进一步地,
所述写租约为当需要向chunk写入数据时,对应的主chunk服务器查看是否拥有该chunk的写租约,没有或已过期则尝试向元数据服务器获取或更新写租约;该chunk正在被复制到其他chunk服务器或者已经分配写租约或读租约,则返回失败,否则返回成功并且chunk的版本号增一;
读租约为在客户端需要读取某个chunk的数据时,获取这个chunk的读租约,该chunk没有分配写租约而且数据已全部写入磁盘,则返回成功,否则返回失败。
优选的,所述步骤(2.2)中布局信息组成文件的各个chunk;信息的列表,每一项包含偏移量、chunk号、版本号和位置信息,位置信息标注chunk所在server服务器内位置。
优选的,所述海量仿真数据处理子系统处理方法包括
(10.1)系统运行,进行初始化,读入配置文件;
(10.2)依照配置文件中的信息,找到对应位置,加载底层数据文件;
(10.3)如底层文件出错,系统做出相应的判断,不能修正则直接退出,能够修正则继续运行;如文件不存在,创建所需的字典文件和数据文件以及其索引文件;
(10.4)对字典文件进行初始化并写入头部信息和root节点的信息,数据文件初始化文件metainfo信息并写入,索引文件初始化头部信息并写入;
(10.5)系统加载数据访问所需要的表信息文件,判断所需要的信息文件是否可打开,如没有,创建一个空文件,等待用户手动输入,如没有表的信息,而用户对表进行了操作,直接返回错误的提示,提示用户错误,如用户输入了表的信息文件,系统会对表信息文件进行处理,保存相应的数据,标记需要进行转换的属性;
(10.5)系统挂起,继续等待输入信息,对输入信息进行提取,对提取的信息输入到管理对象,进行底层转换,对转换的信息进一步加工,由访问层对SQL语句进行拆解,拆分SQL语言到语句中的属性转到对应的表上进行操作;
(10.6)循环等待输入,如中间有错误,程序会异常终止,并且提示错误;否则等待用户正常输入结束符,然后程序终止。
与现有技术比,本发明的有益效果为:
1、降低用户使用电力系统海量数据存储与处理系统的难度
仿真数据分布式存储子系统对外提供标准的POSIX接口,不需要对使用海量数据存储与处理系统的传统分布式并行计算平台等应用进行调整修改,无缝对接原有电力系统仿真计算分析应用,并给予用户及时的技术支持,降低了应用准入门槛和难度,降低各用户使用电力系统海量数据存储与处理系统的难度。
2、精益化成本控制,降低业务基础设施成本
基于廉价PC机构建,易扩展,配置灵活,所需所用,随时可以方便快捷地扩展存储空间,降低存储系统投资成本、运维成本,并且能充分利用一批已淘汰的低配置服务器,一定程度上延长服务器使用年限,节省大量的硬件投入,极大降低运营和服务硬件成本。
3、有效提升海量仿真数据存储与处理能力
建立了仿真数据分布式存储、分布式数据处理机制,显著提升电力系统仿真计算分析关系数据库的访问性能,提高电力系统仿真计算支持用户并发数量上限,有助于改善在线用户存取数据体验,解决电力系统仿真分析计算因仿真电网不同时间和空间上的特性,在现有电网模型基础上派生出大量附加数据的存储与处理难题。
4、提升资源利用率,带来经济效益和社会效益
电力系统海量数据存储与处理系统可以提升资源利用率,充分利用电网企业大量闲置的廉价PC机构建海量数据存储与处理系统;提高运维水平,让工作人员从繁重的硬件管理中解脱出来,减少人力和硬件投入,降低能源消耗,为企业带来显著的经济效益。电力系统海量数据存储与处理系统,践行资源共享、降本增效、节能减排理念,给电网公司带来良好的社会效益。
具体实施方式
下面结合附图对本发明的具体实施方式作进一步的详细说明。
本发明关键词说明:
电力系统海量数据存储与处理系统:基于电力系统海量数据存储与处理技术,支持海量仿真计算数据高效存储与处理,包括仿真数据分布式存储子系统和海量仿真数据处理子系统。
仿真数据分布式存储子系统:将数据分散存储在多台独立的互联设备上,采用可扩展的系统架构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息。
海量仿真数据处理子系统:对数据通过一系列的切分规则将数据分布到不同的数据库服务器上,通过路由规则路由访问特定的数据库,从而缓解数据存储在单一数据库所带来的性能问题。
关系型数据:关系型数据是以关系数学模型来表示的数据。关系数学模型中以二维表的形式来描述数据。
结构化数据:即行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据。
非结构化数据:包括所有格式的办公文档、文本、图片、XML、HTML、各类报表、图像和音频/视频信息等等。
E格式文件:国家电网公司规定的电网数据交换标准,类似于xml格式。
1.电力系统海量数据存储与处理系统整体架构
根据系统原始需求,以中央服务器系统模式为系统框架进行整体构建。在架构的基础上,根据对海量电力系统仿真数据的存储和处理要求,对系统的可扩展性,容错性等方面进行改善,提高系统对大规模仿真数据的高效分析。根据环境要求,电力系统海量数据存储与处理系统主要基于如下考虑:
(1)系统必须易于扩展。要支持大规模数据处理,首先要保证系统能提供海量数据的存储能力。这就要求系统能扩展到成百上千台机器。其次面对不断增加的数据量,系统只需要通过简单地增加机器的数量即可,用户不需关心数据的组织,系统的负载均衡等问题。另外随着系统的扩展,系统能始终保持非常好的性能。
(3)系统是建立在大量廉价的普通计算机上,因此机器发生故障会很普遍。必须对这些节点计算机持续进行检测,并且在系统的基础上进行:检查,容错,以及从故障中恢复。因此,持续监视,错误检测,容错处理,自动恢复必须集成到这个文件系统的设计中。
(3)支持高级语言查询接口。传统的关系数据库使用SQL(Structured QueryLanguage)语言进行数据处理。SQL语言本身简单且易于理解,相较于使用低级的编程语言,用户更习惯于使用类似SQL的编程语言来表达查询任务。本仿真数据处理支持面向用户的数据库查询语言SQL。
(4)数据处理任务通常由两类读取组成:大的流式读取和小规模的随机读取。在大的流式读取中,每个读操作通常要读取几百KB的数据,每次读取1MB或者以上的数据也是很常见的。对于同一个客户端来说,往往会发起连续的读取操作顺序读取一个文件。小规模的随机读取通常在文件的不同位置,读取几KB数据。对于性能有过特别考虑的应用通常会作批处理并且对他们读取的内容进行排序,这样可以使得他们的读取始终是单向顺序读取,而不需要往回读取数据。
基于以上分析,本系统包括两部分:仿真数据分布式存储子系统和海量仿真数据处理子系统。
2.仿真数据分布式存储子系统
考虑到用户的可操作性,采用中心服务器(master)模式。中心服务器存储仿真数据的元数据信息,不存储仿真数据。用户的数据访问请求由中心服务器定位后,转发到具体的文件服务器处理用户的数据读取请求。因此,中心服务器的负载不会很大,不会成为系统的瓶颈。当数据规模增大时,可以增加多个中心服务器。服务器之间形成级联的方式。中心服务器模式操作简单,利于用户管理。当数据增加时,通过增加服务器节点的数量,体现了系统的可扩展性。
数据存取API。系统提供相应的客户端的API接口,实现数据的导入和读取。文件以分层目录的形式组织,用路径名来标识。支持常用的操作,如创建新文件,删除文件,打开文件,关闭文件,读和写文件。
系统提供快照和记录追加操作。快照以很低的成本创建一个文件或者目录树的拷贝;记录追加操作允许多个客户端同时对一个文件进行数据追加操作。同时保证每个客户端的追加操作都是原子性的。多个客户可以在不需要额外的同步锁定的情况下,同时对一个文件追加数据。
2.1仿真数据分布式存储子系统架构
系统集群由一个单一的master和多个server(文件服务器)组成,主节点会有多个客户端client访问。每一个节点都是一个普通的计算机,运行的是一个用户级别的服务器进程。如图1所示:
在系统中,每一个文件都拆成固定大小的块(chunk)。每一个块都由master根据块创建的时间产生一个全局唯一的以后不会改变的64位的chunk handle标志。Sever在本地文件系统保存这些文件块,并且根据chunk handle和字节区间,通过操作系统文件系统读写这些块数据。处于可靠性的考虑,每一个块都会在不同的server上保存备份。缺省情况下,保存3个备份。不过用户对于不同的文件的命名空间(namespace)区域,可指定不同的复制级别。
(1)元数据服务器(master)
在整个系统中,一个文件系统的所有元数据由单个master来统一管理,大大提高了系统的可操作性,元数据包括的内容有:
目录项信息:系统采用传统的目录结构命名空间,目录树中的所有节点(文件和目录),均由一个全局唯一的文件号来标识,根目录的文件号固定为2,目录项信息指的是目录树中各目录项所包含的各目录项的名称及文件ID;
属性信息:各目录、文件的创建,修改时间,及文件的副本数、大小;
chunk信息:一个文件依次由哪些chunk组成的;
位置信息:chunk的各个副本被保存在那个chunk服务器上;
租约信息:系统次用租约来维持多个客户端情况下数据的一致性,这些租约信息由元数据服务器(master)来统一管理。
master的设计大大简化系统设计,并且也让master能够基于全局的角度来管理chunk的存放和做出复制的决定。不过,应尽量减少master的读和写操作,以避免它成为瓶颈。客户端永远不会通过master来做文件的数据读写。客户端只是问master它应当访问哪个server来获取所需要的数据。客户端在一定时间内cache这个信息,并且在后续的操作中都直接和server进行操作。master负责管理所有的文件系统的元数据。包括namespace,访问控制信息,文件到chunk的映射关系,当前chunk的位置等等信息。master也同样控制系统级别的活动,比如chunk的分配管理,孤点chunk的垃圾回收机制,sever之间的chunk镜像管理。master和这些server之间会有定期的心跳线进行通讯,并且心跳线传递信息和server的运行状态。
所有的元数据都是保存在master的内存里。头两个数据类型同时也是由master本地硬盘的记录所有变化信息的operation log来持久化保存的,这个记录也会在远端机器上保存副本。通过log,在master宕机的时候,可以简单,可靠的恢复master的状态。master并不持久化保存chunk位置信息。相反,他在启动的时候以及server加入集群的时候,向每一个server询问他的chunk信息。
(2)server文件数据服务器
Server端保存数据,chunk的大小是一个设计的关键参数。在系统中,一个文件被分割成多个chunk,每个chunk大小固定为64M,所以通过简单的模运算计算出某个文件偏移量在该文件第几个chunk的多少偏移量上。每一个chunk的实例都是作为在server上的Linux文件格式存放的,并且只有当需要的情况下才会增长。之后分配空间的机制可以通过文件内部分段避免空间浪费。另一个关键是chunk的记录。master并不持久化保存server上保存的chunk的记录。它只是在启动的时候简单的从server取得这些信息。master可以再启动之后一直保持自己的这些信息时最新的,因为它控制所有的chunk的位置,并且使用普通心跳信息监视server的状态。
为了进行数据的有效保存,防止宕机时数据的丢失,一个chunk默认被复制成3份,保存在3个不同的sever服务器中,客户端可以为每个文件指定不同的副本个数。三副本就保证了在两个sever服务器故障情况下,仍能从第三个sever服务器上的副本读出数据,提高了系统的可靠性。
在chunk数据写入时,若某个sever服务器突然故障,会导致相应的副本更新失败,进而影响chunk各个副本的一致性。为了解决这个问题,为每个chunk副本分配一个版本号,副本每更新一次则版本号上升,这样就可以通过比较版本号来发现过期的副本。
连接到各个应用系统的客户端代码包含了文件系统的API,并且会和master和server进行通讯处理,代表应用程序进行读写数据的操作。客户端和master进行元数据的操作,但是所有的数据相关的通讯是直接和server进行的。
客户端或者server都不会cache文件数据。这是因为大部分的应用都是流式访问超大文件或者操作的数据集太大而不能被cache。不涉及cache系统使得客户端以及整个系统大大简化了。Server不需要cache文件数据,因为chunks就像本地文件一样的保存,操作系统的buffer cache已经把常用的数据cache到了内存里。
(3)客户端(Client)
系统的客户端通过master及server服务器交互,完成对文件系统的修改和访问等操作。为了减少与master服务器的交互次数,客户端会缓存元数据的信息。系统的客户端对读取和写入数据进行缓存,这就存在缓存一致性的问题,系统采用读写租约(Lease)解决这个问题,所有的租约由元数据服务器统一管理,每个租约有300秒的时限,过期作废。读写租约的方式入下:
1)写租约:当需要向chunk写入数据时,对应的主chunk服务器首先查看是否拥有该chunk的写租约,如果没有或已过期则尝试向元数据服务器获取或更新写租约,如果该chunk正在被复制到其他chunk服务器或者已经分配写租约或读租约,则返回失败,否则返回成功并且chunk的版本号增一;
2)读租约:在客户端需要读取某个chunk的数据时,它首先尝试去获取这个chunk的读租约,如果该chunk没有分配写租约而且数据已全部写入磁盘,则返回成功,否则返回失败。
3)读写租约保证了一个chunk同时只能由一个客户端写入,而且一个或多个客户端在读取某chunk数据时,该chunk数据不会被修改,这样客户端就能够把读取的数据缓存在本地,因为缓存中的数据与server服务器上保存的数据一定是一致的。
2.2仿真数据分布式存储子系统处理流程
仿真数据分布式存储子系统数据处理流程如下:
(1)写入过程
如图2所示,步骤1,数据节点之间的交互过程,客户端首先向元数据服务器发送查找命令,检查所要创建文件的父目录下是否已有该文件名目录项,元数据服务器通过查询B+树检查是否有并返回结果。
步骤2,若得知此文件名不存在,客户端向元数据服务器发送信息在该目录下创建文件,指定文件名以及该文件的副本数,元数据服务器在名字空间中添加该文件名目录项,并向客户端返回该文件对应的文件句柄,之后的交互中,该文件句柄就代表这个文件。
步骤3,然后客户端准备向文件的某偏移量写入数据,它先算得该偏移量位于第几个server,向元数据服务器发送定位命令创建该偏移量对应的chunk。
步骤4,元数据服务器为该chunk分配chunk号,并优选(根据当时的容量负载情况以及机架位置)3个(若副本为3)sever服务器来存放这个chunk,然后这个3个server服务器发送信息,3个server服务器创建该chunk并返回成功。
步骤5,元数据服务器在接收到所有创建成功信息后向客户端返回成功。
步骤6,客户端向3个sever服务器写数据。
(2)读取过程
客户端读取一个文件数据的过程,如图3所示,步骤1,客户端想元数据服务器发送查找命令获取所要读取文件的文件句柄。
步骤2,向元数据服务器获取文件的布局信息。布局信息的内容是组成该文件的各个chunk。信息的列表,每一项包含了偏移量、chunk号、版本号、位置信息,位置信息说明了这个chunk位于那些server服务器(由IP来表示)内。
步骤3,客户端向元数据服务器发送命令索取所要读取chunk的读租约,若可以分配租约,则元数据服务器返回一个租约号。
步骤4,客户端根据位置信息,从中选择一个chunk服务器,向其发送读命令,开始读取据了。
步骤5,在读取过程中,客户端还可以向另外两个chunk服务器读数据,并发读取提高吞吐量。
步骤6,当数据读完后,客户端向元数据服务器发送释放命令,释放租约。
3.海量仿真数据数据处理子系统
对于数据的切分主要有两种方法,分别是垂直切分和水平切分。垂直切分(VerticalPartition/Sharding):就是把不同格式的数据,存储到不同的数据库。水平切分(HorizontalPartition/Sharding):就是把相同的数据格式的数据,存储到不同的数据库。一般来说,对于海量数据的数据库,如果是因为表多而数据多,这时候适合使用垂直切分,即把关系紧密(比如同一模块)的表切分出来放在一个server上。如果表并不多,但每张表的数据非常多,这时候适合水平切分,如图4所示,即把表的数据按某种规则(比如按ID散列)切分到多个数据库(server)上。当然,现实中更多是这两种情况混杂在一起,这时候需要根据实际情况做出选择,也可能会综合使用以工程为维度进行垂直与以单表为维护进行水平切分,从而将原有数据库切分成类似矩阵一样可以无限扩充的数据库(server)阵列。
通过对电力系统仿真计算分析数据的分析,拟采用水平切分,以减少节点间的数据传递。具体切分原则如下:
(1)结合业务逻辑和表间关系,将当前shard划分成多个更小的shard,通常情况下,这些更小的shard每一个都只包含一个主表(将以该表ID进行散列的表)和多个与其关联或间接关联的次表。这种一个shard一张主表多张次表的状况是水平切分的必然结果。这样切分下来,shard数量就会迅速增多。如果每一个shard代表一个独立的数据库,那么管理和维护数据库将会非常麻烦,而且这些小shard往往只有两三张表,为此而建立一个新库,利用率并不高,因此,在水平切分完成后可再进行一次“反向的Merge”,即:将业务上相近,并且具有相近数据增长速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据库上,在逻辑上它们依然是独立的shard,有各自的主表,并依据各自主表的ID进行散列,不同的只是它们的散列取模(即节点数量)必需是一致的。这样,每个数据库结点上的表格数量就相对平均了。
(2)所有表格均划分到合适的shard之后,所有跨越shard的表间关联都必须打断,在书写sql时,跨shard的join、group by、order by都将被禁止,需要在应用程序层面协调解决这些问题。
针对切分后分布在各数据库节点的数据,系统的处理流程可以分为两部分。一部分是数据导入,将源数据从本地读取到分布式存储系统中保存;一部分是查询执行部分,接收用户提交的查询任务,生成查询计划提交给系统执行并返回执行结果。这个过程也包括查询过程中的数据导入。下面分别对这两个过程进行描述。
系统首先从元数据管理模块中获取与源数据对应的模式信息,然后根据源数据的模式信息生成相应的数据导入任务,对源数据进行预处理,即对源数据按列进行划分。接着按照特定的路径将不同列的数据存放到不同的文件中,在存储的过程中按照特定的文件格式将数据以二进制的格式压缩存储在分布式存储系统中。
系统执行查询任务的流程为:首先对用户提交的查询任务进行词法和语法解析生成中间查询解析结果,查询解析模块一方面将中间的解析结果如查询对应的数据表,以及查询涉及的属性列等信息发送给数据导入模块;一方面继续根据数据集的划分属性和数据库信息对查询解析结果进行优化,生成查询执行计划。其中在生成查询执行计划的过程中,会根据数据导入模块生成的数据导入策略对查询计划进行优化。然后系统将数据导入计划和查询执行计划提交给流式处理模块进行整合优化生成执行计划,接着将执行计划编译成作业集提交给数据查询系统,由数据查询系统协调查询在数据库机器和并行处理框架中执行,最终查询结果保持到分布式存储系统中。
非结构化数据由于其数据结构的不唯一性,使得其不能直接存储于关系型数据库中,基于结构化的实现,和成本的考虑,选择关系数据库MySQL来存储与处理数据。
对于非结构化数据结构化存储系统主要有两大功能,一是实现数据存储,一是实现管理机制。关系数据库中使用二维表来进行数据的存储。为了将非结构化数据同样存储于关系型数据库中,考虑也以二维表的形式存储,另外,非结构化数据又是Key-Value型。在关系数据库中以二维表的形式也可以存储非结构化数据。
表1 Key-Value数据表
如表1,Key-Value数据表,其中列KEY对应Key-Value操作中的Key值,列VALUE对应Key-Value操作中的Value值。Value值作为一个不可解析的BLOB对象存储。Value值包含多种数据类型,可以拆分成多了属性列。因为数据库只对数据的存储作了保障,所以需要KEY/VALUE的解析过程,而作为不可解析的BLOB数据,分解的工作需要交给客户端程序来处理,这样的schema less模式虽然可以保证数据的大量快速操作,但是也相应的增加了程序员的负担,需要在进行查询时,客户端为其语句进行解析,有别于关系型数据直接读取需要的数据对象。对于VALUE值,每一个数据对象可以表示出来,因而用表2中的结构表示VALUE。
表2 VALUE的结构
VALUE_1 |
VALUE_2 |
…… |
VALUE_n-1 |
VALUE_n |
为了在关系数据库里面存储VALUE值,可以有两种解决方案,一种是就沿用前面叙述的BLOB型,将VALUE作为一个大集合存储,而解析则交给客户端程序去实现;第二中模型则是将VALUE进行拆分,具体到拆分成n个小表,而每一个小表表现为KEY/VALUE_var(var为属性编号),这样对于每一行记录都将其进行拆分,对应的属性列插入到对应的表之中,而没有相应的属性的记录就不需要插入,做到能够动态适应,有属性就多建一个小表,按记录属性格式插入到对应小表。
如图5,两列的小表依然是按照行存储到数据库之中,但是因为表的列数固定,而且仅仅只为两列,这样使得读入单个属性列的速度大大加快,由于MySQL是一个完全多线程的数据库,因而对于查询时读取不会产生冗余数据,能够快速读入内存,而且数据库可以为两列表每一列都做一个索引。众所周知,数据库只能对一个表中的某几列作索引,并不能全部都索引到,当查询的属性列没有索引时,查找速度将急剧下降,因而采用这样一种多个表存储的结构能很好的解决数据查找时读入的问题。
对于每一个属性而言,SQL解析都会依照相应的数据格式形式进行处理,其中,String(字符串)类型作为一个整体存储到数据库中之后,无论在查找或者匹配或者复制等其他操作时,都是比整型要消耗更多的CPU资源,而且当有多份数据一样时,字符串所占用的空间都会大大的加长。为了应对这样一个问题,对于系统采用列式存储思想处理属性列的下一步工作是可以将字符串作一步转换,使用Hash函数进行Hash,将数据库中所存储是字符串类型转换成整型,这样对于重复而且相对大型的字符串类型可以使用一份数据存储,而数据库中的字符串转换成了整型,最多也就只占4个字节,如果使用64位Hash,也就8个字节,能够很大程度上节省空间,而且在数据库内部也能做更加快速的操作。
而作了转换之后,需要用外部信息才存储这些转换的信息,包括一个字典,用来存储字符串Hash值和分配的全局唯一ID的映射关系;一个数据文件,存储字符串原始数据;并对数据文件进行索引的B+树文件。
3.1海量仿真数据处理子系统架构
系统结构分为三个层次,包括上层的数据访问层,中层核心的管理层以及底层的数据缓存和数据存储层。海量仿真数据处理子系统的架构如图6所示。
系统按照不同的功能模块划分为三个模块,即是数据访问层、数据管理层和底层数据存储层,本节将依次对每一个模块进行介绍。
(1)数据访问层
由于存储系统对于KEY/VALUE型的数据进行了表拆分,所以在数据访问层需要对记录进行转换,系统保证对用户的透明性,使得用户使用时依然可以沿用之前的MySQL数据库使用方法进行使用,保证每一个表用户可以依照之前的方式进行创建。由于拆分表的工作是有系统自动完成的,当系统存储非关系型数据时,用户仅需要按照表的创建方式,定义每一个属性,系统根据用户定义自动拆分大表成为N个小表,对用户每次输入SQL语句进行自动管理和划分。
数据访问层如图7所示,接受用户接入,等待用户输入,然后对输入语句进行两步工作,一步是进行输出转换,一步是进行输入拆分,并且保存拆分信息。用户输入通常是通用的SQL语句,而拆分的表对外的表现依然是一个大表,这样,在用户输入SQL语句后,通常要对SQL语句进行转换,为了保证转换的成功,系统需要相应的信息,这些信息包括表的创建信息,系统会自动对其中的转换属性进行标记,对其他属性列仅仅进行拆分。当用户输入SQL语句后,SQLManager管理类将对输入语句进行转换,并且保存转换信息,调用下一层的访问接口,传递原始数据,获得转换ID。
(2)数据管理层
数据管理层是系统的中枢,对上承接数据访问层,对下管理底层数据存储。管理层是数据执行具体的操作的事务处理,替换的数据以及查找匹配ID都在这一层进行,底层数据对其不可见,管理层负责调用底层接口,通过传递参数来进行管理。管理层接受上层提取的输入信息,调用底层接口,获得所需数据。由于底层数据都放在文件之中,因而管理层也需要对数据缓存进行托管。管理层主要包括系统初始化,字典管理、数据文件管理与索引的建立,以及内存的管理。
数据管理层如图8所示,首先进行初始化,加载字典对象、索引对象与数据对象以及缓存对象,这些都来自底层数据层。数据信息查询通过参数之间调用文件对象,从字典对象、索引对象和数据对象中分别进行查询、插入和删除更改。字典对象最终是以文件形式存入底层,这就涉及到了字典的管理,本系统的字典文件采用树形结构进行管理,因而节点操作包括分裂合并以及新开辟节点与回收节点都由管理层进行管理,什么时候进行预读,什么时候同步写入文件等等。而数据对象则是用分页的机制进行存储,因此对页面文件也有一部分管理工作,另外还需要生成索引对象。
(3)数据存储层
数据存储层是最底层,与操作系统对接,调用底层文件接口对文件进行操作。无论上层数据怎么样,最终存储到底层都是按照一维的方式按顺序依次存入,因而对底层文件要按块写入,每一块都要有信息进行标记。插入、删除和查找都需要有相应的信息才能进行,因此底层数据组织方式也就至关重要了。
字典文件用于实现键值对的快速查找,内部统一格式化排列,方便寻找文件地址,便于存储和读取键值信息。字典文件为了同一定址,使用固定的结构体按节点存储和读取,每一个节点分配一个节点号,按顺序依次分配。每个节点包含相应的关键字和值,并且按关键字由小到大进行。为了能快速索引,需要对节点进行类型分配,分配唯一的根节点,根节点连接到各个内部节点,内部节点连接到记录键值对的信息节点。查找时,从根节点进入,进行随机查找,按关键字大小找到节点内关键字位置,并查找到下一个节点,直到命中,读出键值信息。这样的查找,跳转的次数越小,相应的花销也就越小,当最多只有2-3跳就能找到结果时,就能实现快速查找。快速查找的实现也就实现了快速的插入和删除,但是为了保证字典的节点的平衡性,由数据管理层对字典的节点进行键值数目的管理,保证每个节点的数目保持在最大数目的一半以上,因而就需要对节点自动进行分裂和合并,合并两个半满的节点,分裂一个满节点为两个半满的节点,实现动态管理。
而数据文件需要存入KEY/VALUE的VALUE值中能够允许转换的的原始字符串信息,而这些信息都是没有固定格式的,不能像字典的文件一样统一管理,因此对数据文件要进行分页,每一页分为固定值。分页大小也有要求,分大了容易浪费,分小了管理繁琐,因而实际测试后选择每一页大小为16KB,每一个页面分配一个页号,按顺序分配。而KEY/VALUE值中VALUE值的原始字符串信息存入地址按页号和页内偏移索引,存入记录索引文件。索引文件由B+树实现,构造字典ID到记录地址的键值映射。
3.2海量仿真数据处理子系统处理流程
流程图9详细描述了系统的工作流程。当系统运行之后,会首先进行初始化,读入配置文件,依照配置文件中的信息,找到对应位置,加载底层数据文件,如果底层文件出错,系统做出相应的判断,不能修正则直接退出,能够修正则继续运行;如果是文件不存在,那么就创建所需的字典文件和数据文件以及其索引文件。对字典文件进行初始化并写入头部信息和root节点的信息,数据文件初始化文件metainfo信息并写入,索引文件初始化头部信息并写入。然后系统会加载数据访问所需要的表信息文件,判断所需要的信息文件是否可以打开,如果没有,创建一个空文件,等待用户手动输入,如果没有表的信息,而用户对表进行了操作,直接返回错误的提示,提示用户错误,如果用户输入了表的信息文件,系统会对表信息文件进行处理,保存相应的数据,标记需要进行转换的属性。
然后系统挂起,继续等待输入信息,然后对输入信息进行提取,对提取的信息输入到管理对象,进行底层转换,然后对转换的信息进一步加工,由访问层对SQL语句进行拆解,拆分SQL语言到语句中的属性转到对应的表上进行操作。然后循环等待输入,如果中间有错误,程序会异常终止,并且提示错误。否则等待用户正常输入结束符,然后程序终止。
最后应当说明的是:以上实施例仅用以说明本发明的技术方案而非对其限制,所属领域的普通技术人员参照上述实施例依然可以对本发明的具体实施方式进行修改或者等同替换,这些未脱离本发明精神和范围的任何修改或者等同替换,均在申请待批的本发明的权利要求保护范围之内。