一种基于SparkSQL的分布式全文检索系统及方法与流程

文档序号:11412234阅读:278来源:国知局
本发明涉及海量数据下的数据分析和信息检索技术,更具体地涉及一种基于sparksql的分布式全文检索系统及方法。属于软件
技术领域
:。
背景技术
::随着云计算、物联网等技术发展以及博客、社交网络,基于位置服务lbs为代表的应用模式的出现(参见文献:孟小峰,慈祥.大数据管理:概念、技术与挑战[j].计算机研究与发展,2013,(01):146-169.),数据的种类和规模正以前所未有的速度增长,大数据中蕴含的宝贵价值成为人们存储和处理大数据的驱动力(参见文献:程学旗,靳小龙,王元卓,郭嘉丰,张铁赢,李国杰.大数据系统和分析技术综述[j].软件学报,2014,(09):1889-1908.),例如,在社交网络方面,facebook、微博、微信等以人为核心的社交网络产生了大量的文本、图片等数据,对这些数据形成的社交网络进行分析,发现人与人之间隐含的关系、存在的社区;在搜索引擎方面,google等大型互联网公司通过对广告相关数据的处理用来改善广告的投放效果以提高点击量;在医疗方面,通过对患者病历数据和生活方式的分析,协助医生进行疾病诊断和医治。数百tb甚至数十至数百pb规模的行业或企业大数据以及数据的复杂性已远远超出了现有传统的计算技术和信息系统的处理能力,因此,寻求有效的大数据处理和分析技术已经成为现实世界的迫切需求。传统的关系型数据库管理技术经过40多年的发展,在扩展性方面遇到了巨大的障碍,无法胜任海量数据的分析任务。以谷歌mapreduce(参见文献:deanj,ghemawats.mapreduce:simplifieddataprocessingonlargeclusters[j].communicationsoftheacm,2008,51(1):107-113.)为代表的非关系型数据的处理和分析技术及其社区开源实现hadoop(参见文献:shvachkok,kuangh,radias,etal.thehadoopdistributedfilesystem[c]//massstoragesystemsandtechnologies(msst),2010ieee26thsymposiumon.ieee,2010:1-10.)以其良好的扩展性、并行性、容错性,成为了大数据处理的标准之一,基于hadoop的数据仓库工具hive(thusooa,sarmajs,jainn,etal.hive:awarehousingsolutionoveramap-reduceframework[j].proceedingsofthevldbendowment,2009,2(2):1626-1629.)提供更高层的sql操作,支持数据的提取、转化和加载(etl),避免了用户编写mapreduce程序带来的复杂性。由于hadoop频繁写磁盘、缺乏作业的规划,迭代处理能力差等缺点,ucberkeleyamplab提出了类mapreduce通用并行处理框架spark(参见文献:zahariam,chowdhurym,dast,etal.resilientdistributeddatasets:afault-tolerantabstractionforin-memoryclustercomputing[c]//proceedingsofthe9thusenixconferenceonnetworkedsystemsdesignandimplementation.usenixassociation,2012:2-2.),有效弥补了hadoop在迭代计算和交互式方面的不足。其中,sparksql(armbrustm,xinrs,lianc,etal.sparksql:relationaldataprocessinginspark[c]//proceedingsofthe2015acmsigmodinternationalconferenceonmanagementofdata.acm,2015:1383-1394.)作为spark软件栈中的一员,在大数据分析、机器学习、深度学习等方面发挥着工具和桥梁作用。sparksql兼容hive,拥有比hive更好的性能,目前已支持tpc-ds基准,是大数据背景下优良的数据仓库解决方案之一。在关系型数据库中,全文检索是衡量数据库易用性和功能完备性的重要指标。全文检索通过将关键词和存储的文档数据进行匹配,找到关联度高的若干文档的信息检索技术。在众多关系型数据库中,如mysql,sqlserver,都已具备全文检索功能。然而,sparksql作为传统数据仓库的替代系统,不支持全文检索的sql语句及其并行化。现有分布式全文检索引擎如solr和elasticsearch虽然提供了hive和spark的连接器,但是仍不支持全文检索sql文法,无法满足边查询边计算的需求,部署的复杂性和学习成本使其难以使用。技术实现要素:本发明技术解决问题:克服现有数据分析工具不支持海量数据下全文检索的问题,提供一种基于sparksql的分布式全文检索系统及方法,增强了sparksql数据分析功能,能够有效满足传统业务迁移以及现有业务对海量数据进行全文检索的需求。本发明技术解决方案:本发明相对于传统关系型数据库具有明显的性能提升,索引存储量更小,能够满足在海量数据下的全文检索交互和存储的需求。在大数据查询分析方面,基于sparksql设计实现了面向关系数据的分布式全文检索系统,系统包括sql翻译层、数据源管理层、并行计算层、分布式存储层四个部分。在sql翻译层中提出了基于sql的全文检索的文法以及全文检索sql语句在sql翻译层各模块间的翻译过程;在数据源管理模块设计了一种全文检索过程的并行化方法;检索优化模块中,设计了两种索引存储模型和相应的查询时原表数据还原策略,其中基于索引指定列存储模型设计了一种用于在查询时还原原表数据、复杂度为o(n)的分区对齐连接算法。sql翻译层定义了全文检索文法,包括索引建立文法和查询文法,通过接收用户输入的全文检索sql语句,翻译转换为对索引数据源的接口调用;该层包括文法解析模块、元数据绑定和校验模块、计划树优化模块和物理计划生成模块;文法解析模块首先对输入的sql语句进行切分,去掉空格形成词序数组;之后根据全文检索文法,提取词序数组中的关键信息,在索引建立过程中,关键信息包括原表名、索引表名,索引列,存储模型,在查询过程中,关键信息包括索引表名、返回结果包含的列名、查询类型、查询条件,这些关键信息分别形成一个语法节点,最终形成一颗语法树;然后对语法树进行遍历,对索引建立语句形成的语法树中原表名节点转换为未关联元数据的数据源节点,索引列节点转换为映射节点,索引表名和存储模型节点转换为索引建立节点,形成逻辑计划树;对查询语句形成的语法树中索引表名节点转换为未关联元数据的数据源节点,返回结果包含的列名节点转换为映射节点,查询类型和查询条件语法树节点转换为查询条件计划树节点,形成逻辑计划树;元数据绑定和校验模块对文法解析模块生成的逻辑计划树中实际类型为表、列、视图的节点与元数据仓库进行关联,校验成功的同时将这些节点替换为关联元数据的数据源节点;计划树优化模块仅对索引查询的计划树进行优化,该计划树优化模块将查询条件计划树节点利用过滤下推技术下推到数据源节点并去掉计划树中的查询条件计划树节点,同时利用列裁剪技术将映射节点包含的映射内容下推到数据源节点并去掉计划树中的映射节点;在索引建立过程中,物理计划生成模块合并数据源节点、映射节点和索引建立节点生成索引建立物理计划节点,在查询过程中,将数据源节点转换为扫描数据源物理计划节点,生成物理计划树;在索引建立过程中,物理计划执行模块将索引建立物理计划节点转化为对索引数据源索引建立接口的调用,调用参数包含了原表名、索引列、存储模型和索引表名,然后索引表的元数据信息中加入原表的名称并存入元数据仓库,在查询过程中,物理计划执行模块将扫描数据源物理计划节点转化为对索引数据源查询接口的调用,调用参数包含了索引表名、查询类型和条件、返回结果包含的列名;数据源管理层,根据sql翻译层对索引数据源的接口调用,转换为索引建立或查询的数据处理逻辑,交给并行计算层执行;数据源管理层包括数据源管理模块和检索优化模块;数据源管理模块管理目前spark支持的所有数据源,根据sql翻译层的索引数据源调用,实例化索引数据源,索引数据源包含全文检索过程的并行化方法即索引建立过程并行化和查询过程并行化;数据源管理模块将实例化的索引数据源传入检索优化模块对索引数据源中的索引建立和查询过程进行优化,检索优化模块针对索引建立过程设计了两种存储模型,包括全量存储模型和索引指定列存储模型,针对查询过程为与存储模型相对应的原表数据还原策略,原表数据还原策略的输出为得分与相对应的原表数据拼接后的结果,其中,基于索引指定列存储模型为一种用于在查询时还原原表数据、复杂度为o(n)的分区对齐连接算法,该算法获取原表数据并与得分数据进行拼接;最终,检索优化模块的输出为优化过的索引建立或查询过程的数据处理逻辑,交给并行计算层;并行计算层,接收数据源管理层的数据处理逻辑,生成作业,并对作业进行规划,分配集群资源,将作业数据处理逻辑分发到每个物理机器上,之后,各物理机器上并行执行作业;分布式存储层接收并行计算层对于文件读写的接口调用,采用分布式读写的方式进行索引的建立和查询,建立的索引和查询的结果都存储在分布式索引层,并返回执行结果。1.一种全文检索的sql文法,包括索引建立文法和查询文法,实现步骤如下:索引建立文法包括需要建立索引的原表名称,由sql中的on关键词指定的需要建立索引的列,存储索引的表名称,设计了strategy、quickway、noquick关键字,索引建立使用的存储模型由strategy后的quickway、noquick关键字指定,quickway为全量存储模型,noquick即索引指定列存储模型;sql翻译层中的文法解析模块根据索引建立文法提取原表名、索引表名,建立索引的列,存储模型信息,转换为语法树中的节点;查询文法包括存储索引的表名称,返回结果包含的列名,查询类型,查询条件,查询类型包括词项查询、模糊查询、段查询、前缀查询、表达式查询,分别由设计的新关键字termquery、fuzzyquery、phrasequery、prefixquery、queryparser指定;查询条件包括查询的列、关键词、编辑距离和返回的结果包含的行数,sql翻译层中的文法解析模块根据查询文法提取索引表名、返回结果包含的列名信息、查询类型、查询条件,转换为语法树中的节点。2.数据源管理模块中,索引数据源包含的一种全文检索过程的并行化方法即索引建立过程并行化和查询过程并行化,实现步骤如下:索引建立过程并行化的实现步骤:(1)将原表数据分片存储在若干个物理节点上,每个节点为一个分区;(2)对于原表每一个分片所在的节点,启动一个索引建立任务,读取分区数据建立索引;(3)将该分区产生的索引写入分布式存储层,成为一个索引分片。查询过程并行化的实现步骤:(1)在每一个索引分片所在的节点,启动一个索引查询任务,读取索引数据并根据查询类型和条件返回查询结果,每个分片的查询结果为一个分区;(2)将查询结果写入分布式存储层;(3)通过全局聚合操作将分布在不同节点上的查询结果根据得分进行聚合,得到全局得分排名前k的行,其中k由查询条件中指定。3.检索优化模块中,针对索引建立过程定义了两种存储模型包括全量存储模型和索引指定列存储模型,针对查询过程定义了与存储模型相应的原表数据还原策略,实现步骤如下:全量存储模型和原表数据还原策略的实现步骤:(1)在索引建立时,从原表按行读入所有列的数据;(2)针对每一行数据,在建立倒排索引表时,只有sql的on关键字指定的索引列才会被分词、建立词典和倒排索引表;(3)对每一行数据,索引中额外存储所有列的数据;(4)在查询时,由于索引中存储原表中所有列的数据,因此,原表数据直接从索引中还原;(5)将得分与还原的原表数据中对应的行进行拼接。索引指定列存储模型和原表数据还原策略的实现步骤:(1)在索引建立时,从原表按行读入所有列的数据;(2)针对每一行数据,在建立倒排索引表时,只有sql的on关键字指定的索引列才会被分词、建立词典和倒排索引表;(3)在查询时,由于索引中未存储原表任何列的数据,因此根据索引表元数据信息中的原表名,从元数据仓库获取原表的分区数据信息;(4)使用用于在查询时还原原表数据、复杂度为o(n)的分区对齐连接算法读取原表的分区数据信息并将得分与原表数据中对应的行进行拼接。4.数据源管理层的检索优化模块中,用于在查询时还原原表数据、复杂度为o(n)的分区对齐连接算法,实现步骤如下:(1)利用弹性分布式数据集rdd(rdd,resilientdistributeddatasets)的分区对齐操作使得原表数据分区与查询结果数据分区对齐;(2)在查询结果的分区内,记录查询结果需要获取的所有原表数据的偏移量和偏移量对应的得分;(3)在原表的分区内通过迭代和记录偏移量的方式找到符合的偏移量,将得分与还原的原表数据对应的行进行拼接;(4)遍历所有映射分区,直到连接操作全部完成。5.一种基于sparksql的分布式全文检索方法,步骤如下:(1)首先对输入的sql语句进行切分,去掉空格形成词序数组;之后根据全文检索文法,提取词序数组中的关键信息,在索引建立过程中,关键信息包括原表名、索引表名,索引列,存储模型,在查询过程中,关键信息包括索引表名、返回结果包含的列名、查询类型、查询条件,这些关键信息分别形成一个语法节点,最终形成一颗语法树;然后对语法树进行遍历,对索引建立语句形成的语法树中原表名节点转换为未关联元数据的数据源节点,索引列节点转换为映射节点,索引表名和存储模型节点转换为索引建立节点,形成逻辑计划树;对查询语句形成的语法树中索引表名节点转换为未关联元数据的数据源节点,返回结果包含的列名节点转换为映射节点,查询类型和查询条件语法树节点转换为查询条件计划树节点,形成逻辑计划树;将逻辑计划树中实际类型为表、列、视图的节点与元数据仓库进行关联,校验成功的同时将这些节点替换为关联元数据的数据源节点;对索引查询的计划树进行优化,将查询条件计划树节点利用过滤下推技术下推到数据源节点并去掉计划树中的查询条件计划树节点,同时利用列裁剪技术将映射节点包含的映射内容下推到数据源节点并去掉计划树中的映射节点;在索引建立过程中,合并数据源节点、映射节点和索引建立节点生成索引建立物理计划节点,在查询过程中,将数据源节点转换为扫描数据源物理计划节点,生成物理计划树;在索引建立过程中,将索引建立物理计划节点转化为对索引数据源索引建立接口的调用,调用参数包含了原表名、索引列、存储模型和索引表名,然后索引表的元数据信息中加入原表的名称并存入元数据仓库,在查询过程中,将扫描数据源物理计划节点转化为对索引数据源查询接口的调用,调用参数包含了索引表名、查询类型和条件、返回结果包含的列名;(2)实例化索引数据源,对索引数据源中的索引建立和查询过程进行优化,在索引建立过程中,根据参数中的存储模型建立索引,在查询过程中,根据索引建立时的存储模型选择相应的原表数据还原策略,将得分与相对应的原表数据拼接,其中,基于索引指定列存储模型使用的是一种用于在查询时还原原表数据、复杂度为o(n)的分区对齐连接算法;最终,将优化过的索引建立或查询过程的数据处理逻辑,交给并行计算层;(3)接收数据处理逻辑,生成作业,并对作业进行规划,分配集群资源,将作业数据处理逻辑分发到每个物理机器上,之后,各物理机器上并行执行作业;(4)采用分布式读写的方式进行索引的建立和查询,建立的索引和查询的结果都存储在分布式索引层,并返回执行结果。与现有技术相比,本发明的优点是:(1)支持spark下sql形式的全文检索及其并行化。设计和实现了全文检索的sql文法,在sparksql原有强大的数据分析功能基础上,提供对海量数据的分布式全文检索操作,有效满足了基于传统数据库的业务迁移以及现有业务中使用全文检索进行数据查找和分析的需求。(2)提出了检索模型在分布式环境下的并行方法并基于spark引擎进行了实现,支持边查询边计算,避免了外部工具带来的复杂性,简化了数据分析的步骤,提供了更有力的工具。(3)良好的检索优化策略以及强大的可扩展性。针对侧重性能优化或存储优化两种场景分别设计了索引存储规则以及原表数据还原策略。(4)实验结果表明,对比传统数据库如mysql,在两种检索优化方案下,该系统索引构建的平均时间缩短为传统数据库的0.6%/0.5%,查询的平均时间缩短为传统数据库的1%/10%,在索引指定列存储模型下,索引存储量减少为传统数据库的55.0%。该系统增强了sparksql数据分析功能,能够有效满足传统业务迁移以及现有业务对海量数据进行全文检索的需求。(5)克服现有数据分析工具不支持海量数据下全文检索的问题,在大数据查询分析方面,基于sparksql设计实现了面向关系数据的分布式全文检索系统,系统包括sql翻译层、数据源管理层、并行计算层、分布式存储层四个部分,在sql翻译层中提出了基于sql的全文检索的文法以及全文检索sql语句在sql翻译层各模块间的翻译过程;在数据源管理模块设计了一种全文检索过程的并行化方法;检索优化模块中,针对索引建立阶段,设计了两种存储模型以及相应的原始表数据还原策略,即全量存储模型和索引指定列存储模型,并且在索引指定列存储模型中设计了一种用于原表数据还原、复杂度为o(n)的分区对齐连接算法,并在sparksql上进行了实现。实验结果表明,对比传统数据库如mysql,在两种检索优化方案下,该系统索引构建的平均时间缩短为传统数据库的0.6%/0.5%,查询的平均时间缩短为传统数据库的1%/10%,在索引指定列存储模型下,索引存储量减少为传统数据库的55.0%。增强了sparksql数据分析功能,能够有效满足传统业务迁移以及现有业务对海量数据进行全文检索的需求。附图说明图1是本发明基于sparksql的分布式全文检索系统的组成框图;图2是本发明sql翻译引擎将全文检索sql语句转换为物理执行计划的过程;图3是本发明中的全文检索过程并行化方法;图4是本发明中的全量存储模型和原表数据还原方法;图5是本发明中的索引指定列存储模型和原表数据还原方法;图6是本发明sparksql与mysql建立索引和查询的执行时间对比实验;图7是本发明sparksql与mysql索引存储量以及原始数据的存储量的对比实验。具体实施方式以下结合具体实施例和附图对本发明作更详细的说明。如图1所示,本发明基于sparksql设计实现了面向关系数据的分布式全文检索系统,系统包括sql翻译层、数据源管理层、并行计算层、分布式存储层四个部分。在sql翻译层中提出了基于sql的全文检索的文法以及全文检索sql语句在sql翻译层各模块间的翻译过程;在数据源管理模块设计了一种全文检索过程的并行化方法;检索优化模块中,针对索引建立阶段,设计了两种存储模型以及相应的原始表数据还原策略,即全量存储模型和索引指定列存储模型,并且在索引指定列存储模型中设计了一种用于原表数据还原、复杂度为o(n)的分区对齐连接算法,并在sparksql上进行了实现。1.全文检索文法和sql转换为数据源接口调用的方法如图2所示为图1中sql翻译层对全文检索文法的详细翻译过程。例如对于索引建立语句:createindexindex_nameontable_name(body)。该语句对表table_name的body列建立索引,索引的存储表名称为index_name。文法解析模块首先将sql解析为具有祖先关系的三个节点即索引建立节点、映射节点以及数据源节点的逻辑计划树,该树表明选取table_name表的body列数据建立索引,并且索引存储为另一张表index_name;在元数据分析和校验模块中,数据源节点与元数据进行关联;在物理计划生成模块中,索引建立逻辑计划节点转换为索引建立物理计划节点;在物理计划执行模块中,调用索引数据源的索引建立接口。对于查询语句:selectscore,bodyfromindex_namewherequeryparser(‘nothisfield’,’body:person’,’3’)。该语句利用queryparser表达式查询方式对索引表进行检索,而在查询关键词中,指定在body列上检索具有person单词的数据,最终返回全局得分top3的结果,结果拥有两列数据,即body列和新添加的score列的数据。文法解析模块首先将sql解析为具有三个节点的逻辑计划树即映射节点、查询条件节点和数据源节点,该树表明对索引index_name利用queryparser进行检索,分区检索结果返回只body列和新添加的score列的数据;在元数据分析和校验模块中,数据源节点与元数据进行关联;在计划树优化模块中,将映射节点和查询条件节点下推至数据源;在物理计划生成模块中,索引查询逻辑计划节点转换为扫描数据源物理计划节点;在物理计划执行模块中,调用索引数据源的查询接口。2.全文检索过程的并行化全文检索过程的并行化如图3所示。例如对于索引建立sql语句:createindexindex_nameontable_name(body),table_name表由三个数据分片组成,对表的每个分片生成一个任务,生成的三个索引分片并行写入分布式存储层。对于基于索引的查询语句:selectscore,bodyfromindex_namewherequeryparser(‘nothisfield’,’body:person’,’3’)。index_name表的每一个索引分片构建一个查询任务,table_name用于在索引指定列存储模型中读取原表信息,每个查询得到的结果通过全局聚合操作得到全局得分topk的结果,结果返回形式与数据库表的形式一致,包含得分以及在select中指定的列。3.检索优化方案索引的处理依赖于开源分词和索引工具lucene,其中,只有分词和索引的列能够通过关键词找到,而存储的列可以直接从索引中获取存储的原始信息。图4、5分别展示了在全量存储模型、索引指定列存储模型下,数据源管理层中索引存储以及查询的结果中原始表数据还原的详细处理过程。如图4所示,当使用全量存储模型建立索引的sql语句:createindexindex_nameontable_name(body)strategyquickway。body为指定索引列,则body列的数据会被分词、建立词典、倒排链表以及存储,而id列只会被存储。当使用sql语句selectscore,bodyfromindex_namewherequeryparser(‘nothisfield’,’body:person’,’3’)查询时,由于索引中存储了所有列即id和body列的原始数据信息,因此,可以直接从索引读取id和body数据,并加入新的得分列,之后,使用列裁剪只保留score和body列的数据。如图5所示,当使用索引指定列存储模型建立索引的sql语句:createindexindex_nameontable_name(body)strategynoquick。body为指定列,则只有body会被分词、建立词典、倒排链表,由于所有的列都不进行存储,检索结果中只包含得分数据,所以id和body列的数据需要从原始表读取,读取的过程采用分区对齐连接算法,加入新的得分列之后,使用列裁剪只保留score和body列的数据,最终的结果包含原始数据的body列和新加入的得分列,最终返回结果的形式与全量存储模型一致。由于在两种存储模型下,得到的结果为一个包含多分区的数据集,各分区内是符合关键词的topk结果,因此,需要进行全局reduce操作,得到只有一个分区的数据集,数据集的总行数为topk。图1中的分布式存储层采用hdfs分布式文件系统,hdfs分布式文件系统作为一个独立的文件系统,不依赖于spark执行环境,文件存储在分布式环境下透明化并且文件具有统一的资源可见性,查询的作业能够使用索引建立作业中建立的索引。基于sparksql的分布式全文检索系统的评测如下:实验使用了10台物理机(一台master,九台slave),每台物理机内存为16g,cpu为intel(r)core(tm)i7-2600cpu@3.40ghz8核心,hadoop版本为2.7.1,spark版本为基于社区最新master分支并加入全文检索模块的分支版本,运行在standalone模式下,集群最大的有效executor数目为36。测试集使用了thewestburylabusenetcorpus,共包含32440001篇文档,针对实验环境,选取了前mi篇文档作为实验数据,由于运算能力有限,mi最大值为3243904,文档数与文本形式的空间占用量对应如下:图6是sparksql与mysql索引建立和查询的执行时间对比实验,实验表明,在全量存储模型和索引指定列存储模型下,sparksql索引构建时间是传统数据库的0.6%/0.5%,查询时间是传统数据库的1%/10%。mysql难以适应海量数据的全文检索;sparksql检索的并行化有效缓解了数据量快速上升带来的性能瓶颈问题;索引指定列存储模型只存储一部分数据,节省了大量的磁盘io操作,相比于全量存储模型,平均执行时间减少了17%。在索引指定列存储模型中,由于获取原表数据需要执行分区对齐连接算法,因此,索引指定列存储模型执行时间比全量存储模型执行时间长。图7是sparksql与mysql索引存储量以及原始数据的存储量的对比,实验表明,索引指定列存储模型的索引存储量是mysql的55.0%,是全量存储模型的36.7%;由于只存储必要的分词和索引信息,不存储原始文档,因此,随着数据量和列数的增加,索引指定列存储模型优势将更加明显。总之,本发明克服现有数据分析工具不支持海量数据下全文检索的问题,在大数据查询分析方面,实验结果表明,对比传统数据库如mysql,在两种检索优化方案下,该系统索引构建的平均时间缩短为传统数据库的0.6%/0.5%,查询的平均时间缩短为传统数据库的1%/10%,在索引指定列存储模型下,索引存储量减少为传统数据库的55.0%。本发明增强了sparksql数据分析功能,能够有效满足传统业务迁移以及现有业务对海量数据进行全文检索的需求。尽管为说明目的公开了本发明的具体实施例和附图,其目的在于帮助理解本发明的内容并据以实施,但是本领域的技术人员可以理解:在不脱离本发明及所附的权利要求的精神和范围内,在其他平台上也可以实现相应的方法与工具。因此,本发明不应局限于实施例和附图所公开的内容。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1