加载表格全量数据的方法、装置、计算机设备、存储介质与流程

文档序号:23003608发布日期:2020-11-20 11:52阅读:131来源:国知局
本发明涉及内存数据库缓存
技术领域
:,尤其涉及一种加载表格全量数据的方法、装置、计算机设备、存储介质。
背景技术
::随着互联网技术的快速发展,分布式架构体系的不断完善,用户对软件的响应速度和系统的整体性能提出了更高要求。采用缓存机制解决高并发请求和热点数据存储问题成为大众首选方案。缓存机制利用内存的高速读写特性将数据存储于内存,以提高数据访问速度,降低系统在数据读写部分的性能损耗。redis(remotedictionaryserver)是一款以key-value为数据模型,开源免费且支持高性能并发读写的非关系型内存数据库,可支持字符串、列表、集合、有序集合及哈希表等多种数据存储结构,提供了发布订阅消息通信模式,其强大的数据管理能力被广泛应用于高速缓存、数据发布及订阅等场景。redis哈希类型是字符串类型的字段和值域的映射表,其(键-字段-值)结构与对象的(标识-属性名-属性值)结构相似,可被用来存储结构简单,无复杂关系查询的对象。redis虽有键值分布式存储,数据之间无耦合性,可扩展性强,查找速度快等诸多优点,但存储的数据无结构化,无耦合性,仅为二进制类型也成为了一个十分明显的缺点。开发者使用如c/c++等强类型相关的语言编程时,需要处理整型、浮点、布尔等编程语言相关数据类型和redis数据类型之间的转换,且不利于理解业务数据的相关性和内聚性。同时,redis提供了许多客户端命令,用于在redis服务端执行增删改查等操作,还提供了多种编程语言的客户端api,以便在软件开发过程中完成和redis数据库的交互。hiredis即是一个访问redis数据库的轻量级c语言客户端函数库,基本实现了对redis协议的最小支持。hiredis中包含了同步api和异步api,其原生接口的使用方法较为灵活。异步api需配合第三方异步事件库一起工作。比如,libevent即是一个用c语言编写的开源、轻量级、跨平台,且支持事件驱动和多种i/o多路复用技术的高性能事件通知库,作为底层网络库被广泛应用。综上所述,软件开发人员使用redis前需要花费大量时间和精力学习redis命令及其客户端api的使用方法,时间和人力成本较高,在一定程度上影响了软件研发整体进度,也增加了软件后期维护的复杂度。基于上述原因,本申请人提出了一种表格数据自动同步方法,但是表格同步方法中,表格数据全量加载过程中与redis的交互的过程访问redis的难度较大,不利于使用者使用,而且在某些情况下还会出现因redis内部数据结构变更引起的哈希类型内字段乱序。公开于该
背景技术
:部分的信息仅仅旨在加深对本发明的总体
背景技术
:的理解,而不应当被视为承认或以任何形式暗示该信息构成已为本领域技术人员所公知的现有技术。基于上述原因,本申请人提出了一种加载表格全量数据的方法、装置、计算机设备、存储介质。技术实现要素:为了满足上述要求,本发明的第一个目的在于提供一种加载表格全量数据的方法。本发明的第二个目的在于提供一种加载表格全量数据的装置。本发明的第三个目的在于提供一种计算机设备。本发明的第四个目的在于提供一种非临时性计算机可读存储介质。为了实现上述目的,本发明采用以下技术方案:一方面,本申请实施例提出了一种加载表格全量数据的方法,包括以下步骤:查找redis数据库中的键值,获取表格实例关联的所有键;将所述表格实例关联的所有键保存至容器,获取所述容器中首个键值元素的字段名,将所述字段名设置为表格列名;依次遍历所述容器的每一个键值元素,利用键值元素创建行对象;将所述行对象添加至表格中,获取所述行对象对应的键值元素的字段名及值填充到行对象的单元格内。在一个可能的实施方式中,所述查找redis数据库中的键值的步骤包括,以渐进式遍历的方式实现键值的查找。在一个可能的实施方式中,所述以渐进式遍历的方式实现键值的查找的步骤包括,获取表格名称、游标初值,输入至基于游标的迭代器中。在一个可能的实施方式中,所述利用键值元素创建行对象的步骤包括,获取键值元素中的所有字段以及值,解析出行号并创建行对象。在一个可能的实施方式中,所述解析出行号并创建行对象的步骤包括,使行内单元格名称和表格列单元格名称一致。在一个可能的实施方式中,所述获取所述行对象对应的键值元素的字段名及值填充到行对象的单元格内的步骤之后还包括,返回成功加载的行数。在一个可能的实施方式中,所述获取所述行对象对应的键值元素的字段名及值填充到行对象的单元格内的步骤之后还包括,返回成功加载的列数。在另一方面,本申请实施例还提出了一种加载表格全量数据的装置,包括以下单元:键值查找单元,用于查找redis数据库中的键值,获取表格实例关联的所有键;容器填充单元,用于将所述表格实例关联的所有键保存至容器,获取所述容器中首个键值元素的字段名,将所述字段名设置为表格列名;元素遍历单元,用于依次遍历所述容器的每一个键值元素,利用键值元素创建行对象;数据填充单元,用于将所述行对象添加至表格中,获取所述行对象对应的键值元素的字段名及值填充到行对象的单元格内。在第三方面,本申请实施例还提出了一种计算机设备,包括存储器、处理器及存储在所述存储器上并可在所述处理器上运行的加载表格全量数据的程序,其中,所述加载表格全量数据的程序被所述处理器执行时实现如上述任一项中所述的加载表格全量数据的方法。在第四方面,本申请实施例提出了一种非临时性计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现如上述任一项中所述的加载表格全量数据的方法。相比于现有技术,本发明的有益效果在于:本申请实施例提出的加载表格全量数据的方法,封装了表格数据全量加载过程中与redis的交互,包括检索键值,创建表格列名,存储行数据,降低了访问redis的难度;通过单元格名称给单元格赋值,避免了因redis内部数据结构变更引起的哈希类型内字段乱序问题。下面结合附图和具体实施例对本发明作进一步描述。附图说明图1是本申请实施例提出的一种加载表格全量数据的方法的具体实施例流程示意图;图2是本申请实施例提出的一种加载表格全量数据的方法的具体运用场景的二维表格的结构框图;图3是图2中表格的单元格类定义的属性和方法示意图;图4是图2中表格的单元格集合类定义的属性和方法示意图;图5是图2中表格的数据行类定义的属性和方法示意图;图6是图2中表格的数据行集合类定义的属性和方法示意图;图7是图2中表格的类定义的属性和方法示意图;图8为本申请实施例提供的加载表格全量数据的装置的示意性框图;图9为本申请实施例提供的计算机设备的示意性框图。具体实施方式下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。应当理解,当在本说明书和所附权利要求书中使用时,术语“包括”和“包含”指示所描述特征、整体、步骤、操作、元素和/或组件的存在,但并不排除一个或多个其它特征、整体、步骤、操作、元素、组件和/或其集合的存在或添加。还应当理解,在此本申请说明书中所使用的术语仅仅是出于描述特定实施例的目的而并不意在限制本申请。如在本申请说明书和所附权利要求书中所使用的那样,除非上下文清楚地指明其它情况,否则单数形式的“一”、“一个”及“该”意在包括复数形式。还应当进一步理解,在本申请说明书和所附权利要求书中使用的术语“和/或”是指相关联列出的项中的一个或多个的任何组合以及所有可能组合,并且包括这些组合。参考图1,如图1为本申请实施例提出的一种加载表格全量数据的方法的具体实施例流程示意图,包括以下步骤:步骤s101、查找redis数据库中的键值,获取表格实例关联的所有键;具体地,在本实施例中,采取以渐进式遍历的方式实现键值的查找。例如,通过表格类的redis客户端子对象执行redis的scan命令,以获取表格实例相关的所有键。而scan命令是一个基于游标的迭代器,这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。在本例中,为适配scan语法,需要获取表格名称、游标初值,输入至基于游标的迭代器中。在某些实施例中,假设表格名称为testtbl,则redis内存数据库中testtbl表数据存储在若干个键为testtbl:n的哈希表中,其中n表示数据表中的唯一行号,其含义等同于数据表主键,可以唯一确定一行数据。所以,待执行的scan命令格式为scancursormatchtablename*,游标cursor的初值为0,命令每执行一次,就会返回下一次检索的游标和本次检索到满足匹配模式的若干结果。当返回游标为0时,表示scan命令完成一次完整遍历。步骤s102、将所述表格实例关联的所有键保存至容器,获取所述容器中首个键值元素的字段名,将所述字段名设置为表格列名;在上述步骤中,已经获取到scan命令遍历的键值,假设容器名称为tbl_keys。在本实施例中,若容器非空,则取出首个元素,假设为testtbl:1,执行redis的hkeys命令获取testtbl:1键中所有字段名,即表格testtbl的列名。步骤s103、依次遍历所述容器的每一个键值元素,利用键值元素创建行对象;具体地,一个redis键到行对象的转换操作首先要执行redis的hgetall命令获取键中所有字段及值,从“表名:行号”格式的键值中解析出行号rid,创建一个行号为rid,行内单元格名称和表格列单元格一致的新行对象,并将键中所有字段及值填充到新行对象内的单元格中。其中,redishgetall命令用于返回哈希表中所有的字段和值。在返回值里,紧跟每个字段名(fieldname)之后是字段的值(value),所以返回值的长度是哈希表大小的两倍。本实施例中采用该命令,能够准确实现行号的解析。步骤s104、将所述行对象添加至表格中,获取所述行对象对应的键值元素的字段名及值填充到行对象的单元格内。具体地,因数据已是从redis数据库中加载的,所以此处批量添加操作无需同步redis库,数据加载方法向调用者返回成功加载的行数和列数。通过上述步骤封装了表格数据全量加载过程中与redis的交互,包括检索键值,创建表格列名,存储行数据,降低了访问redis的难度;通过单元格名称给单元格赋值,避免了因redis内部数据结构变更引起的哈希类型内字段乱序问题。下面以一个具体例子说明本发明实施例的具体实现过程:参考图2-7,图2为本申请实施例具体运用场景中二维表格的结构框图,图3为本例中图2表格的单元格类定义的属性和方法,图4为本例中图2表格的单元格集合类定义的属性和方法,图5为本例中图2表格的数据行类定义的属性和方法,图6为本例中图2表格的数据行集合类定义的属性和方法,图7为本例中二维表格类定义的属性和方法。本实施例的目的是基于redis实现一种线程安全的分布式虚拟二维表格,即本申请实施例提出的表格数据自动同步方法的具体应用场景,旨在通过表格对redis数据库进行操作时,使得开发者无需学习redis相关技术,不必关心数据存储细节和底层实现,无须事先为要存储的数据定义字段名称和格式,仅通过表格的行列操作即可访问redis数据库,解决了redis学习和使用成本高,数据无耦合性,不易理解的问题。本申请的实施例中,主要在于解决在上述表格同步方法中,表格数据全量加载过程中与redis的交互的过程访问redis的难度较大,不利于使用者使用,而且在某些情况下还会出现因redis内部数据结构变更引起的哈希类型内字段乱序等问题。本例提供的单元格和行描述二维表格模型,以行和列的形式组织数据,在逻辑上更便于用户理解。表格内部由多个类协同实现整体功能,并对外提供多个接口供用户使用。表格所提供的功能包含创建表格,设计表格字段和索引,批量增加,修改,删除,查询行数据,获取表格行列数,清空表格,注册变更通知回调等。为实现上述表格功能,本例所采用的技术方案包含了表格定义,异步订阅和redis操作三大模块。表格定义模块包含单元格类,单元格集合类,数据行类,数据行集合类和二维表格类定义。异步订阅模块使用hiredis和libevent开源软件以异步方式连接redis服务端,执行subscribe命令订阅以表名命名的通道数据,启动事件线程异步接收订阅响应数据,并及时通知外层用户。redis操作模块包括redis命令类、同步客户端类和响应解析类定义,命令类保存一个redis命令所有参数;响应解析类负责完成redis服务端返回响应到自定义响应结构的转换;同步客户端类使用hiredis以同步方式连接redis服务端,以管道方式执行多条命令,并返回redis响应参数。本例中提供了一种基于redis的数据自动同步表格实现方案,方案用c++语言设计相关类,并封装了一系列可供外部使用的接口。方案还包括redis命令类,redis同步客户端类,redis响应解析类,redis异步订阅类,单元格类,单元格集合类,数据行类,行集合类,表格类等的设计和封装。使用的redis服务端部署为单机模式的主从环境,redis同步客户端类封装了同步方式和redis服务端交互的接口。redis异步订阅类实现异步方式连接redis服务端,以表格名称为通道名,执行redis的subscribe命令订阅表格的变化通知,收到变更消息后通知表格更新数据。创建的表格的每一个行记录可以映射到redis数据库中一个值类型为哈希表的键值对。映射关系解释如下:假设有一个存储个人信息的表格实例dt_person,dt_person实例的表名为person,表中定义了name,age,city三列,并存储了a和b两人的信息,分别为{a,10,西安},{b,18,广州},则这两项信息将通过redis的hmset命令存储在redis数据库的哈希表中。用户a对应的命令为:hmsetperson:1nameaage10city西安。其中,键person:1中的数字1代表该记录在person表中的行号。用户b映射方式和a相同。下面结合附图和具体实施方式对本发明进行详细说明。redis命令类命名为rediscommand,该类将一个redis命令的所有元素保存在动态字符串数组中,包括命令名、键名及其参数。rediscommand使用模板函数技术实现了数值、布尔等非字符串类型转换为字符串类型的功能,通过重载<<和()运算符定义了向redis命令中动态增加参数,并返回新rediscommand实例的接口,通过此接口使用者可以追加方式动态拼接redis命令参数。redis同步客户端类命名为redisha,实现同步方式连接redis服务端,以管道方式在redis服务端上执行一系列redis命令,并解析redis服务端返回的执行结果。redis响应解析类负责将hiredis开源软件返回的响应消息(redisreply)统一转换为自定义的响应结构。自定义响应结构命名为redisreply,包含数据类型,整型值,字符串值及redisreply类型的动态数组。其中,数据类型对应redis协议定义的字符串、数组、整型、空、状态和失败6种返回类型。当响应数据类型为整型时,其值存储在redisreply类的整型值属性中;当响应数据类型为字符串、状态或失败时,其值存储在redisreply类的字符串值属性中;当响应数据类型为数组时,其值存储在redisreply类的动态数组属性中,数组元素redisreply类型的值按上述规则存储。redis异步订阅类命名为redissubscriber,定义的核心数据成员包括libevent事件对象,hiredis异步对象,初始化通知回调和消息通知回调。订阅类初始化过程需完成如下处理:其一,以异步方式连接redis服务端获取hiredis异步对象,设置连接和断开回调,创建libevent事件对象实例,并绑定到异步对象,使得redis异步回调和事件关联;其二,使用者需向订阅类注册初始化通知回调和消息通知回调;其三,启动独立线程开启事件分发处理;其四,以表格名称为通道名,执行redis的subscribe命令订阅表格的变化通知,并注册命令反馈回调。命令反馈回调中区别处理subscribe命令执行结果和订阅消息。收到订阅消息后,调用外层用户注册的变更回调向外层通知变更数据。单元格类命名为datacell,本文档内简写为dc。单元格是二维表格中的基本数据单元,具有单元格名称(字符串类型)、存储值(字符串类型)、变更标志(布尔类型)及所在表(weak_ptr类型)等属性。单元格类提供的接口如表1所示。表1单元格类接口表其中,dci_3是dc类赋值运算符重载接口,该接口根据入参对象重置当前对象内部数据。对于dc类内唯一的指针数据成员,即所属表table,赋值运算仅是重置其值。dci_4是dc类拷贝构造函数,该接口直接调用dci_3接口实现其功能。dci_8是dc类获取单元格值的接口,该接口使用c++语言的函数模板和重载技术实现将单元格内存储的字符串值转换为多种基本数据类型,方便使用者按照实际所需类型获取值。dci_9是dc类设置单元格值的接口,该接口为了支持使用者传入多种c++语言基本数据类型,使用函数模板、重载及字符串流技术将多种不同入参类型统一转换为字符串类型存储。dci_14是单元格类封装的比较函数接口,该函数定义了两个形参,形参1是字符串类型,用于存储关系运算符,如:">"、">="、"<"、"<="、"!="、"=="、"like"、"between"、"in";形参2是字符串数组类型,用于存储关系运算符参数。该方法调用dc类内部重载的关系运算符接口,比较两个单元格内存储值之间的关系。单元格集合类命名为datacellcollection,本文档内简写为dcc。多个单元格组成的一个单元格集合,该集合在逻辑上等同于一行或一列;dcc类内使用顺序和关联容器存储多个单元格地址(shared_ptr<datacell>)。使用智能指针即方便管理动态内存,又可避免内存泄漏。存储于顺序容器可便于利用下标索引单元格;存储于关联容器可为列名和单元格建立映射关系,方便根据列名查找单元格。单元格集合类提供的接口如表2所示。表2单元格集合类接口表其中,dcci_3是dcc类赋值运算符重载接口,dcci_4是dcc类拷贝构造函数接口,这两个接口定义了dc类的复制控制机制,要求类对象复制过程构建完全独立的副本,即类内存储的单元格对象指针必须采用深拷贝方式。dcci_7是dcc类定义的根据单元格名称获取其位置索引的接口。单元格在集合内的位置索引定义为单元格对象在顺序容器中的下标。dcci_8接口检测单元格集合内是否存在指定名称的单元格。dcci_9是dcc类定义的第一种增加操作接口,该接口主要实现在当前对象指定位置插入指定单元格功能。在本实施例中,默认参数标识只在当前行增加。假设使用者通过dcc类对象c调用dcci_9接口,传入一个dc对象地址a和一个插入位置p,dcci_9接口详细处理过程如下:步骤1,判断待插入单元格对象a所属表是否和待插入集合c所属表相同。若相同,则认为a已经在c中,结束处理。步骤2,判断插入位置p是否越界。若越界,则终止处理。步骤3,将c对象关联的表格所属表地址赋值给a对象。获取c对象的shared_ptr智能指针。调用dcci_10接口。步骤4,判断c对象是否关联数据表。若不关联,则终止处理。步骤5,判断c对象关联数据表中是否有行数据。若没有,则终止处理。步骤6,在c对象关联表格所有行的指定位置插入入参单元格对象a。dcci_10是dcc类定义的第二种增加操作接口,该接口主要实现在指定单元格集合对象的指定位置上插入指定单元格功能。接口默认入参单元格、插入位置、入参单元格集合参数均合法,直接调用顺序容器和关联容器的insert方法向入参单元格集合中增加入参单元格对象。dcci_11是dcc类定义的第三种增加操作接口,该接口向集合中追加单元格,即在末尾位置插入。dcci_12是dcc类定义的第四种增加操作接口,向集合中追加指定名称单元格,该接口首先根据入参单元格名称构造一个单元格对象,然后调用dcci_11接口;dcci_13是dcc类定义的第一种删除操作接口,该接口删除集合中指定名称的单元格。例如:使用者通过dcc类对象c调用dcci_13接口,传入一个单元格名称n,dcci_13接口先根据单元格名称n从容器中获取单元格索引,再调用dcci_14接口;dcci_14是dcc类定义的第二种删除操作接口,该接口删除集合中指定索引的单元格。例如:使用者通过dcc类对象c调用dcci_14接口,传入一个单元格位置索引p,dcci_14接口判断入参索引p是否越界,若越界,则终止处理;根据索引p从顺序容器中获取单元格对象指针objptr。在关联容器中查找objptr所指单元格对象名称,若关联容器中未找到相应元素,则只需从顺序容器中删除指定索引元素。若关联容器中找到,则还需从关联容器中删除。若c对象已关联表格,则所关联表格的每一行调用dcci_15接口。dcci_15是dcc类定义的内部删除操作接口,该接口删除指定集合中指定索引的单元格。dcci_16是dcc类定义的第三种删除操作接口,该接口删除当前集合中与入参同名的单元格对象。例如:使用者通过dcc类对象c调用dcci_16接口,传入一个单元格对象obj,dcci_16接口通过单元格对象obj获取单元格名称n,再调用dcci_13接口;dcci_17是dcc类定义的一种拷贝接口,该接口实现将当前集合指定索引开始的单元格拷贝到入参指定集合内。使用者通过dcc类对象c调用dcci_17接口,传入一个开始位置s,一个单元格集合m,dcci_17接口先检查开始位置s在对象c中是否合法性;若不合法,则终止处理。对象m循环调用dcci_9接口依次在末尾追加c集合中单元格对象副本。dcci_18是dcc类提供的根据单元格名称获取单元格对象副本的接口。dcci_19是dcc类提供的根据单元格索引获取单元格对象副本的接口。数据行类命名为datarow,本文档内简写为dr。数据行类描述了单行应该具备的属性和方法。单行应至少具有一个单元格集合和所在表两个属性。行类提供的接口如表3所示。表3数据行类接口表dri_2是dr类赋值运算符重载接口,dri_3是dr类拷贝构造函数接口,这两个接口定义了dr类的复制控制机制,要求类对象复制过程构建完全独立的副本,即类内存储的单元格对象指针必须采用深拷贝方式。dri_5是dr类提供的第一种检索单元格接口,该接口根据单元格名称从行内检索,接口内部直接调用单元格集合类的dcci_18接口。dri_6是dr类提供的第二种检索单元格接口,该接口根据单元格位置从行内检索,接口内部直接调用单元格集合类的dcci_19接口。dri_7是dr类提供的获取行内单元格集合对象的接口。dri_8是dr类获取行号的接口,表格中每个行对象都有表内唯一的行号,即行号等同于表格主键。dri_9是dr类设置行对象标识的接口。dri_10是dr类获取行主键值的接口,行对象的主键是“表名:行号”。dri_11是dr类提供的获取行内所有字段名的接口。dri_12是dr类提供的获取行内所有字段名和值的接口,返回的动态数组中依次存储了f1-v1-f2-v2…。数据行集合类命名为datarowcollection,本文档内简写为drc。drc类描述了多行应该具备的属性和方法。行集类具有多行元素集合和所在表属性;通过双向链表list容器管理多个行对象指针(shared_ptr<dr>),通过二级哈希表管理行集索引表,一级哈希表以列名为键,其值域亦是一个哈希表,二级哈希表以列单元格对象存储值为键,值域是行对象指针。行集合类提供的接口如表4所示。表4数据行集合类接口表行集合类需支持同时设置多个索引字段,为了实现此功能,索引表采用两级哈希表结构,一级哈希表以列名为键,以二级哈希表为值。二级哈希表以列值为键,以列值所属行类实例为值。drci_7是drc类设置索引的接口,行集合类设置索引时,若所属表格行数为0,则只需向一级哈希表中增加列名和空二级哈希表的映射关系。若所述表格行非0,则还需根据表格中每行数据构建二级哈希表。drci_9是drc类提供的一种增加单行的接口。在行集合中增加一个新行时,若表格已设置了索引,需同步更新索引表。具体处理过程为:遍历索引表,从待增加行对象中获取索引列名对应的单元格对象;从单元格对象中获取存储值,查找该存储值在当前列名对应的索引表列值中是否存在;若存在,即索引字段值冲突,添加新行失败。若不存在,向当前列名对应的索引表中插入新列值和新行的对应关系。最后向行集容器中插入新行。drci_10是drc类提供的第一种删除单行的接口。从行集合中删除一个行对象时,若表格已设置了索引,则同样需要更新索引表。具体处理过程为:检查待删除行对象中是否存在索引列;若存在,先从索引表中删除相应列值和行对象映射关系;若不存在,从行集容器中查找指定行对象并删除;drci_11是行集合类提供的根据索引字段名和值删除行接口。drci_12是行集合类提供根据位置检索行的方法。详细处理过程为:检查传入位置索引是否越界,若越界,终止处理;否则,将传入位置索引对应到行对象在行集列表中的相对位置,并返回指定位置上的行对象。drci_13是行集合类提供的根据行标识获取行对象的接口。drci_14是行集合类提供的根据索引字段名称和值获取行对象的接口。drci_15是行集合类提供的更新行数据的接口。drci_16是行集合类提供的查找满足用户指定条件行集的接口。drci_17是行集合类提供的逐行遍历的接口。drci_18是行集合类提供的根据行标识判断行存在性接口。表格类描述了包含行和列的二维表格模型,用于在内存中临时保存一个虚拟表数据,其中行和列均定义为单元格集合。一个二维表格由多行和多列构成。多行通过行集合表示,行集合中包含多个行实例,每个行实例中包含一个单元格集合实例,一个单元格集合实例中包含多个单元格实例,每个单元格实例中存储有效的名称和值。多列通过一个单元格集合表示,列单元格集合中包含多个单元格实例,每个单元格实例中只有名称有效,不存储有意义的值。表格还具有名称、编号、订阅子对象和redis客户端子对象等属性。表格类命名为datatable,本文档内简写为dt,可以被独立创建和使用。表格类提供的接口如表5所示。表5表格类接口表dti_3是dt类提供的创建表格实例的静态方法,该方法内部处理流程如图7右侧所示。使用者向该接口传入redis服务端ip、端口、密码、表格名称、数据库索引和订阅标志等参数。redis服务端ip是部署redis服务的ip地址,端口是redis服务监听端口,密码是redis客户端连接redis服务端时的认证密码。订阅标志表示是否开启订阅表格数据变更功能,值为真时即开启,值为假即关闭。若调用者未向接口传递数据库索引和订阅标志参数,则接口使用默认值,数据库索引默认值为0,即默认表格数据存储于redis服务器的0号数据库;订阅标志默认值为真,即表格实例默认开启订阅数据变更功能。静态方法首先在堆上动态构建一个表格实例,将实例地址存储于智能指针中。表格实例化后需先初始化内部数据,包括行集、列集、redis客户端实例以及订阅实例。初始创建的表格没有架构,即没有设置列名,也没有存储任何行数据。所以,初始化行集需要动态创建一个空drc实例,初始化列名集合需要动态创建一个空dcc实例。为了表格实例可以正常用作使用者和redis数据库之间的桥梁,表格初次创建时需要初始化redis客户端子对象,保证redis客户端对象和redis服务端之间连接建立正常。为了能够及时感知表格数据的变更,表格实例创建后还需初始化订阅子对象,保证订阅子对象和redis服务端之间的异步连接建立正常,同时,成功执行了redis的subscribe命令,且正常启动异步事件处理线程,开始订阅以表格名称命名的通道上的所有消息。表格对象创建成功且完成了所有初始化后,静态方法将表格实例地址返回给使用者。使用者即可获得表格实例地址,即一个shared_ptr<dt>类型的变量。静态方法调用示例如下:shared_ptr<dt>ptr=dt::createdatatable(“192.168.1.1”,6973,“123456”,“testtbl”,true,1);dti_5是dt类设置表格列字段名称的接口。使用者获得表格实例地址后,若需设计一张全新的数据表,则可根据应用场景通过表格实例地址调用该接口设置表格中存储数据的列名。例如设置3个列名分别为f1,f2,f3,则执行调用:vector<string>heads={“f1”,“f2”,“f3”};ptr->sethead(heads);该接口内部遍历传入的列名数组,依次取出每个元素,作为表格列单元格集合对象调用dcc类dcci_12接口的入参,循环增加指定名称的单元格。dti_6是dt类设置表格索引字段的接口,索引是可选设置项,允许表格无索引。使用者可以根据业务需要随时为表格实例创建索引,允许在多个列上创建索引,允许多次设置索引,设置时可以选择重置或追加两种方式。重置方式会清空之前的索引信息,重新根据表数据构建索引表;追加方式则会保留原有索引信息,并根据新设置的索引列补充索引表数据。虽允许一张表设置多个索引列,但只允许在一个列上检索,不支持多列组合检索。表格类设置索引的接口直接调用行集合类设置索引接口。dti_8是dt类设置表格名称接口。dti_9是dt类获取表格名称接口。表格名称区分大小写,默认值为空。dti_10是dt类获取表格编号接口。表格编号通过自增表格类的静态变量获取,单进程内唯一,多进程间可能相同。dti_11是dt类加载表格全量数据接口,即本实施例中提出的加载表格全量数据的方法的另一具体实施例。在本例中,若使用者无需设置新表,仅需从redis数据库中加载已有表数据,则通过表格实例地址调用表格类的dti_11接口,调用示例:autoret=ptr->loaddata();加载表数据方法首先需通过表格类的redis客户端子对象执行redis的scan命令,以获取表格实例相关的所有键。假设表格名称为testtbl,则redis内存数据库中testtbl表数据存储在若干个键为testtbl:n的哈希表中,其中n表示数据表中的唯一行号,其含义等同于数据表主键,可以唯一确定一行数据。所以,待执行的scan命令格式为scancursormatchtablename*,游标cursor的初值为0,命令每执行一次,就会返回下一次检索的游标和本次检索到满足匹配模式的若干结果。当返回游标为0时,表示scan命令完成一次完整遍历。将scan遍历过程中检索出的所有键保存到容器,假设为tbl_keys。若容器非空,则取出首个元素,假设为testtbl:1,执行redis的hkeys命令获取testtbl:1键中所有字段名,即表格testtbl的列名。调用dti_8接口设置表格列名。循环遍历tbl_keys中的每一个键元素,完成键值到行对象的转换操作,最后调用表格类批量增加数据行接口将根据tbl_keys创建的所有行添加到表格中。因数据是从redis数据库中加载的,所以,此处批量添加操作无需同步redis库。数据加载方法向调用者返回成功加载的行数和列数。一个redis键到行对象的转换操作首先要执行redis的hgetall命令获取键中所有字段及值,从“表名:行号”格式的键值中解析出行号rid,创建一个行号为rid,行内单元格名称和表格列单元格一致的新行对象,并将键中所有字段及值填充到新行对象内的单元格中。加载表格全量数据方法获得的技术效果:其一,该方法封装了表格数据全量加载过程中与redis的交互,包括检索键值,创建表格列名,存储行数据,降低了访问redis的难度;其二,该方法通过单元格名称给单元格赋值,避免了因redis内部数据结构变更引起的哈希类型内字段乱序问题。dti_12是dt类获取表格行列数接口。dti_13是dt类清空表格行数据接口。dti_15是dt类获取表格新行号接口。每张表格指定一个全局唯一的行号标识符名称。比如,一个表格实例名称为tablenamea,可以定义该表的行号标识符名称为tablenamea_seq。生成新行号的方法需先传入行号标识符名称,再执行redis的incr命令将key为tablenamea_seq中存储的数值加1。redis机制保证若指定的key在redis数据库中不存在,则指定key的值会先被初始化为0,再执行incr操作,最后将key存储在redis数据库中,并向客户端返回incr执行后的结果。redis的单线程串行处理机制保证了多线程环境下并发生成相同表的新行号时不会出现数据竞争问题。dti_16是dt类创建表格新行对象接口。创建新行对象方法首先在堆上动态创建一个空的新行对象,再将表格对象的列名单元格集合复制到新行对象内,最后设置新行对象关联的数据表为当前表格对象,并将新行对象地址返回给使用者,以便使用者设置行数据。dti_17是dt类批量新增行接口。dti_18是dt类批量删除行接口。dti_19是dt类批量修改行接口。批量操作以事务方式执行,成功即全部成功,失败则全部失败。批量增加、删除或修改行时需先对表数据加锁,然后进行数据备份,备份是为了部分行操作失败时回退表格数据。备份完成后,调用行集合类定义的增加、删除或修改单行接口循环处理传入的多个行。所有行处理成功后,先对表数据解锁,再根据业务需要选择是否同步更新redis数据库。更新redis数据库方法需传入待更新的批量行数据和操作标识,操作标识可设置为增加、删除或修改。该方法首先将每行数据解析到订阅发布数据结构中,然后再根据操作标识将订阅发布结构转换为redis命令。若操作标识为增加或修改,行数据需转换为redis的hmsetkeyf1v1[f2v2…]命令。若操作标识为删除,行数据需转换为redis的hdelkeyf1[f2…]命令。命令中的key为“表名:行号”,fn和vn对应行内每个单元格的名称和值。所有待操作行都按规则转换为redis命令后序列化整个发布订阅结构,向待执行的redis命令集合中追加publishchannelmessage命令,其中,channel即是表名,message即是序列化后的发布订阅数据。以通道方式执行所有redis命令,解析执行结果,根据命令执行结果向调用者返回成功或失败。发布订阅数据结构定义为复合类型,包括操作标识、数据库索引、表格名称、表格编号及变更行数据。行数据中包括行号和行属性集合;行属性数据包括属性名和属性值。发布变更通知的表格实例将发布订阅复合结构序列化为json字符串,订阅变更通知的表格实例将接收的json字符串反序列化为复合结构。dti_20是dt类行数据查询接口。行查询方法允许使用者传入自定义查询函数对象,函数对象内自定义行查询条件,查询函数对象接口定义为bool(dr&)。行查询方法循环遍历表格中的所有行,将每个行作为查询函数对象的入参,执行查询函数,根据返回值判断传入行是否满足查询条件。若满足,则将传入行的副本放入查询结果集合。最后将查询结果集合返回给调用者。dti_21是dt类批量新增列接口。dti_22是dt类批量删除列接口。表格的批量增加或删除列方法内循环调用单元格集合的增加或删除单元格的接口,表格的列名单元格集合中存储了表格地址,增删单元格时若表格中有行数据,则会对每个行对应的单元格集合中增删单元格。dti_23是dt类提供的逐行遍历接口。dti_24是dt类注册行增加通知回调接口。dti_25是dt类注册行删除通知回调接口。dti_26是dt类注册行修改通知回调接口。为了实现表格数据的自动同步功能,表格需要实现数据变更回调方法。表格内订阅子对象的异步事件处理线程接收到变更消息时,会调用表格类注册的数据变更回调。表格类的变更回调能够根据订阅消息体中的操作标识同步更新自身内存数据。使用者可以向表格类选择性地注册表格数据增加、修改或删除变更回调接口,当表格因收到订阅变更消息而更新对象内存数据时会调用使用者注册的回调接口,使用者可以自定义回调接口内对变更数据的处理逻辑。dti_27是dt类注册订阅通知回调接口。表格类是订阅类的上层使用者,必须向订阅类注册订阅通知回调,以便及时接收表格数据变更通知消息。表格类接收到数据变更通知后,先将接收的json字符串反序列化为复合结构,再根据操作标识进行增加、删除或修改处理。增加时,先检查变更数据中的行号在表格实例内存中的存在性,若不存在,则在增加变更数据。否则忽略不处理。修改和删除时,若行号在表格实例内存中存在,则更新或删除相应行数据,否则忽略不处理。被动接收变更消息且触发的表格数据变更皆无需同步到redis数据库,由主动发布变更的表格实例完成redis库数据变更。dti_28是dt类检查表格存在性接口。使用者可以通过表格实例检查redis数据库中任何表格数据的存在性。例如,通过testtbl表格实例检测testcheck表是否已存在,可以执行ptr->tableexist(“testcheck”);若不指定入参表名,则默认检查表格实例自身的存在性,即ptr->tableexist()等同于ptr->tableexist(“testtbl”)。dti_29是dt类根据索引字段名值对检索行接口。使用索引表检索行时只允许在一个列上检索,不支持多列组合检索。图8是本发明实施例提供的一种加载表格全量数据的装置的示意性框图。如图8所示,对应于以上加载表格全量数据的方法,本发明还提供一种加载表格全量数据的装置。该加载表格全量数据的装置包括用于执行上述加载表格全量数据的方法的单元,该装置可以被配置于台式电脑、平板电脑、手提电脑、等终端中。具体地,请参阅图8,该加载表格全量数据的装置200包括:键值查找单元201,用于查找redis数据库中的键值,获取表格实例关联的所有键;容器填充单元202,用于将所述表格实例关联的所有键保存至容器,获取所述容器中首个键值元素的字段名,将所述字段名设置为表格列名;元素遍历单元203,用于依次遍历所述容器的每一个键值元素,利用键值元素创建行对象;数据填充单元204,用于将所述行对象添加至表格中,获取所述行对象对应的键值元素的字段名及值填充到行对象的单元格内。需要说明的是,所属领域的技术人员可以清楚地了解到,上述加载表格全量数据的装置200的各个子单元的具体实现过程,可以参考前述方法实施例中的相应描述,为了描述的方便和简洁,在此不再赘述。上述加载表格全量数据的装置200可以实现为一种计算机程序的形式,该计算机程序可以在如图9所示的计算机设备上运行。参阅图9,该计算机设备300包括通过系统总线301连接的处理器302、存储器和网络接口305,其中,存储器可以包括非易失性存储介质303和内存储器304。该非易失性存储介质303可存储操作系统3031和计算机程序3032。该计算机程序3032包括程序指令,该程序指令被执行时,可使得处理器302执行一种加载表格全量数据的方法。该处理器302用于提供计算和控制能力,以支撑整个计算机设备300的运行。该内存储器304为非易失性存储介质303中的计算机程序3032的运行提供环境,该计算机程序3032被处理器302执行时,可使得处理器302执行一种加载表格全量数据的方法。该网络接口305用于与其它设备进行网络通信。本领域技术人员可以理解,图9中示出的结构,仅仅是与本申请方案相关的部分结构的框图,并不构成对本申请方案所应用于其上的计算机设备300的限定,具体的计算机设备300可以包括比图中所示更多或更少的部件,或者组合某些部件,或者具有不同的部件布置。所述存储介质可以是u盘、移动硬盘、只读存储器(read-onlymemory,rom)、磁碟或者光盘等各种可以存储程序代码的计算机可读存储介质。本领域普通技术人员可以意识到,结合本文中所公开的实施例描述的各示例的单元及算法步骤,能够以电子硬件、计算机软件或者二者的结合来实现,为了清楚地说明硬件和软件的可互换性,在上述说明中已经按照功能一般性地描述了各示例的组成及步骤。这些功能究竟以硬件还是软件方式来执行,取决于技术方案的特定应用和设计约束条件。专业技术人员可以对每个特定的应用来使用不同方法来实现所描述的功能,但是这种实现不应认为超出本发明的范围。在本发明所提供的几个实施例中,应该理解到,所揭露的装置和方法,可以通过其它的方式实现。例如,以上所描述的装置实施例仅仅是示意性的。例如,各个单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式。例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。本发明实施例方法中的步骤可以根据实际需要进行顺序调整、合并和删减。本发明实施例装置中的单元可以根据实际需要进行合并、划分和删减。另外,在本发明各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以是两个或两个以上单元集成在一个单元中。该集成的单元如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分,或者该技术方案的全部或部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,终端,或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。以上所述,仅为本发明的具体实施方式,但本发明的保护范围并不局限于此,任何熟悉本
技术领域
:的技术人员在本发明揭露的技术范围内,可轻易想到各种等效的修改或替换,这些修改或替换都应涵盖在本发明的保护范围之内。因此,本发明的保护范围应以权利要求的保护范围为准。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1