数据截断方法和装置与流程

文档序号:19745067发布日期:2020-01-21 18:13阅读:678来源:国知局
数据截断方法和装置与流程

本申请涉及分布式计算技术领域,具体涉及一种数据截断方法和装置。



背景技术:

在价格动因产生时触发已有价格的重新计算,同一段时间范围内的同一个业务维度的多个价格动因可能在同一时间点落在不同的机器上计算,如果不采用某种方式进行保证,就会导致数据的错乱。

举例说明:数据库中存在一条生效时间为2019-01-01~2019-12-31的a商品的底价为10元,现在来了一个2019-01-01~2019-10-01的a商品的供价动因(假设供价动因算出的底价是15元),紧接着又来了一个该时间段内的合同动因(假设合同动因算出的底价是5元),这个时候触发a商品的底价重新计算,就会涉及到价格时间的截断。按照动因的先后顺序,最后的正确截断价格应该是:2019-01-01~2019-10-01时间段内5元,2019-10-02~2019-12-31时间段内10元。在没有一个合理的解决方案来处理这两个价格动因,最后的计算结果可能与预期不符,可能的结果如下:

①假设供价动因触发的计算被分配到了s1机器上执行,合同动因触发的计算被分配到了s2机器上执行。如果s2的执行速度比s1快,s2先计算完了,价格变成2019-01-01~2019-10-01时间段5元,2019-10-02~2019-12-31时间段内10元,且提交数据库成功。而后s1执行完成,就会覆盖掉s2之前的价格,变成2019-01-01~2019-10-01时间段内15元,2019-10-02~2019-12-31时间段内10元,很显然前一段时间段内的价格跟预期的价格5元不符。

②还是上述场景,供价动因仍然在s1机器上执行,合同动因在s2机器上执行。s1执行完提交了,这个时候由于数据库事务并未结束,所以s1的计算结果并没有被s2读取到,s2使用的截断数据仍然是数据库中最原始的数据,最后导致的结果是2019-01-01~2019-10-01时间段内有2条数据,分别是s1算出来的15元和s2算出来的5元,2019-10-02~2019-12-31时间段内也存在2条数据,分别是s1算出来的15元和s2算出来的5元,很显然,这个结果和预期的结果也不一样。

相关技术中,一些项目是通过采用内存标志,或者文件标志、数据库标志来解决这个问题。但是内存只能是在独立的机器上运行才没有问题,在分布式计算上不行;至于文件和数据库标志,这两种方案导致的计算资源的占用会很大,影响程序的计算性能。



技术实现要素:

为至少在一定程度上克服相关技术中存在的问题,本申请提供一种数据截断方法和装置。

根据本申请实施例的第一方面,提供一种数据截断方法,包括:

在接收到计算任务时,检测是否存在全局锁;

如果不存在,则根据计算任务设置一个全局锁,并根据计算任务进行数据截断;

如果存在,则根据全局锁的属性判断是否执行计算任务。

进一步地,全局锁的属性包括版本号;

相应地,所述根据全局锁的属性判断是否执行计算任务,包括:

将全局锁的版本号与计算任务的版本号进行比较;

根据比较结果判断是否执行计算任务。

进一步地,所述根据比较结果判断是否执行计算任务,包括:

如果计算任务的版本号更高,则将计算任务放入等待队列;

如果计算任务的版本号更低,则根据生效时间判断是否执行计算任务;

其中,全局锁/计算任务的版本号与全局锁/计算任务的时间戳相对应,时间戳靠前则版本号低。

进一步地,所述根据生效时间判断是否执行计算任务,包括:

判断全局锁的生效时间与计算任务的生效时间是否一致;

如果一致,则放弃该计算任务;

如果不一致,则将计算任务放入等待队列。

进一步地,所述将计算任务放入等待队列,包括:

等待全局锁释放;

当检测到全局锁已经释放时,根据计算任务设置一个新的全局锁,并根据计算任务进行数据截断。

进一步地,所述等待全局锁释放,包括:

按照预设的检测频率,定期检测全局锁是否存在;

当全局锁不存在时,则全局锁已经释放。

进一步地,所述根据计算任务进行数据截断之后,还包括:

将数据截断结果提交到数据库,并释放全局锁。

进一步地,所述释放全局锁之后,还包括:

检测全局锁是否释放成功;

如果成功,则结束运行;

如果失败,则重新尝试释放全局锁;

如果超时,则等待自动释放全局锁。

进一步地,所述等待自动释放全局锁,包括:

在设置全局锁时,同时记录全局锁存在的时间;

当全局锁存在的时间超过预设的时间阈值时,自动释放全局锁。

根据本申请实施例的第二方面,提供一种数据截断装置,包括:

检测模块,用于在接收到计算任务时,检测是否存在全局锁;

执行模块,用于在检测到不存在全局锁时,根据计算任务设置一个全局锁,并根据计算任务进行数据截断;

判断模块,用于在检测到存在全局锁时,根据全局锁的属性判断是否执行计算任务。

本申请的实施例提供的技术方案具备以下有益效果:

采用全局锁来保证分布式计算数据截断的准确性,减少并控制错误数据的生成,从源头保证数据的准确,避免因为数据截断可能导致的错乱而造成损失;减少文件系统和数据库的消耗,提升系统的整体运算性能。

应当理解的是,以上的一般描述和后文的细节描述仅是示例性和解释性的,并不能限制本申请。

附图说明

此处的附图被并入说明书中并构成本说明书的一部分,示出了符合本申请的实施例,并与说明书一起用于解释本申请的原理。

图1是根据一示例性实施例示出的一种数据截断方法的流程图。

图2是根据一示例性实施例示出的一种数据截断方法的控制流程图。

具体实施方式

这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本申请相一致的所有实施方式。相反,它们仅是与如所附权利要求书中所详述的、本申请的一些方面相一致的装置和方法的例子。

图1是根据一示例性实施例示出的一种数据截断方法的流程图。该方法可以应用于重新计算价格时的数据截断,包括以下步骤:

步骤101:在接收到计算任务时,检测是否存在全局锁;

步骤102:如果不存在,则根据计算任务设置一个全局锁,并根据计算任务进行数据截断;

步骤103:如果存在,则根据全局锁的属性判断是否执行计算任务。

本方案的原理是设置一个全局的标志,让各个线程都能读取到这个标志。本申请的方案采用全局锁来保证分布式计算数据截断的准确性,减少并控制错误数据的生成,从源头保证数据的准确,避免因为数据截断可能导致的错乱而造成损失;减少文件系统和数据库的消耗,提升系统的整体运算性能。

需要说明的是,全局锁可以理解为一种在分布式集群中的唯一标志,所有线程并发计算时,在某一时间点只能有一个线程持有全局锁。

参照图2,一些实施例中,全局锁的属性包括版本号;

相应地,所述根据全局锁的属性判断是否执行计算任务,包括:

将全局锁的版本号与计算任务的版本号进行比较;

根据比较结果判断是否执行计算任务。

一些实施例中,所述根据比较结果判断是否执行计算任务,包括:

如果计算任务的版本号更高,则将计算任务放入等待队列;

如果计算任务的版本号更低,则根据生效时间判断是否执行计算任务;

其中,全局锁/计算任务的版本号与全局锁/计算任务的时间戳相对应,时间戳靠前则版本号低。

需要说明的是,当某个线程设置全局锁时,该全局锁的版本号(时间戳)与本次计算任务的版本号(时间戳)相同。也即,所述“将全局锁的版本号与计算任务的版本号进行比较”,等于是将正在进行的计算任务与等待进行的计算任务进行版本号的比较。

一些实施例中,所述根据生效时间判断是否执行计算任务,包括:

判断全局锁的生效时间与计算任务的生效时间是否一致;

如果一致,则放弃该计算任务;

如果不一致,则将计算任务放入等待队列。

参照图2,正在进行的计算任务(等效于全局锁)与等待进行的计算任务之间,还要比较二者的生效时间是否存在时间交集,判断时间交集的步骤可以在比较版本号的步骤之前。容易理解的是,判断时间交集的步骤在判断时间一致的步骤之前,也能达到同样的效果。

参照背景技术部分所提出的价格变动的计算任务,假设合同动因的生效时间为2019-01-01~2019-06-01,合同动因先计算,其余条件不变。动因的生效时间也会被保存在全局锁中,因此全局锁中存储有版本号和生效时间范围两个字段。

合同动因先计算,那么此时会设置一个a_key的redis全局锁,存储有版本号、生效时间(假设为101、2019-01-01~2019-06-01)。当供价动因来时,根据a_key能够获取到锁,这个时候会先看下生效时间是否完全一致,如果时间完全一致则看版本号大小,版本号小直接丢弃;如果生效时间不是完全一致则看时间是否有交集。如果没有交集则继续等待锁;如果有交集(在此处假设的情形下,合同动因与供价动因的交集为2019-01-01~2019-06-01),则根据版本号,把小版本中存在交集的时间剔除,只留下无交集的时间(2019-06-02~2019-10-01)继续等待。

一些实施例中,所述将计算任务放入等待队列,包括:

等待全局锁释放;

当检测到全局锁已经释放时,根据计算任务设置一个新的全局锁,并根据计算任务进行数据截断。

参照图2,如果设置redis全局锁失败,程序会根据配置的尝试次数和重试间隔时间重复尝试,当尝试次数达到设定的值后仍然没有成功,则本次计算任务结束。

一些实施例中,所述等待全局锁释放,包括:

按照预设的检测频率,定期检测全局锁是否存在;

当全局锁不存在时,则全局锁已经释放。

一些实施例中,所述根据计算任务进行数据截断之后,还包括:

将数据截断结果提交到数据库,并释放全局锁。

需要说明的是,数据截断是在内存中进行操作的,不会出现异常。提交到数据库成功后,需要释放redis锁;如果是提交到数据库失败,则数据不会入表,此时仍然需要释放掉redis全局锁。如果数据提交成功了,但是锁释放失败了,不影响数据的正常入表。

一些实施例中,所述释放全局锁之后,还包括:

检测全局锁是否释放成功;

如果成功,则结束运行;

如果失败,则重新尝试释放全局锁;

如果超时,则等待自动释放全局锁。

需要说明的是,如果释放redis全局锁失败,程序会根据配置的尝试次数和尝试间隔重复尝试,当尝试次数达到配置值后仍然没有释放成功,这个时候就只能等待全局锁超时后自动失效。

一些实施例中,所述等待自动释放全局锁,包括:

在设置全局锁时,同时记录全局锁存在的时间;

当全局锁存在的时间超过预设的时间阈值时,自动释放全局锁。

下面结合具体的应用场景,对本申请的方案进行拓展说明。

当价格的动因产生或其他场景下需要触发到价格的计算,导致同一时间或者极短时间内同一维度的商品价格在不同机器上执行时(涉及到价格有效时间段截断),先执行的线程会设置一个redis全局锁,并存放对应的业务维度和运行的时间戳(版本号),当第二个线程再执行同维度商品的价格计算时会根据业务维度先进行全局锁的检测,如果没有检测到同维度的全局锁则正常继续运行,同时设置全局锁;如果检测到同维度的全局锁,则将锁中存放的版本和自己需要计算的版本进行比较,如果发现自己计算的版本比锁中的版本小则直接结束,否则进行等待。当持有锁的线程把事情做完后释放掉redis的全局锁,此时等待的线程则可以继续运行。当持有锁的线程运行异常或者超时后,自动释放掉锁,避免出现死锁情况。

下面结合具体的计算任务进行说明,在实际项目中本方法如何解决可能产生的数据截断错乱问题。

背景数据:数据库中已经存在一条生效时间为2019-01-01~2019-12-31的a商品的底价为10元。

动因数据1:来了一个2019-01-01~2019-10-01的a商品的供价动因(供价动因算出的底价是15元),此时需要触发a商品的底价重新计算,该动因计算被分配到了服务器集群中的s1机器执行。

动因数据2:紧接着又来了一个2019-01-01~2019-10-01时间段内的合同动因(合同动因算出的底价是5元),这个时候需要再次触发a商品的底价重新计算,该动因计算被分配到了服务器集群中的s2机器执行。

主要业务逻辑:拿数据库中对应的业务维度的数据,同本次需要计算的业务维度数据进行时间段的截断,如数据库中的数据是a商品的2019-01-01~2019-12-31的数据,本次需要计算的是2019-01-01~2019-10-01,那么最后截断出来的时间段就是本次计算出的结果会覆盖数据库中同时间段的2019-01-01~2019-10-01的数据,继续保留2019-10-02~2019-12-31的原始数据,最后数据库中的数据会由原来的一条变成2条。

最终正确结果:数据库中存在2条a商品的底价数据,一条是2019-01-01~2019-10-01价格5元,2019-10-02~2019-12-31价格10元。

处理过程:s1机器先接到供价的动因计算,此时s1机器中的执行线程会拿着a商品的业务主键a_key在redis集群中寻找对应的全局锁。此时没有找到,程序会设置一个全局锁,锁中的主键就是a_key,锁中的值就是供价动因的时间戳(版本号)123。经过这个操作后在redis集群中会存在一个a_key:123这样的数据,然后s1机器上的执行线程继续做后续的业务逻辑处理,处理过程尚未完全结束。

这个时候合同动因也同步在s2机器上执行了,s2的执行线程也会先拿着a商品的业务主键a_key在redis集群中寻找对应的全局锁。由于s1线程尚未执行完成,此时redis集群中a_key对应的全局锁还没有释放,故s2执行线程会发现已经存在a_key对应的全局锁。

此时s2线程开始比较锁中的版本和自己的版本大小,由于s2是后接到的动因,所以s2的版本会比较大,这个时候s2会进入等待状态,并每隔一段时间进行一次锁的重新检测。

经过一段时间后,s1线程执行完成了,数据提交到了数据库,此时数据库中的数据变成了2019-01-01~2019-10-01时间段为15元,2019-10-02~2019-12-31时间段为10元,同时s1释放掉a_key这个全局锁。s2再次检测时会发现a_key对应的全局锁没有了,会立即设置a_key的全局锁(这个过程和s1执行的过程是一样的),此时redis集群中又会出现一个a_key:124的全局锁,然后s2继续执行后续的业务逻辑。

待计算完成后需要进行截断时,s2会取数据库中最新的业务数据。由于经过s1计算后,数据库中的数据已经变成了2条:2019-01-01~2019-10-01(15元),2019-10-02~2019-12-31(10元)。s2算出来的是2019-01-01~2019-10-01(5元),根据业务处理逻辑,这个时候s2会用计算出来的同时间段数据覆盖数据库中同时间段的数据,保留没有时间交集的原始数据,最后变成2019-01-01~2019-10-01(5元),2019-10-02~2019-12-31(10元),并提交数据库。这个计算结果就和我们预期的结果是一致的了。对于超时后自动释放锁,这个主要是为了解决死锁问题,保证程序能够正常运行。

本申请的方案采用redis的全局锁,保证分布式计算数据截断的准确性;通过对事务的整体控制,保证数据的一致性。保障价格在分布式计算过程中数据截断的准确性和实时性,减少并控制错误价格的生成,从源头保证价格的准确。充分保证了数据的准确性,从而避免了因为数据截断可能导致的错乱对项目结果产生的损失。

与现有的一些解决方案相比,本申请的方案减少了文件系统和数据库的消耗,提升了系统的整体运算性能。此外,还通过超时或异常处理,避免死锁的发生。

本申请还提供如下的实施例:

一种数据截断,该装置包括:

检测模块,用于在接收到计算任务时,检测是否存在全局锁;

执行模块,用于在检测到不存在全局锁时,根据计算任务设置一个全局锁,并根据计算任务进行数据截断;

判断模块,用于在检测到存在全局锁时,根据全局锁的属性判断是否执行计算任务。

关于上述实施例中的装置,其中各个模块执行操作的具体步骤已经在有关该方法的实施例中进行了详细描述,此处不再详细阐述说明。

可以理解的是,上述各实施例中相同或相似部分可以相互参考,在一些实施例中未详细说明的内容可以参见其他实施例中相同或相似的内容。

需要说明的是,在本申请的描述中,术语“第一”、“第二”等仅用于描述目的,而不能理解为指示或暗示相对重要性。此外,在本申请的描述中,除非另有说明,“多个”的含义是指至少两个。

流程图中或在此以其他方式描述的任何过程或方法描述可以被理解为,表示包括一个或更多个用于实现特定逻辑功能或过程的步骤的可执行指令的代码的模块、片段或部分,并且本申请的优选实施方式的范围包括另外的实现,其中可以不按所示出或讨论的顺序,包括根据所涉及的功能按基本同时的方式或按相反的顺序,来执行功能,这应被本申请的实施例所属技术领域的技术人员所理解。

应当理解,本申请的各部分可以用硬件、软件、固件或它们的组合来实现。在上述实施方式中,多个步骤或方法可以用存储在存储器中且由合适的指令执行系统执行的软件或固件来实现。例如,如果用硬件来实现,和在另一实施方式中一样,可用本领域公知的下列技术中的任一项或他们的组合来实现:具有用于对数据信号实现逻辑功能的逻辑门电路的离散逻辑电路,具有合适的组合逻辑门电路的专用集成电路,可编程门阵列(pga),现场可编程门阵列(fpga)等。

本技术领域的普通技术人员可以理解实现上述实施例方法携带的全部或部分步骤是可以通过程序来指令相关的硬件完成,所述的程序可以存储于一种计算机可读存储介质中,该程序在执行时,包括方法实施例的步骤之一或其组合。

此外,在本申请各个实施例中的各功能单元可以集成在一个处理模块中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个模块中。上述集成的模块既可以采用硬件的形式实现,也可以采用软件功能模块的形式实现。所述集成的模块如果以软件功能模块的形式实现并作为独立的产品销售或使用时,也可以存储在一个计算机可读取存储介质中。

上述提到的存储介质可以是只读存储器,磁盘或光盘等。

在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本申请的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不一定指的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任何的一个或多个实施例或示例中以合适的方式结合。

尽管上面已经示出和描述了本申请的实施例,可以理解的是,上述实施例是示例性的,不能理解为对本申请的限制,本领域的普通技术人员在本申请的范围内可以对上述实施例进行变化、修改、替换和变型。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1