数据处理方法与装置制造方法

文档序号:6487073阅读:121来源:国知局
数据处理方法与装置制造方法
【专利摘要】本申请提供了一种数据处理方法与装置,其中,数据处理方法用于工作线程处理双缓冲区数据,所述工作线程包括单独的上下文;所述工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。通过本申请,能够有效满足系统尤其是分布式系统的预读需求,提高系统的I/O性能。
【专利说明】数据处理方法与装置
【技术领域】
[0001]本申请涉及数据处理【技术领域】,特别是涉及一种数据处理方法与装置。
【背景技术】
[0002]随着多处理器、多核、多线程成为提升计算性能的主要手段,计算机系统设计的关注焦点正在从单个线程的执行性能转移到多个甚至大量线程的并行运行上,开发可以在数量持续增长的并行处理器上高效运行的应用程序就变得非常重要。与此同时,软件并行化也意味着I/o (输入/输出)并行化。在I/o并行化中,预读可以有效地减少磁盘的寻道次数和应用程序的I/o等待时间,是改进磁盘读I/O性能的重要优化手段之一。
[0003]一般情况下,操作系统在内核空间实现对文件的预读功能。主流操作系统都遵循了一个简单有效的原则:把读模式分为随机读和顺序读两大类,并只对顺序读进行预读,预读算法需要能够识别应用程序的访问模式和预测出即将被访问的数据页面。传统的预读算法采用模式匹配的方法,监测应用程序对各个文件的读请求序列,维护一定的历史记录,并将其与访问模式逐一进行特征匹配。如果符合任何一种非随机的访问模式的特征,即可依此特征进行预测和预读。以Linux操作系统为例,其预读流程如图1所示,该预读包括:步骤SlO:判断是否为顺序读,若否,则结束预读;若是,是进行步骤S20 ;步骤S20:计算预读的大小;步骤S30:进行流水线预读,返回步骤S10。
[0004]但是,上述预读方式存在着系统消耗和成本高,异步读取效率低,尤其是对于分布式系统来说,异步读取效率更为低,系统I/o性能差的问题。

【发明内容】

[0005]本申请提供了一种数据处理方法与装置,以解决现有的预读方案无法满足系统的预读需求,尤其是分布式系统的预读需求,无法有效提高系统I/o性能的问题。
[0006]为了解决上述问题,本申请公开了一种数据处理方法,所述方法用于工作线程处理双缓冲区数据,其中,所述工作线程包括单独的上下文;所述工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。
[0007]为了解决上述问题,本申请还公开了一种数据处理装置,所述装置用于工作线程处理双缓冲区数据,其中,所述工作线程包括单独的上下文;所述装置包括监控模块,用于使所述工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。
[0008]与现有技术相比,本申请具有以下优点:
[0009]本申请中,每一个用于处理一个或多个待顺序读的数据块的工作线程,拥有独立的上下文及双缓冲区,并且,通过调用第一接口函数监控其自身双缓冲区异步预读数据状态,无须额外的监控线程。每个工作线程拥有独立的一个或者多个双缓冲区,能够快速及时地并发预读数据;每个工作线程具有独立的上下文,且每个工作线程可以通过调用第一接口函数监控其自身双缓冲区异步预读数据状态,确定本工作线程自身的双缓冲区异步预读数据的情况,无须使用额外的监控线程,避免了多工作线程使用一个监控线程进行监控造成的不必要的上下文切换,以及当监控线程出现问题时导致的整个程序不能正常工作的问题。可见,通过本申请,能够有效满足系统尤其是分布式系统的预读需求,提高系统的I/O性能。
【专利附图】

【附图说明】
[0010]图1是现有技术中的一种Linux操作系统内核预读流程示意图;
[0011]图2是一种异步预读过程的示意图;
[0012]图3是根据本申请实施例二的一种数据处理方法的步骤流程图;
[0013]图4是根据本申请实施例三的一种数据处理方法的步骤流程图;
[0014]图5是图4所示实施例中的一个工作线程进行异步预读的示意图;
[0015]图6是根据本申请实施例四的一种数据处理方法的步骤流程图;
[0016]图7是图6所示实施例中的advise函数的处理流程图;
[0017]图8是图6所示实施例中的get_block函数的处理流程图;
[0018]图9是根据本申请实施例五的一种数据处理方法中的单缓冲区的状态转移示意图;
[0019]图10是根据本申请实施例五的一种数据处理方法中的双缓冲区的状态转移示意图;
[0020]图11是根据本申请实施例六的一种数据处理装置的结构框图。
【具体实施方式】
[0021]为使本申请的上述目的、特征和优点能够更加明显易懂,下面结合附图和【具体实施方式】对本申请作进一步详细的说明。
[0022]以下,为便于理解本申请的数据读取方案,首先对异步预读作以简要介绍。
[0023]异步预读是数据预读中较为常用和有效的手段,其通过异步I/O把所需数据提前加载到内存,以便向应用程序隐藏I/O延迟。图2是一种异步预读过程的示意图,如图2所示,异步预读可以使CPU和磁盘同时工作,从而提高计算机系统的利用率。如果没有预读,那么在加载数据时,磁盘忙碌而CPU等待;在处理数据时,CPU忙碌而磁盘空闲。这种交替的空闲和等待是对系统资源的一种闲置浪费。而通过异步预读,操作系统在后台提前进行1/0,可以消减CPU的等待时间,使之与磁盘并行工作,实现流水线作业。
[0024]本申请的数据读取方案基于上述异步预读方式,以下进行详细说明。
[0025]实施例一
[0026]本实施例的数据处理方法用于工作线程处理双缓冲区数据,其中,工作线程包括单独的上下文;工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。
[0027]工作线程用于处理一个或多个待顺序读的数据块,本实施例中,每个工作线程具有一个单独的上下文,并具有自己的双缓冲区空间。每个工作线程在处理自身的双缓冲区数据时,通过调用第一接口函数监控其自身双缓冲区异步预读数据状态,进而可以根据该异步预读数据状态进行后续的预读数据处理,无须额外的监控线程进行异步预读数据状态监控。
[0028]通过本实施例,每一个用于处理一个或多个待顺序读的数据块的工作线程,拥有独立的上下文及双缓冲区,并且,通过调用第一接口函数监控其自身双缓冲区异步预读数据状态,无须额外的监控线程。每个工作线程拥有独立的一个或者多个双缓冲区,能够快速及时地并发预读数据;每个工作线程具有独立的上下文,且每个工作线程可以通过调用第一接口函数监控其自身双缓冲区异步预读数据状态,确定本工作线程自身的双缓冲区异步预读数据的情况,无须使用额外的监控线程,避免了多工作线程使用一个监控线程进行监控造成的不必要的上下文切换,以及当监控线程出现问题时导致的整个程序不能正常工作的问题。可见,通过本实施例,能够有效满足系统尤其是分布式系统的预读需求,提高系统的I/o性能。
[0029]实施例二
[0030]参照图3,其示出了根据本申请实施例二的一种数据处理方法的步骤流程图。
[0031]本实施例的数据处理方法包括以下步骤:
[0032]步骤S 102:为每个工作线程在内存中分配至少一个双缓冲区。
[0033]其中,每个工作线程用于处理一个或多个待顺序读的数据块,并且,每个工作线程具有一个单独的上下文。
[0034]工作线程是处理数据的线程,以分布式数据库系统为例,每个工作线程会处理一个查询请求,根据查询请求可以知道需要同时读取那些连续的数据块,然后工作线程从外部存储器读取这些数据块。如果一个查询请求需要读取来自多个文件的多个连续数据块,或者从同一个文件中读取多个连续数据块,工作线程会为每个需要读取的连续数据块分配一个双缓冲区来读取所需数据。
[0035]系统启动时往往会启动一个线程池,当有任务需要处理时,会从线程池中获取一个线程作为工作线程,每个工作线程在第一次读取文件时会创建单独的上下文,当然也可以在创建工作线程的同时创建上下文,工作线程根据任务的需求来确定待读取的连续数据块。有几个连续数据块需要同时读取,就可以建立几个双缓冲区,处理完成一个任务以后,工作线程放回线程池,优选地,其中的上下文和双缓冲区的内存不释放,作为空闲双缓冲区,留待在处理下个任务时重用,下次处理任务时,如果需要双缓冲区,先从工作线程的空闲双缓冲区中分配,如果没有空闲双缓冲区,则创建新的双缓冲区。当然,在实际应用中,双缓冲区的数量也有可能与需要同时读取的连续数据块的数量不同,可以由本领域技术人员适当设置,同样可适用本实施例的数据处理方案。
[0036]每个工作线程具有一个单独的上下文,在该工作线程内部对上下文进行处理,有效避免了多工作线程间的上下文切换;为每个工作线程分配双缓冲区,可以使用双缓冲区交替工作,在处理一个缓冲区的数据时使用另一个缓冲区预读数据,实现真正的异步预读。
[0037]步骤S104:每个工作线程直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到本工作线程自身的双缓冲区。
[0038]在预读数据时,每个工作线程直接将外部存储器中的数据预读到用户态的自身双缓冲区中,避免了 pagecache的使用,使得数据直接在外部存储器如磁盘和用户缓冲区之间传送。
[0039]优选地,在预读数据时,工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据,其中,第二接口函数携带有异步预读信息,异步预读信息包括:待顺序读的数据块的信息和待顺序读的数据块所属的数据库文件的句柄;工作线程根据异步预读信息,直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区。
[0040]优选地,工作线程在根据异步预读信息,直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区时,可以根据异步预读信息和工作线程中的双缓冲区的大小,确定异步预读的次数和顺序;再根据确定的异步预读的次数和顺序,调用第三接口函数直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区。
[0041]优选地,异步预读信息还包括:预读方式和/或缓存方式,其中,预读方式用于指示对待顺序读的数据块是正向顺序读还是反向顺序读,缓存方式用于指示是否对预读的数据进行缓存。
[0042]优选地,第三接口函数的输入参数包括本次预读的所述待顺序读的数据块的信息。此外,第三接口函数的输入参数还可以包括:预读方式和/或缓存方式,其中,预读方式用于指示本次对待顺序读的数据块的预读是正向顺序读还是反向顺序读,缓存方式用于指示是否对本次预读的数据进行缓存。
[0043]步骤S106:每个工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态,根据该状态确定异步预读的进度,从其自身的双缓冲区获取数据并进行处理。
[0044]系统使每个工作线程通过第一接口函数监控其自身双缓冲区异步预读数据状态,进而可以根据该状态确定自身的数据异步预读的进度,确定从该工作线程自身的双缓冲区中读取数据进行处理。
[0045]对缓冲区数据的处理可以是常规处理手段,如修改、存储、传输等等,本申请对此不作限制。
[0046]通过本实施例,每一个用于处理一个或多个待顺序读的数据块的工作线程,拥有独立的上下文及双缓冲区,并且,每个工作线程直接从外部存储器异步预读数据,进而根据异步预读进度获取数据进行处理。通过直接从外部存储器异步预读数据,避开了 pagecache的使用;每个工作线程拥有独立的一个或者多个双缓冲区,能够快速及时地并发预读数据;而且,在预读数据量较大时,待预读的数据可以使用双缓冲区异步交替多次读取,每次读取缓冲区大小的数据量;当工作线程处理双缓冲区中的一个缓冲区如当前缓冲区的数据时,异步并行从外部存储器读取数据到双缓冲区中的另一个缓冲区如预读缓冲区中,从而实现工作线程处理数据与从外部存储器读取数据的并行执行,有效避免了数据不断被加入、再被淘汰、再被重新加入的情况,提升了系统I/O性能;此外,每个工作线程具有独立的上下文,且每个工作线程可以根据异步预读的进度确定本工作线程自身的双缓冲区异步预读数据的情况,无须使用监控线程,避免了多工作线程使用一个监控线程进行监控造成的不必要的上下文切换,以及当监控线程出现问题时导致的整个程序不能正常工作的问题。可见,通过本实施例,能够有效满足系统尤其是分布式系统的预读需求,提高系统的I/O性能。
[0047]实施例三
[0048]参照图4,其示出了根据本申请实施例三的一种数据处理方法的步骤流程图。
[0049]本实施例的数据处理方法包括以下步骤:
[0050]步骤S202:根据文件访问命令分配工作线程,并且,根据该文件访问命令确定需要进行顺序读操作,为分配的工作线程确定待顺序读的数据块。[0051]其中,为顺序读操作分配的工作线程可以在系统收到文件访问命令时从线程池中分配,如,根据数据库的查询命令,从线程池中分配工作线程,而在顺序读取时不再分配工作线程,工作线程再根据该查询命令,确定需要访问那些文件,再确定是否需要访问这些文件的连续的数据块。
[0052]本步骤可以采用Linux系统内核通过验证如下两个条件来判定一个读操作是否是顺序读的方式:(I)这是文件被打开后的第一次读,并且读的是文件首部;(2)当前的读请求与前一个读请求在文件内的位置是连续的。当确定了要进行顺序预读后,为该工作线程确定待预读的数据块。
[0053]当然,不限于此,实际使用中,其它根据文件访问命令确定顺序读的方式同样适用,如,访问数据库时,根据查询数据库文件的查询命令分配工作线程,确定对数据库文件的查询是范围查询,则可确定为顺序读,进而根据范围查询所查询的范围,为该工作线程确定待顺序读的数据块,也即,访问数据库时,先分配工作线程,若为范围查询访问,则可确定该查询操作为顺序读操作,进而为该工作线程确定待顺序读的数据块。
[0054]步骤S204:为分配的工作线程在内存中分配至少一个双缓冲区,该工作线程具有一个单独的上下文。
[0055]工作线程既要处理数据,又要读取数据,工作线程根据自己处理的文件访问命令,来决定需要从哪些文件中读取哪些连续数据块,为每个连续数据块的读取都分配一个双缓冲区,工作线程的双缓冲区个数不确定,根据文件访问命令来确定个数。并且,下次处理文件访问命令时可以重用已有的双缓冲区,当工作线程中的双缓冲区个数不足时,再为工作线程创建新的双缓冲区。
[0056]也就是说,通常情况下,每个工作线程在内存中可能会被分配一个缓冲区,但是,当一个工作线程需要对多个待顺序读的数据块进行处理时,则会为该工作线程在内存中分配与多个待顺序读的数据块的数量相等的双缓冲区,也即,系统会首先判断每个工作线程待处理的待顺序读的数据块是否有多个;若是,则为该工作线程在内存中分配与待顺序读的数据块的数量相同的双缓冲区。分配双缓冲区时,首先从工作线程的空闲双缓冲区中分配,如果没有足够的空闲双缓冲区,则为工作线程创建新的双缓冲区,当工作线程处理完任务后,将所有双缓冲区加入工作的线程的空闲双缓冲区列表。
[0057]优选地,每个工作线程的每个双缓冲区采用固定大小,固定大小的双缓冲区实现了固定的预读粒度,采用固定的预读粒度省去了预读窗口快速扩张的过程,实现更简单高效。其中,双缓冲区的大小可以由本领域技术人员根据实际情况适当设置,优选地,每个双缓冲区的大小为IM或2M。使用IM的预读粒度,单块磁盘的利用率理论上能达到60%,而使用2M的预读粒度,单块磁盘的利用率理论上能达到75%以上。当然,不限于固定大小的双缓冲区,在实际使用中,非固定大小的缓冲区同样适用。
[0058]另外,工作线程中的上下文如io_context和双缓冲区都是可以重复利用的,在处理第一个预读请求时初始化。
[0059]步骤S206:工作线程使用Direct IO方式直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到本工作线程自身的双缓冲区。
[0060]每个工作线程直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到本工作线程自身的双缓冲区,是指工作线程绕过操作系统,避开了 pagecache,直接操作IO (输入输出),也就是Direct IO (直接10),Direct IO使得文件数据直接在磁盘和用户缓冲区之间传送,Direct IO在功能上等同于设备的原始10。
[0061]本实施例中,设定每个工作线程的双缓冲区包括当前缓冲区和预读缓冲区。具体到一个工作线程的一个双缓冲区,该工作线程可以交替使用其当前缓冲区和预读缓冲区,直接从外部存储器中异步预读对应的一个或多个待顺序读的数据块的数据,直至异步预读完对应的一个或多个待顺序读的数据块中的所有数据。优选地,工作线程在读取数据时,可以采用双缓冲区的流水线式读取方式,即:当当前缓冲区的数据返回后,如果还有数据需要读取,立即开始异步预读预读缓冲区的数据;接着处理当前缓冲区的数据,处理完成后,将当前缓冲区和预读缓冲区对换;当前缓冲区和预读缓冲区对换以后,如果当前缓冲区数据未完成读取,等待其异步读取完成;当前缓冲区数据完成读取后,如果还有数据需要读取,立即再次开始预读预读缓冲区的数据,然后处理当前缓冲区的数据,如此循环,直到读取完成所有的数据为止。从这一过程可以看到,只要有数据需要读取的情况下,双缓冲区交替读取,任何时候都有一个缓冲区在异步读取数据,并且读取的数据都是需要的,没有读取任何不必要的数据。
[0062]在上述数据预读过程中,每个工作线程调用第一接口函数独立监控本工作线程自身的双缓冲区异步预读数据的状态。优选地,每个工作线程在需要处理数据时,可以调用用于异步预读状态检查的接口函数即第一接口函数,通过该接口函数监控本工作线程自身的双缓冲区异步预读数据的状态;进而根据异步预读数据的状态确定待处理的数据,并从自身的双缓冲区获取确定的数据进行处理。
[0063]本实施例中,设定缓冲区的状态包括空闲状态、等待状态和准备状态。对于双缓冲区中的当前缓冲区来说,当前缓冲区的状态包括空闲状态、等待状态和准备状态,当前缓冲区的空闲状态用于指示当前缓冲区当前空闲,当前缓冲区的等待状态用于指示等待异步读取数据到当前缓冲区,当前缓冲区的准备状态用于指示当前缓冲区异步读取数据完成;对于双缓冲区中的预读缓冲区来说,预读缓冲区的状态也包括空闲状态、等待状态和准备状态,预读缓冲区的空闲状态用于指示预读缓冲区当前空闲,预读缓冲区的等待状态用于指示等待异步读取数据到预读缓冲区,预读缓冲区的准备状态用于指示预读缓冲区异步读取数据完成。
[0064]步骤S208:工作线程根据其自身的双缓冲区的异步预读数据的状态,从其自身的双缓冲区中获取数据并进行处理。
[0065]具体地,包括:工作线程确定本工作线程的当前缓冲区或预读缓冲区的当前状态为准备状态,则从本工作线程自身的当前缓冲区或预读缓冲区中获取数据并进行处理。
[0066]举例说明如下,工作线程主要做处理数据的工作,数据是从外部存储器如磁盘中读取来的,假设某个工作线程只需要顺序读取一个文件中的一个连续数据块的数据,假如数据块大小为10M,每个缓冲区为1M,首先工作线程会将数据读入当前缓冲区,然后开始处理当前缓冲区的数据,同时向操作系统发起一个异步读取接下来的数据到预读缓冲区,工作线程不断处理当前缓冲区的数据,处理完成后,调用类似i0_geteventS等的用于异步预读状态检测的第一接口函数等待预读缓冲区的数据读取完成,然后互换当前缓冲区和预读缓冲区,处理当前缓冲区的数据同时发起异步预读数据到预读缓冲区,直到处理完所需的数据。需要说明的是,工作线程监控双缓冲区的状态可以只是在处理数据过程中,在需要数据而数据又没有准备好的情况下,检查双缓冲区的状态,等待读取完成,通常不会轮询双缓冲区状态,并且工作线程只负责检查自己发起的IO对应的双缓冲区。这种方式使得异步预读数据速度更快,效率更高。当然,采用轮询的方式也是可行的,但异步预读效果将有所下降。
[0067]以下,以基于Linux环境下的Libaio和Direct IO的一个工作线程为具体实例,对本实施例作以说明。
[0068]参照图5,示出了本实施例中的基于Linux环境下的Libaio和Direct IO的一个工作线程进行异步预读的示意图。
[0069]Libaio 是 Linux Native AIO,是 Linux 下原生的异步 IO 接口,只能与 Direct IO一起使用,使用了 Direct 10,就不能使用操作系统的pagecache,所以用户态的cache就是必备品。Libaio 提供了 io_setup、io_submit、io_getevents 和 io_destroy 四个 API(应用程序接口),其中,io_setup用于构建一个异步IO上下文的句柄;io_destroy用于销毁一个异步IO上下文的句柄;io_submit用于提交一个异步IO操作到指定的异步IO上下文句柄中,传入参数为一个struct iocb的结构,其中包括了需要读写的文件句柄、offset、size、buffer和一个void*类型的指针;io_getevents用于阻塞等待指定数量的异步IO完成事件,传入最长的阻塞时间、最少获取的事件数量、最多获取的事件数量,本实施例中用于异步预读状态检查。
[0070]使用Direct IO绕过操作系统的pagecache,直接读取磁盘,预读的内存和文件的缓存管理都有应用程序自主管理,使整个应用程序的内存管理可控。
[0071]本实施例中,每个工作线程都有一个io_context (IO上下文,Libaio的工作空间),每个工作线程调用io_getevents监控自己的io_context ;每个工作线程之间相互独立,不共享任何数据,互不影响;不需要额外的监控线程来监控异步读取状态。
[0072]一方面,当整个进程共用一个io_context时,监控线程需要将从io_context上集中收到的消息分发给多个不同的工作线程,这一个过程涉及到锁竞争和上下文切换,影响效率,而本实例中每个线程都拥有一个io_conteXt,不需要锁保护,收到消息时不需要分发,没有上下文切换。
[0073]另一方面,如果存在额外的监控线程,额外的监控线程需要循环调用io_getevents函数检查异步读取状态,如果异步读取完成,唤醒相应的阻塞的工作线程,然后工作线程处理已经读取的数据,这种方式由于i0_geteventS会周期性地被唤醒,增加了不必要的上下文切换,特别是在高并发的情况下,频繁的上下文切换将影响读取效率;并且,一旦监控线程出问题,将导致整个程序不能正常工作。而本实例使用io_geteVentS函数监控工作线程自身的双缓冲区异步预读数据的状态,不用额外的监控线程来监控异步读取状态,则避免了不必要的上下文切换,也有效避免了监控线程出现问题时导致整个程序不能正常工作的情况。
[0074]本实例的异步读取的方案如图5所示,图5中示出了一个工作线程,该工作线程包括多个双缓冲区,从O到N,N大于或等于I,每个双缓冲区包括当前缓冲区Current Buffer和预读缓冲区Ahead Buffer,当该工作线程需要读取数据时,调用io_Submit函数发送异步读取请求,然后调用i0_geteventS函数等待返回;在工作线程不需要读取数据时,工作线程空闲,也不会有不必要的上下文切换。[0075]通过本实施例,解决了现有的预读方案无法满足系统的预读需求,尤其是分布式系统的预读需求,无法有效提高系统I/O性能的问题,有效满足了系统尤其是分布式系统的预读需求,提高了系统的I/O性能。
[0076]实施例四
[0077]参照图6,其示出了根据本申请实施例四的一种数据处理方法的步骤流程图。
[0078]本实施例以分布式数据库系统为例,对本申请的数据处理方法作以说明。
[0079]在分布式数据库系统中有多个节点,每个节点有一个由数块磁盘组成的磁盘阵列,多个节点进行并行I/o能提升整个分布式数据库的并发数据服务性能。每个节点保存了上千个数据文件,每个数据文件由成千上万个块数据,每个块大约64KB。对分布式数据的访问模式主要分为两类,简单查询(get)和范围查询(scan),简单查询需要随机读取多个块数据,范围查询需要顺序读取数个块数据,甚至是遍历整个节点所有磁盘的数据文件,范围查询还包括反向范围查询。在进行范围查询时需要顺序读取同一个数据文件的不同部分或者顺序读取多个数据文件,可能有多个随机读取和多个并行顺序读取同时作用于同一个数据文件。为了防止频繁打开/关闭数据文件,分布式数据库节点往往会同时打开上千个数据文件,并缓存文件句柄,每个文件可能会存储数个顺序预读流,操作系统跟踪如此多个文件的预读流状态,将消耗很多内存资源。为此,本实施例提供了一种数据读取方法,为解决该问题提供了 一种可行方案。
[0080]本实施例的双缓冲异步按需预读机基于Libaio和Direct IO的异步读取,仍采用每个工作线程都具有一个io_context,每个工作线程调用io_getevents监控自己的io_context ;每个工作线程之间相互独立,不共享任何数据,互不影响,无需额外的监控线程来监控异步读取状态,当工作线程需要读取数据时,调用io_submit函数发送异步读取请求,然后调用io_getevents函数等待返回的方案。并且,本实施例使用advise接口函数给出明确的顺序预读指示,使用get_block接口函数顺序读取数据。
[0081]本实施例的数据处理方法包括以下步骤:
[0082]步骤S302:设置第二接口函数advise函数和第三接口函数get_bloCk函数。
[0083]Advise函数用于指示顺序读,也即异步预读一个或多个待顺序读的数据块的数据,给予某个顺序流(即待顺序读的数据块)明确的顺序预读指示,advise函数需要传入异步预读信息,也即,advise函数需要传入的参数包括数据文件句柄(本实施例中为待顺序读的数据块所属的数据库文件的句柄),需要读取的连续块数据信息(即待顺序读的数据块的信息),如需要读取的所有block元信息数组(block在文件中的起始地址和长度),可能包含成百上千个block元信息,这些block元信息可能包含多个组,每组的block在物理文件中都是连续的,相当于指定了多个顺序预读流,一个缓冲区可以容纳I个多个block数据。优选地,需要传入的异步预读信息还包括:预读方式和/或缓存方式,其中,预读方式用于指示对待顺序读的数据块是正向顺序读还是反向顺序读,也即,是否需要反向预读;缓存方式用于指示是否对预读的数据进行缓存,如缓存到块缓存中,即,是否需要将块数据加入block cache (应用程序实现的块数据缓存)。根据上述异步预读信息,工作线程可以直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到本工作线程自身的双缓冲区中。
[0084]由于在分布式数据系统中可以明确的知道何种操作为随机读(简单查询时确定为随机读),何种操作为顺序读取(范围查询时确定为顺序读取),所以提供advise函数,让调用者显式调用advise函数明确指示需要顺序预读,advise函数使判断是否进行顺序预读变得很简单。如果工作线程进行范围查询,为每个需要读取的顺序流调用advise函数给予明确预读指示,异步读取时根据该预读指示进行顺序预读。在分布式数据库系统中,每次范围查询时,会计算好需要涉及到的数据文件,每个块数据在数据文件中的起始位置和结束位置,在为每个顺序流调用advise函数时,将需要读取的块数据的信息传入,那么工作线程在读取数据时,采用双缓冲区的流水线式读取方式。当current缓冲区(即当前缓冲区)的数据返回后,如果还有数据需要读取,立即开始异步预读ahead缓冲区(即预读缓冲区)的数据;接着处理current缓冲区的数据,处理完成后,将current缓冲区和ahead缓冲区对换!current缓冲区和ahead缓冲区对换以后,如果current缓冲区数据未完成读取,等待其异步读取完成current缓冲区数据完成读取后,如果还有数据需要读取,立即再次开始预读ahead缓冲区的数据,然后处理current缓冲区的数据,如此循环,直到读取完成所有的数据为止。从这一过程可以看到,只要有数据需要读取的情况下,双缓冲区交替读取,任何时候都有一个缓冲区在异步读取数据,并且读取的数据都是需要的,没有读取任何不必要的数据。
[0085]工作线程将一个顺序流需要读取的块集合一次性传递给advise函数,并显示给予明确预读指示,然后调用get_block函数按顺序取出所需的块数据,get_bloCk读取块数据一定是按顺序的,不能乱序,如果需要反向预读,则get_block读取的块数据顺序一定也是反向的。get_block函数由上层指定需要随机读还是顺序读,如果是随机读,则使用同步方式读取,如果是顺序读,则采用本实施例的双缓冲区按需预读的方式读取,先读取数据到双缓冲区的当前缓冲区,返回应用层所需的数据,并发起异步读取紧接着的数据到另外一个缓冲区中(预读缓冲区),上层应用不断的调用get_block函数获得所需的数据,当当前缓冲区的数据被应用层全部取走后,将预读缓冲区作为当前缓冲区,旧的当前缓冲区作为新的预读缓冲区,再次发起异步预读。这个过程实现了处理数据与读取的数据的分离,在处理数据的同时预读将要处理的数据。
[0086]Get_block函数可以一次读取一个缓冲区的数据给应用层,也可以每次读取一个或多个block的数据给应用层,get_block的参数包括本次预读的数据块的信息,也即本次预读的一个或多个block元信息。比如预读方式是反向预读,一般一个block数据只返回给应用层一次,对每个顺序流,get_block函数参数中的给定block元信息也是反向的并且连续的,多次调用get_block函数给定的block元信息参数也必须保证反向并连续,应用层根据实际数据的需求来决定怎么调用get_block来获取数据,比如依次从每个顺序流中调用get_block获取第一个block,然后再获取每个顺序流的第二个block,直到应用层读取完所有advise参数中包含的所有block数据,或提前终止了数据读取。Get_block函数可以根据advise函数指定的缓存方式对block进行缓存。
[0087]在分布式数据库系统中,无论是简单查询(get),还是范围查询(scan),都是以块为读取的单位,所以需要提供一个get_bloCk函数用于读取一个块数据,简单查询需要随机读取多个块数据,范围查询需要顺序读取数个块数据,甚至是遍历整个节点所有磁盘的数据文件,范围查询还包括反向范围查询,为了满足这些功能,需要get_block函数能够根据输入参数来决定采用随机读取块数据,或是顺序预读,或是反向顺序预读,由于范围查询可能遍历整个节点所有磁盘的数据文件,所以get_block函数需要根据输入参数决定是否把读取的块数据加入到block cache中。也就是说,在根据异步预读待顺序读的数据块的信息,和待顺序读的数据块对应的工作线程中的每个双缓冲区的大小,确定异步预读的次数和顺序后;根据确定的异步预读的次数和顺序,调用第三接口函数,即get_bloCk函数,直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到本工作线程自身的双缓冲区。
[0088]步骤S304:根据查询数据库文件的查询命令分配工作线程,并且,根据该查询命令确定对数据库文件的查询是范围查询。
[0089]步骤S306:根据范围查询所查询的范围,为分配的工作线程确定待顺序读的数据块,该工作线程具有一个单独的上下文。
[0090]其中,该工作线程具有的一个单独的上下文在该工作线程创建时或该工作线程首次读取数据时,使用Libaio为该工作线程创建一个单独的上下文io_context。
[0091]步骤S308:工作线程调用advise函数进行顺序读指示处理。
[0092]其中,advise函数的处理流程如图7所示,包括:
[0093]步骤S3082:判断读取的数据块是否连续,若是,则进行步骤S3084 ;若否,则结束顺序预读流程。
[0094]本步骤检查传入的块集合中的块是否连续并属于同一个文件。
[0095]步骤S3084:为需读取的数据块分配该工作线程私有的双缓冲区。
[0096]确定在工作线程中是否已为该文件顺序流分配对应的双缓冲区,如果对应的双缓冲区不存在,则从工作线程私有的空闲双缓冲区中分配一个,如果工作线程没有空闲双缓冲区,创建一个新的双缓冲区作为该顺序流的双缓冲区。
[0097]步骤S3086:保存需读取的块信息到双缓冲区。
[0098]在分布式数据库系统中,进行范围查询时需要顺序读取同一个数据文件的不同部分或者顺序读取多个文件,也就是说一次范围查询可能涉及到多个顺序流(即待顺序读的数据块),每个工作线程拥有一个或多个双缓冲区,每个双缓冲区保存了一个预读流的状态,工作线程中双缓冲区的个数与该工作线程处理一个范围查询所涉及到的并发顺序流个数相等。当工作线程完成一次范围查询后,线程中的缓冲区将被下次的范围查询所重用。在分布式数据库系统中,可能有多个随机读取和多个并行顺序读取同时作用于同一个数据文件,工作线程调用get_block函数实现随机读取一个块数据时,使用一个额外线程私有的块缓冲区,并使用Direct IO同步读取一个块,而顺序读取使用工作线程私有的一个或多个双缓冲区,采用异步读取的方式读取,所以即使同一个数据文件同时被顺序读取和随机读取,顺序读取的预读都不会受到影响。
[0099]用于顺序读取的缓冲区大小可以配置,默认为1M,也就是说每次读取根据所需读取的数据量,尽量按照IM的粒度从磁盘中读取数据,如果实际需要读取的数据小于1M,一次磁盘IO将所有的数据读取完成。使用IM的读取粒度,单块磁盘的利用率理论上能达到60%,在分布式数据库系统的每个节点往往有数个磁盘组成的磁盘阵列,每个磁盘保证高利用率将使节点的吞吐量大大提高。此外,缓冲区大小也可以配置为2M,单块磁盘的利用率理论上能达到75%以上。
[0100]本步骤中,将需读取的块信息和文件句柄等信息存储于双缓冲区结构的内部状态中。
[0101]步骤S3088:对在block cache中的块做标记。
[0102]如上所述,block cache中的数据可以重用,若本次顺序预读的数据块在blockcache中已存在,贝U需对其进行标记。遍历块集合,将在block cache中的块设置一个存在标志,防止在block cache存在的块在读取文件的过程中被被淘汰。
[0103]步骤S30810:计算每个缓冲区读取的起始位置和大小,通知get_block函数。
[0104]把第一个不在block cache中的块偏移地址作为第一次读取起始偏移地址和并计算需要读取的连续块个数,读取以块为单位。计算好下次预读块的起始偏移地址和块个数。
[0105]步骤S310:工作线程调用get_bloCk函数进行数据读取处理。
[0106]其中,get_block函数的处理流程如图8所示,包括:
[0107]步骤S3102:判断块是否在block cache中,若是,贝U从block cache中读取并返回;若否,则进行步骤S3104。
[0108]如果块在block cache中存在,读取并返回。
[0109]步骤S3104:判断是否为顺序读取,若是,则进行步骤S3106 ;若否,则同步读取该块数据,进行步骤S3108。
[0110]如果为随机读取一个块,使用Direct 10同步读取一个块数据并返回,转入步骤S3108执行;否则,转入步骤S3106执行。
[0111]步骤S3106:使用双缓冲区流水线读取块数据。
[0112]处理顺序读取,获取双缓冲区的状态,根据双缓冲区读取块数据。如果返回超时,直接返回超时错误,否则,更新双缓冲区内部状态,返回读取到的块,转入步骤S3108执行。
[0113]步骤S3108:判断块是否加入block cache中,若否,则结束本次预读流程;若是,则进行步骤S31010。
[0114]步骤S31010:将块数据加入block cache中。
[0115]如果需要将该块拷贝到block cache中,并且该块不在block cache中,则拷贝该块到block cache中。将数据加入block cache中,实现了数据的重复利用。
[0116]可见,通过advise函数和get_bloCk函数,简单有效地实现了顺序读的指示的数据读取。
[0117]本实施例根据分布式数据库系统的需求,实现了双缓冲异步按需预读机制,该机制完美解决了分布式数据库系统节点的预读需求,实现了 I/o的顺序化、异步化和并行化,从而改善了 I/o性能。本实施例中,应用程序对数据的访问模式了如指掌,所以在用户空间实现预读比在内核中实现预读更有针对性,可以根据应用需求量身定做。比如在分布式数据库系统中,简单查询为随机读取,范围查询为顺序读取,这样划分简单直接,只对范围查询进行预读,省去了用模式匹配的方式来识别顺序读取。预读大小不需要估算,每次范围查询所需的块数据对应用程序来说都是事先确定的,预读的数据都是程序所需要的,由于需要读取的总数据量已知,反向预读只需要从后往前读取,每次读取一个缓冲区大小的数据。预读的粒度设置为IM或2M,使用IM的预读粒度,单块磁盘的利用率理论上能达到60%,使用2M的预读粒度,单块磁盘的利用率理论上能达到75%以上,固定的预读粒度省去了预读窗口快速扩张的过程,实现更简单高效。每个工作线程拥有一个或多个双缓冲区,每个双缓冲区保存了一个预读流的状态,工作线程中双缓冲区的个数跟线程处理一个范围查询所涉及到的并发顺序流个数相等,当工作线程完成一次范围查询后,线程中的缓冲区将被下次的范围查询所重用,采用这种方式解决了分布式数据库对同一个数据文件的多个部分或多个文件同时做顺序读取的需求。对于简单查询,不进行预读,也就不会影响到线程的预读缓冲区,从而隔离了随机读对顺序读的影响。从磁盘的读取的数据一般都会加入分布式数据库中的block cache中,但对大范围的查询请求,比如遍历整个节点所有数据文件,对于这些数据都不写入block cache,避免对block cache数据污染。每个双缓冲区包含一个current缓冲区和ahead缓冲区,当工作线程处理current缓冲区的数据时,ahead缓冲区已经开始了异步预读。
[0118]实施例五
[0119]本实施例对实施例四中的数据处理方法进行了进一步地优化,增加状态机管理工作线程中的双缓冲区的状态。
[0120]本实施例中的单缓冲区和双缓冲区的状态转移分别如图9和图10所示。
[0121]参照图9,其示出了本实施例的数据处理方法中的单缓冲区的状态转移示意图。
[0122]如图9所示,单个缓冲区有三种状态:WAIT状态(即等待状态)、READY状态(即准备状态)、和FREE状态(即空闲状态)。其中,WAIT状态表示等待异步读取数据到缓冲区中,读取的数据不一定有效;READY状态表示缓冲区中的数据异步读取完成,但数据不一定有效;FREE状态表示缓冲区空闲,可以读取新的数据。
[0123]从图9所示的状态转移图可以看出,对FREE状态的缓冲区调用io_submit后,缓冲区进入WAIT状态,当异步读取将缓冲区所需的数据读入后,修改缓冲区的状态为READY状态,当处理完缓冲区中的最后一部分数据后,将缓冲区状态设置为FREE,从而该缓冲区可继续用来读取新的数据;如果当前线程读取的文件与处于READY状态的缓冲区所读取的文件相同时,意味着以前的某次读取超时,或是上层应用出错,应用层没有通知停止正在读取的数据的缓冲区,所有缓冲区状态仍然为WAIT,当异步读取完成后,丢弃无效的数据,修改缓冲区的状态为READY状态。READY状态转变成FREE状态有两种可能情况:I)取到了缓冲区中最后一部分数据;2)缓冲区中的数据是无效的。
[0124]由于单个缓冲区具有3种状态,那么双缓冲区会有6种状态组合,分别为FREE+FREE、READY+READY、WAIT+WAIT、WAIT+READY、WAIT+FREE 和 READY+FREE。双缓冲区的状态转移图如图10所示。
[0125]此时,正常的双缓冲区读取流程如下:
[0126]步骤A:开始时,双缓冲区处于状态1,使用current缓冲区读取数据,current缓冲区调用io_submit函数发起一个异步读取请求,接着调用io_getevents函数等待异步读取返回,current缓冲区转变为WAIT状态,转入状态5。
[0127]步骤B:异步读取完成返回,current缓冲区转变为READY状态,转入状态6。
[0128]步骤C:从处于READY状态的current缓冲区按顺序取出块数据返回给应用层,当从current缓冲区读取第一个块数据时,如果ahead缓冲区空闲,并且还有数据需要读取,发起预读,ahead缓冲区调用io_submit函数发起预读请求,这次不用等待异步读取返回,异步预读会在后台继续进行,current缓冲区为READY状态,ahead缓冲区为WAIT状态,转入状态4。
[0129]步骤D:如果预读比上层处理慢,current缓冲区中的块数据都已经全部取走,则current缓冲区状态转变为FREE状态,ahead缓冲区的数据都还没有准备好仍然处于WAIT状态,将原来的ahead缓冲区作为新的current缓冲区,旧的current缓冲区作为新的ahead缓冲区,转入状态5等待。
[0130]步骤E:如果预读比上层处理快,两个缓冲区数据都准备好了,两个缓冲区状态都为READY,转入状态2。
[0131]步骤F:如果处于状态2,并且current缓冲区的块数据已经全部取走,将原来的ahead缓冲区作为新的current缓冲区,旧的current缓冲区作为新的ahead缓冲区,转入状态6。
[0132]步骤G:根据预读快慢和所读数据量多少,会在状态2、4、5、6之间反复切换,直到读取了所有的数据,最后只剩下一个READY的current缓冲区,ahead缓冲区处于FREE状态,双缓冲区处于状态6,如果最后的current缓冲区的数据也完全取走了,转入状态1,等待下次读取开始。
[0133]通过本实施例,使用状态机管理双缓冲区的状态,使工作线程能够根据双缓冲区的状态快速方便地读取数据。
[0134]实施例六
[0135]参照图11,其示出了根据本申请实施例六的一种数据处理装置的结构框图。
[0136]本实施例的数据处理装置用于工作线程处理双缓冲区数据,其中,工作线程包括单独的上下文;数据处理装置包括监控模块402,用于使工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。
[0137]本实施例的数据处理装置还包括:预读模块404,用于在监控模块402使工作线程调用第一接口函数监控其自身缓冲区异步预读数据状态之前,使工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据,其中,第二接口函数携带有异步预读信息,异步预读信息包括:待顺序读的数据块的信息和待顺序读的数据块所属的数据库文件的句柄;根据异步预读信息,直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区。
[0138]优选地,异步预读信息还包括:预读方式和/或缓存方式,其中,预读方式用于指示对待顺序读的数据块是正向顺序读还是反向顺序读,缓存方式用于指示是否对预读的数据进行缓存。
[0139]优选地,预读模块404在根据异步预读信息,直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区时,根据异步预读信息,和工作线程中的双缓冲区的大小,确定异步预读的次数和顺序;根据确定的异步预读的次数和顺序,调用第三接口函数直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区。
[0140]优选地,第三接口函数的输入参数包括本次预读的所述待顺序读的数据块的信
肩、O
[0141]优选地,本实施例的数据处理装置还包括:确定模块406,用于在预读模块使工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据之前,系统根据查询数据库文件的查询命令确定对数据库文件的查询是范围查询;根据范围查询所查询的范围,为工作线程确定待顺序读的数据块。[0142]优选地,本实施例的数据处理装置还包括:分配模块408,用于在确定模块406根据范围查询所查询的范围,为工作线程确定待顺序读的数据块之后,判断确定的待顺序读的数据块是否有多个;若是,则为工作线程分配与待顺序读的数据块的数量相同的双缓冲区。
[0143]优选地,双缓冲区包括当前缓冲区和预读缓冲区;对于工作线程中的每一个双缓冲区,预读模块404在直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区时,使工作线程交替使用其当前缓冲区和预读缓冲区,直接从外部存储器中异步预读对应的一个或多个待顺序读的数据块的数据,直至异步预读完对应的一个或多个待顺序读的数据块中的所有数据。
[0144]优选地,每个双缓冲区的大小固定。
[0145]优选地,每个双缓冲区的大小为IM或2M。
[0146]优选地,预读模块404在使工作线程直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到工作线程自身的双缓冲区时,使工作线程使用DIRECT IO方式直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到自身的双缓冲区。
[0147]优选地,工作线程的单独的上下文通过以下方式创建:在工作线程创建时或工作线程首次读取数据时,数据处理装置使用Libaio为工作线程创建一个单独的上下文io_context ο
[0148]优选地,本实施例的数据处理装置还包括:数据处理模块410,用于在监控模块402使工作线程调用第一接口函数监控其自身缓冲区异步预读数据状态之后,使工作线程根据异步预读数据的状态确定待处理的数据,并从自身的双缓冲区获取确定的所述数据进行处理。
[0149]优选地,当前缓冲区的状态包括空闲状态、等待状态和准备状态,当前缓冲区的空闲状态用于指示当前缓冲区当前空闲,当前缓冲区的等待状态用于指示等待异步读取数据到当前缓冲区,当前缓冲区的准备状态用于指示当前缓冲区异步读取数据完成;预读缓冲区的状态包括空闲状态、等待状态和准备状态,预读缓冲区的空闲状态用于指示预读缓冲区当前空闲,预读缓冲区的等待状态用于指示等待异步读取数据到预读缓冲区,预读缓冲区的准备状态用于指示预读缓冲区异步读取数据完成。
[0150]优选地,数据处理模块410,用于使工作线程确定其当前缓冲区或预读缓冲区的当前状态为准备状态,确定准备状态的当前缓冲区或预读缓冲区的数据为待处理的数据,从工作线程自身的当前缓冲区或所述预读缓冲区中获取数据并进行处理。
[0151]优选地,第一接口函数为Libaio的io_getevents函数,和/或第二接口函数为advise函数,和/或第三接口函数为get_block函数。
[0152]本实施例的数据处理装置用于实现前述多个方法实施例中相应的数据处理方法,并具有相应的方法实施例的有益效果,在此不再赘述。
[0153]本申请提供了一种基于异步预读的数据处理方案,实现了双缓冲区异步按需预读机制,使用Libaio实现异步读取时,没有使用额外的监控线程,每个工作线程独立地监控自己的异步读取状态;每个工作线程根据所需的顺序流数量来分配双缓冲区,提供接口函数让用户明确给予预读指示,实现流水线的按需预读,没有读取不需要的数据;支持反向预读,对同一个文件的多个随机读和顺序读互不影响;增大了磁盘读取粒度,提高磁盘利用率;提供是否将读取的数据加入block cache的选项。通过本申请,减少磁盘的寻道次数和应用程序的I/O等待时间,改进磁盘读I/O性能,提升并行I/O效率。
[0154]本申请中多个实施例以分布式数据库系统为例,但不仅限于分布式数据库系统,在用户态按块读取文件的系统都适用本专利的方案,比如分布式文件系统等,均可参照本申请实施例实现本申请的数据读取方案。
[0155]本说明书中的各个实施例均采用递进的方式描述,每个实施例重点说明的都是与其他实施例的不同之处,各个实施例之间相同相似的部分互相参见即可。对于装置实施例而言,由于其与方法实施例基本相似,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
[0156]本申请是参照根据本申请实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
[0157]这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
[0158]这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
[0159]以上对本申请所提供的一种数据处理方法和装置进行了详细介绍,本文中应用了具体个例对本申请的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本申请的方法及其核心思想;同时,对于本领域的一般技术人员,依据本申请的思想,在【具体实施方式】及应用范围上均会有改变之处,综上所述,本说明书内容不应理解为对本申请的限制。
【权利要求】
1.一种数据处理方法,其特征在于,所述方法用于工作线程处理双缓冲区数据,其中,所述工作线程包括单独的上下文; 所述工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。
2.根据权利要求1所述的方法,其特征在于,在所述工作线程调用第一接口函数监控其自身缓冲区异步预读数据状态的步骤之前,还包括: 所述工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据,其中,所述第二接口函数携带有异步预读信息,所述异步预读信息包括:所述待顺序读的数据块的信息和所述待顺序读的数据块所属的数据库文件的句柄; 根据所述异步预读信息,直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区。
3.根据权利要求2所述的方法,其特征在于,所述异步预读信息还包括:预读方式和/或缓存方式,其中,所述预读方式用于指示对所述待顺序读的数据块是正向顺序读还是反向顺序读,所述缓存方式用于指示是否对预读的数据进行缓存。
4.根据权利要求2所述的方法,其特征在于,根据所述异步预读信息,直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区的步骤包括: 根据所述异步预读信息,和所述工作线程中的双缓冲区的大小,确定异步预读的次数和顺序; 根据确定的所述异步预读的次数和顺序,调用第三接口函数直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区。·
5.根据权利要求4所述的方法,其特征在于,所述第三接口函数的输入参数包括本次预读的所述待顺序读的数据块的信息。
6.根据权利要求2所述的方法,其特征在于,在所述工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据的步骤之前,还包括: 系统根据查询数据库文件的查询命令确定对数据库文件的查询是范围查询; 根据所述范围查询所查询的范围,为所述工作线程确定待顺序读的数据块。
7.根据权利要求6所述的方法,其特征在于,在根据所述范围查询所查询的范围,为所述工作线程确定待顺序读的数据块的步骤之后,还包括: 判断所述确定的待顺序读的数据块是否有多个;若是,则为所述工作线程分配与所述待顺序读的数据块的数量相同的双缓冲区。
8.根据权利要求7所述的方法,其特征在于,所述双缓冲区包括当前缓冲区和预读缓冲区; 对于所述工作线程中的每一个双缓冲区,所述直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区的步骤包括:所述工作线程交替使用其当前缓冲区和预读缓冲区,直接从所述外部存储器中异步预读所述对应的一个或多个待顺序读的数据块的数据,直至异步预读完所述对应的一个或多个待顺序读的数据块中的所有数据。
9.根据权利要求1至8任一项所述的方法,其特征在于,每个所述双缓冲区的大小固定。
10.根据权利要求9所述的方法,其特征在于,所述每个双缓冲区的大小为IM或2M。
11.根据权利要求2所述的方法,其特征在于,所述直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区的步骤包括: 所述工作线程使用DIRECT IO方式直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到自身的双缓冲区。
12.根据权利要求1所述的方法,其特征在于,所述工作线程的单独的上下文通过以下方式创建: 在所述工作线程创建时或所述工作线程首次读取数据时,使用Libaio为所述工作线程创建一个单独的上下文io_context。
13.根据权利要求1所述的方法,其特征在于,在所述工作线程调用第一接口函数监控其自身缓冲区异步预读数据状态的步骤之后,还包括: 所述工作线程根据所述异步预读数据的状态确定待处理的数据,并从自身的双缓冲区获取确定的所述数据进行处理。
14.根据权利要求13所述的方法,其特征在于, 所述当前缓冲区的状态包括空闲状态、等待状态和准备状态,所述当前缓冲区的空闲状态用于指示所述当前缓冲区当前空闲,所述当前缓冲区的等待状态用于指示等待异步读取数据到所述当前缓冲区,所述当前缓冲区的准备状态用于指示所述当前缓冲区异步读取数据完成; 所述预读缓冲区的状态包括空闲状态、等待状态和准备状态,所述预读缓冲区的空闲状态用于指示所述预读缓冲区当前空闲,所述预读缓冲区的等待状态用于指示等待异步读取数据到所述预读缓冲区,所述预读缓冲区的准备状态用于指示所述预读缓冲区异步读取数据完成。
15.根据权利要求14所述的方法,其特征在于,所述根据所述异步预读数据的状态确定待处理的数据,并从自身的缓冲区获取确定的所述数据进行处理的步骤包括: 所述工作线程确定其当前缓冲区或预读缓冲区的当前状态为所述准备状态,确定所述准备状态的所述当前缓冲区或所述预读缓冲区的数据为所述待处理的数据,从所述工作线程自身的所述当前缓冲区或所述预读缓冲区中获取数据并进行处理。
16.根据权利要求1所述的方法,其特征在于,所述第一接口函数为Libaio的io_getevents函数,和/或所述第二接口函数为advise函数,和/或所述第三接口函数为get_block函数。
17.一种数据处理装置,其特征在于,所述装置用于工作线程处理双缓冲区数据,其中,所述工作线程包括单独的上下文; 所述装置包括监控模块,用于使所述工作线程调用第一接口函数监控其自身双缓冲区异步预读数据状态。
18.根据权利要求17所述的装置,其特征在于,还包括: 预读模块,用于在所述监控模块使所述工作线程调用第一接口函数监控其自身缓冲区异步预读数据状态之前,使所述工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据,其中,所述第二接口函数携带有异步预读信息,所述异步预读信息包括:所述待顺序读的数据块的信息和所述待顺序读的数据块所属的数据库文件的句柄;根据所述异步预读信息,直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区。
19.根据权利要求18所述的装置,其特征在于,所述异步预读信息还包括:预读方式和/或缓存方式,其中,所述预读方式用于指示对所述待顺序读的数据块是正向顺序读还是反向顺序读,所述缓存方式用于指示是否对预读的数据进行缓存。
20.根据权利要求18所述的装置,其特征在于, 所述预读模块在根据所述异步预读信息,直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区时,根据所述异步预读信息,和所述工作线程中的双缓冲区的大小,确定异步预读的次数和顺序;根据确定的所述异步预读的次数和顺序,调用第三接口函数直接从外部存储器将对应的所述一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区。
21.根据权利要求20所述的装置,其特征在于,所述第三接口函数的输入参数包括本次预读的所述待顺序读的数据块的信息。
22.根据权利要求18所述的装置,其特征在于,还包括: 确定模块,用于在所述预读模块使所述工作线程调用第二接口函数指示异步预读一个或多个待顺序读的数据块的数据之前,系统根据查询数据库文件的查询命令确定对数据库文件的查询是范围查询;根据所述范围查询所查询的范围,为所述工作线程确定待顺序读的数据块。
23.根据权利要求22所述的装置,其特征在于,还包括: 分配模块,用于在所述确定模块根据所述范围查询所查询的范围,为所述工作线程确定待顺序读的数据块之后,判断所述确定的待顺序读的数据块是否有多个;若是,则为所述工作线程分配与所述待顺序读的数据块的数量相同的双缓冲区。
24.根据权利要求23所述的装置,其特征在于,所述双缓冲区包括当前缓冲区和预读缓冲区; 对于所述工作线程中的每一个双缓冲区,所述预读模块在直接从外部存储器将对应的一个或多个待顺序读的数据块的数据异步预读到所述工作线程自身的双缓冲区时,使所述工作线程交替使用其当前缓冲区和预读缓冲区,直接从所述外部存储器中异步预读所述对应的一个或多个待顺序读的数据块的数据,直至异步预读完所述对应的一个或多个待顺序读的数据块中的所有数据。
25.根据权利要求17至24任一项所述的装置,其特征在于,每个所述双缓冲区的大小固定。
26.根据权利要求25所述的装置,其特征在于,所述每个双缓冲区的大小为IM或2M。
【文档编号】G06F9/38GK103577158SQ201210250129
【公开日】2014年2月12日 申请日期:2012年7月18日 优先权日:2012年7月18日
【发明者】庄明强 申请人:阿里巴巴集团控股有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1