一种实现业务幂等的方法、装置、设备和介质

文档序号:1888757 发布日期:2021-11-26 浏览:36次 >En<

阅读说明:本技术 一种实现业务幂等的方法、装置、设备和介质 (Method, device, equipment and medium for realizing service idempotency ) 是由 刘鹏 于 2021-08-10 设计创作,主要内容包括:本申请提供了一种实现业务幂等的方法、装置、设备和介质,其中,方法包括:扫描业务代码,从业务代码中确定目标对象,为目标对象加锁,并执行目标对象,在目标对象执行完后,将加在目标对象上的锁释放。由此可见,本申请提供的实现业务幂等的方法使得在实现业务幂等的过程中,开发人员仅在业务代码中的目标对象上增加注解即可,无需针对各目标对象额外编写代码,对开发人员更友好,并且使用成本较低。(The application provides a method, a device, equipment and a medium for realizing service idempotent, wherein the method comprises the following steps: scanning the service code, determining a target object from the service code, locking the target object, executing the target object, and releasing the lock added to the target object after the target object is executed. Therefore, the method for realizing the business idempotent provided by the application enables developers to add annotations only on the target objects in the business codes in the process of realizing the business idempotent, does not need to write codes additionally for all the target objects, is more friendly to the developers, and has lower use cost.)

一种实现业务幂等的方法、装置、设备和介质

技术领域

本申请涉及计算机技术领域,特别是涉及一种实现业务幂等的方法、装置、设备和介质。

背景技术

在复杂分布式系统中,接口幂等是基本要求。例如,购物车提交时,由于网络抖动或用户频繁点击可能会多次请求创单接口,创单接口对于购物车流水号应该幂等。

可基于分布式锁为目标对象加锁和释放锁,即基于分布式锁为待进行幂等操作的对象加锁和释放锁,以避免目标对象重复执行,保证了业务幂等性,比如,基于数据库唯一索引的分布式锁为目标对象加锁和释放锁;基于数据库乐观锁为目标对象加锁和释放锁;基于数据库悲观锁为目标对象加锁和释放锁;基于redis实现的分布式锁为目标对象加锁和释放锁;基于zookeeper锁为目标对象加锁和释放锁;等等。

目前,通常需要开发人员针对各目标对象额外编写代码,以基于分布式锁实现为目标对象加锁和释放锁,例如,基于数据库唯一索引的分布式锁为业务代码中的目标对象加锁和释放锁时,需要开发人员在业务代码中编写加锁、释放锁、补偿和异常处理等代码。但是,额外编写代码对开发人员不友好,并且现有的分布式锁的使用成本通常较高。

发明内容

有鉴于此,本申请提供了一种实现业务幂等的方法和装置,以解决现有技术中额外编写代码对开发人员不友好且分布式锁的使用成本高的问题,其技术方案如下:

一种实现业务幂等的方法,包括:

扫描业务代码,从业务代码中确定目标对象,目标对象为待进行幂等操作的对象,目标对象标注有注解;

为目标对象加锁,并执行目标对象;

在目标对象执行完后,将加在目标对象上的锁释放。

可选的,为目标对象加锁,包括:

生成目标对象对应的切面AOP;

基于切面AOP为目标对象加锁;

将加在目标对象上的锁释放,包括:

基于切面AOP将加在目标对象上的锁释放。

可选的,还包括:

若目标对象执行的过程中产生业务异常,则拦截目标对象,并将加在目标对象上的锁释放。

可选的,在目标对象执行完后,将加在目标对象上的锁释放,包括:

若目标对象执行成功,则确定目标对象所在线程是否处于锁定状态;

若是,则将加在目标对象上的锁释放。

可选的,目标对象上添加的锁设置有超时时间;

实现业务幂等的方法,还包括:

基于目标对象上加的锁内部的异步定时任务定时扫描目标对象上加的锁;

若在超时时间内对目标对象上的锁执行释放锁操作,且释放失败,则使目标对象上加的锁自动释放。

可选的,实现业务幂等的方法,还包括:

若在超时时间内未对目标对象上的锁执行释放锁操作,则延长超时时间。

可选的,目标对象上加的锁为乐观锁或基于Redis的分布式锁。

一种实现业务幂等的装置,包括:代码扫描模块、加锁模块和锁释放模块;

代码扫描模块,用于扫描业务代码,从业务代码中确定目标对象,目标对象为待进行幂等操作的对象,目标对象标注有注解;

加锁模块,用于为目标对象加锁,并执行目标对象;

锁释放模块,用于在目标对象执行完后,将加在目标对象上的锁释放。

一种实现业务幂等的设备,包括存储器和处理器;

所述存储器,用于存储程序;

所述处理器,用于执行所述程序,实现如上述任一项的实现业务幂等的方法的各个步骤。

一种计算机可读存储介质,其上存储有计算机程序,其特征在于,计算机程序被处理器执行时,实现如上述任一项的实现业务幂等的方法的各个步骤。

经由上述的技术方案可知,本申请提供的实现业务幂等的方法,扫描业务代码,从业务代码中确定目标对象,为目标对象加锁,并执行目标对象,在目标对象执行完后,将加在目标对象上的锁释放。由此可见,本申请提供的实现业务幂等的方法使得在实现业务幂等的过程中,开发人员仅在业务代码中的目标对象上增加注解即可,无需针对各目标对象额外编写代码,对开发人员更友好,并且使用成本较低。

附图说明

为了更清楚地说明本申请实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本申请的实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据提供的附图获得其他的附图。

图1为本申请实施例提供的一种实现业务幂等的方法的流程示意图;

图2为本申请实施例提供的实现业务幂等的装置的结构示意图;

图3为本申请实施例提供的实现业务幂等的设备的硬件结构框图。

具体实施方式

下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。

一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同,幂等方法是指可以使用相同参数重复执行,并能获得相同结果。如背景技术中介绍,基于分布式锁为目标对象加锁和释放锁时,需要开发人员在业务代码中编写加锁、释放锁、补偿和异常处理等代码,对开发人员不友好。此外,现有的分布式锁的使用成本通常较高,例如,使用zookeeper锁时,需要引入zookeeper中间件,增加了运维成本。

为了解决现有技术存在的问题,本案发明人在深入研究后想到:可以由开发人员在业务代码中的目标对象上增加注解@Lock,之后可对业务代码进行扫描,以基于扫描到的注解,从业务代码中确定目标对象,并为目标对象加锁和释放锁。基于此,本案发明人提出了一种实现业务幂等的方法,接下来通过下述实施例对本申请提供的实现业务幂等的方法进行详细介绍。

请参阅图1,示出了本申请实施例提供的实现业务幂等的方法的流程示意图,该实现业务幂等的方法可以包括:

步骤S101、扫描业务代码,从业务代码中确定目标对象。

其中,目标对象标注有注解。

开发人员可在需要实现业务幂等时,为业务代码中的目标对象增加注解@Lock,该注解用于指示目标对象为待进行幂等操作的对象。

本步骤可扫描业务代码,以基于扫描到的注解从业务代码中确定目标对象,以便后续步骤为目标对象加锁和释放锁。

可选的,在本步骤中,开发人员为目标对象增加注解包括两种方式:

第一种方式,在整个目标对象上增加注解。

在本实施例中,若在整个目标对象上增加注解,则后续加锁操作针对的是整个目标对象,即目标对象执行一次后,必须等待该目标对象上加的锁释放后,该目标对象才可再次执行。

第二种方式,在为目标对象增加注解时,手动指定需要锁的业务key。

这里,业务key可以为用户的标识信息,例如用户ID、手机号等。

在本实施例中,若在为目标对象增加注解时,手动指定需要锁的业务key,则后续加锁操作针对的是业务key对应的目标对象。

以购物车创建订单的场景为例,购物车提交时,由于网络抖动或用户频繁点击可能会多次请求创单接口,创单接口对于购物车流水号应该幂等,此时可将order的uuid字段作为需要锁的业务key,则实现逻辑大体如下。

下面以举例方式说明两种方式的区别,并假设目标对象为支付方法。

针对第一种方式:

若为整个支付方法增加注解,则后续加锁针对整个支付方法,即用户A在支付时会为支付方法加锁,加锁后用户B无法进行支付,只能等待用户A支付结束且加在该支付方法上的锁释放后,用户B才可进行支付,用户B在支付时也会为该支付方法加锁,加锁后用户A无法进行支付,只能等待用户B支付结束且加在该支付方法上的锁释放后,用户A才可再次进行支付。

针对第二种方式:

假设手动指定需要锁的业务key为用户A和B的手机号,则用户A基于手机号进行支付时会为该支付方法加锁,该锁仅针对用户A有效,针对用户B无效,即加锁后用户B仍可进行支付;同理,在用户B基于手机号进行支付时也会为该支付方法加锁,该锁仅针对用户B有效,针对用户A无效,加锁后用户A仍可进行支付。

步骤S102、为目标对象加锁,并执行目标对象。

由于网络抖动或用户频繁点击等可能会多次触发目标对象,如若每次触发目标对象,该目标对象均执行,则可能出现多个结果,导致业务无法幂等。为避免出现这种情况,本步骤可为目标对象加锁,以便加锁后直至释放锁之前,目标对象仅执行一次。

需要说明的是,本步骤可在目标对象首次执行前,为目标对象加锁。若加锁后直至释放锁之前,目标对象需要再次执行,则本步骤不再为目标对象加锁,并且会拦截目标对象,终止目标对象的再次执行,以避免目标对象多次执行。也即,本步骤可在目标对象首次需要执行前,为目标对象加锁,并在加锁后执行目标对象,在目标对象加锁之后直至释放锁之前,若目标对象仍需执行,可拦截该目标对象,终止该目标对象的再次执行,这样就能保证在一次“加锁-释放锁”的过程中,目标对象仅执行一次,由此实现了业务幂等。

例如用户首次点击支付按键,可为支付按键对应的支付方法加锁,加锁后支付方法开始执行,在本次加锁直至释放锁之前,若用户再次点击支付按键,则拦截支付方法,终止支付方法的再次执行,以防用户多次支付。

更具体的来说,本实施例会在目标对象每次执行前(即目标对象即将执行但未执行时)获取锁,其中,若获取锁成功,表示目标对象仍未加锁,则可基于获取到的锁为目标对象加锁;若获取锁失败,表示目标对象已加锁,则抛出异常,拦截目标对象,终止目标对象的再次执行,优选的情况下,还可返回指示重复执行异常的信息。

可以理解的是,对于目标对象首次执行,获取锁成功的概率会比较高,此时可基于获取到的锁为目标对象加锁;若目标对象不是首次执行,那么获取锁时会自动判断目标对象是否锁定,若目标对象已经锁定,即目标对象已加锁,则抛出异常,拦截目标对象,终止目标对象的再次执行,若目标对象未锁定,则基于获取到的锁为目标对象加锁。

可选的,本步骤在为目标对象加锁后,还可进一步确定是否加锁成功,若加锁成功,则执行后续操作,例如在目标对象执行前打印日志、执行目标对象等,若加锁失败,则抛出异常,返回指示加锁失败的异常信息。

值得注意的是,本申请可针对一目标对象重复执行“加锁-释放锁”操作,那么本步骤中的“首次执行”是指一次“加锁-释放锁”过程中的第一次执行(非首次执行会在目标对象加锁后被拦截),若针对一目标对象多次执行“加锁-释放锁”操作,则该目标对象可以对应有多次“首次执行”。例如,用户首次点击支付按键后,可为支付按键对应的支付方法加锁,加锁后支付方法首次执行,在用户完成支付后,可将加在支付方法上的锁释放,之后用户可再次点击支付按键,加锁后支付方法可再次首次执行。

在一可选实施例中,本实施例给出了本步骤的一种具体实现方式,可选的,该实现方式可以包括以下步骤S1021~步骤S1022:

步骤S1021、生成目标对象对应的切面AOP。

AOP是指面向切面编程,其英文全称为“Aspect Oriented Programming”,该切面AOP具有目标对象执行前调用前置处理、目标对象执行完后调用后置处理的能力。

可选的,前置处理可以包括打印日志和获取锁(在本实施例中,获取锁成功后可开启try代码块以便为目标对象加锁),相对的,后置处理可以包括打印日志和开启finish代码块以便将加在目标对象上的锁释放。

步骤S1022、基于切面AOP为目标对象加锁。

具体的,在为目标对象创建锁后,可基于切面AOP调用try代码块以便为目标对象加锁。可选的,在确定加锁成功后,还可基于切面AOP在目标对象执行前打印日志。

步骤S103、在目标对象执行完后,将加在目标对象上的锁释放。

可选的,与上述“基于切面AOP为目标对象加锁”相对应的,本步骤可基于切面AOP将加在目标对象上的锁释放,也即,本步骤可基于切面AOP调用finish代码块以便将加在目标对象上的锁释放。可选的,在释放锁后,还可基于切面AOP打印日志。

本申请提供的实现业务幂等的方法,在实现业务幂等的过程中,开发人员仅在业务代码中的目标对象上增加注解即可,无需针对各目标对象额外编写代码,对开发人员更友好,并且仅需一个注解即可保证业务幂等,开发人员上手成本较低且使用简单。

此外,本申请提供的实现业务幂等的方法可以以jar包依赖的方式引入业务代码中,这样可使jar包与业务代码完全解耦,在不需要实现业务幂等时,可将jar包从业务代码中轻松剥离出来,使用上更加方便。

在以下实施例中,对目标对象执行可能出现的一些情况进行介绍。

情况一,目标对象执行的过程中可能出现业务异常,例如空指针、无权限等异常,为了保证业务异常后,加在目标对象上的锁能够顺利释放,本实施例可通过catch代码块捕获目标对象执行过程中产生的业务异常,在捕获到业务异常后,拦截该目标对象,终止该目标对象的执行,并将加在目标对象上的锁释放,优选的,还可在捕获到业务异常后原样抛出,并抛出“执行过程异常”。

可选的,本实施例中“将加在目标对象上的锁释放”具体可以为:通过切面AOP调用finish代码块以将加在目标对象上的锁释放。

情况二,目标对象可能顺利执行完,则本实施例可在目标对象执行成功后,确定目标对象所在线程是否处于锁定状态,若是,则将加在目标对象上的锁释放。

可选的,本实施例在确定目标对象所在线程处于锁定状态时,可发出锁释放信号,以将加在目标对象上的锁释放。这里,“将加在目标对象上的锁释放”具体可以为:通过切面AOP调用finish代码块以将加在目标对象上的锁释放。

可选的,若目标对象所在线程未处于锁定状态,则可打印日志,以便基于日志排查问题。

综合上述情况一和情况二可见,无论是目标对象执行的过程中产生业务异常还是目标对象成功执行,本申请都可以通过切面AOP调用finish代码块以将加在目标对象上的锁释放。可以理解的是,将加在目标对象上的锁释放时,可能会释放成功,也可能会释放失败。若释放成功,则可打印日志,并正常结束业务代码,若释放失败,会抛出“释放锁异常”,并可参见情况三。

情况三,为了应对加在目标对象上的锁释放失败的情况,本申请实施例可在加锁时设置超时时间,并利用锁内部的“巡逻队”(该“巡逻队”为一个异步定时任务)自动释放锁,具体来说,可在超时时间内基于目标对象上加的锁内部的异步定时任务定时扫描目标对象上加的锁,若发现已接收到锁释放信号但目标对象上加的锁释放失败,则使目标对象上加的锁自动释放,这里,“释放失败”是指在超时时间内对目标对象上的锁执行释放锁操作且释放失败。例如,假设超时时间为30秒,则可基于异步定时任务每隔5秒进行一次扫描,如在第15秒时发现已接收到锁释放信号但目标对象上加的锁释放异常,则可使目标对象上加的锁自动释放。

可选的,可能存在目标对象上加的锁在达到超时时间时正在释放的情况,或者存在达到超时时间时目标对象上加的锁刚好释放失败的情况,此时可直接基于异步定时任务使目标对象上加的锁自动释放。

由于本申请可基于异步定时任务使目标对象上加的锁自动释放,因此在释放锁失败时,开发人员可自主选择是否处理该异常。

情况四,极端情况下,例如目标对象执行的过程中断网、断电、加锁后的应用异常退出等极端情况(在出现极端情况前目标对象仍在执行,并且未执行到释放锁的步骤,即未执行步骤S103),为了防止出现“死锁”,可基于异步定时任务在发现未释放的锁时,延长锁的生存时间。也即,本申请可基于目标对象上加的锁内部的异步定时任务定时扫描目标对象上加的锁,如发现在超时时间内未对目标对象上的锁执行释放锁操作,则延长超时时间。例如,假设超时时间为30秒,则可基于异步定时任务每隔5秒进行一次扫描,如在第5秒时发现未对目标对象上的锁执行释放锁操作,则延长超时时间,例如延长30秒。如此,即使出现特殊情况导致目标对象暂时不能执行,也可在恢复正常后使目标对象继续执行。

综上,本申请可应用于全场景下,无论目标对象执行是否出现异常,都能保证目标对象上加的锁顺利释放,不会出现“死锁”,并且极端情况下通过延长超时时间的补偿方式使得目标对象能够顺利执行,从而保证本申请的业务100%幂等。此外,本申请可在高可用、分布式场景下,至少达到5个9的可用性,性能更高,稳定性更好。

考虑到将本申请提供的实现业务幂等的方法应用于分布式系统时新老系统的兼容性问题,在本实施例中,目标对象上加的锁可以为乐观锁,或者基于Redis的分布式锁。

其中,基于Redis的分布式锁的核心实现为SET lockKey locakVuale EX 30。在本实施例中,基于Redis的分布式锁可使用现有的Redisson框架,该框架实现了Redlock(Redis Distributed Lock)算法,能够保证Redis集群情况下,锁数据的一致性问题,并且该框架支持Redis集群模式下锁数据的一致性和可用性。

基于数据库的乐观锁的核心实现为:UPDATE t_lock SET lock=${lock},SETversion=${version}。在本实施例中,数据库主从模式下,优选开启“半同步复制”,以保证主库写入数据后,从库也写入成功后再返回,本申请为数据库实现了类Redlock算法,保证数据库集群模式下锁数据的一致性和可用性。

由于和乐观锁相比,基于Redis的分布式锁的性能更高,因此默认情况下使用基于Redis的分布式锁,当然,为保证历史项目和向下兼容,也可使用基于数据库的乐观锁。

在本实施例中,具体选用哪一锁需要根据开发人员预先配置的信息确定,或者根据分布式系统引入的插件确定,其中,若引入数据库插件,则使用基于数据库的乐观锁;若引入Redis插件,则使用基于Redis的分布式锁。

由于本实施例可采用缓存(即基于Redis的分布式锁)加数据库双锁实现,能够向下兼容老分布式系统的同时支持新的分布式系统,兼容性更好,支持复杂分布式系统的高并发要求。

本申请实施例还提供了一种实现业务幂等的装置,下面对本申请实施例提供的实现业务幂等的装置进行描述,下文描述的实现业务幂等的装置与上文描述的实现业务幂等的方法可相互对应参照。

请参阅图2,示出了本申请实施例提供的实现业务幂等的装置的结构示意图,如图2所示,该装置可以包括:代码扫描模块201、加锁模块202和释放锁模块203。

代码扫描模块201,用于扫描业务代码,从业务代码中确定目标对象,目标对象为待进行幂等操作的对象,目标对象标注有注解。

加锁模块202,用于为目标对象加锁,并执行目标对象。

锁释放模块203,用于在目标对象执行完后,将加在目标对象上的锁释放。

本申请提供的实现业务幂等的装置,扫描业务代码,从业务代码中确定目标对象,为目标对象加锁,并执行目标对象,在目标对象执行完后,将加在目标对象上的锁释放。由此可见,本申请提供的实现业务幂等的装置使得在实现业务幂等的过程中,开发人员仅在业务代码中的目标对象上增加注解即可,无需针对各目标对象额外编写代码,对开发人员更友好,并且使用成本较低。

在一种可能的实现方式中,上述加锁模块202,具体用于生成目标对象对应的切面AOP,基于切面AOP为目标对象加锁。

相应的,上述锁释放模块203,具体用于基于切面AOP将加在目标对象上的锁释放。

在一种可能的实现方式中,本申请实施例提供的实现业务幂等的装置还可以包括:异常处理模块。

异常处理模块,用于若目标对象执行的过程中产生业务异常,则拦截目标对象,并将加在目标对象上的锁释放。

在一种可能的实现方式中,上述锁释放模块203还可以包括:线程锁定判断模块和锁释放子模块。

线程锁定判断模块,用于若目标对象执行成功,则确定目标对象所在线程是否处于锁定状态。

锁释放子模块,用于在线程锁定判断模块确定目标对象所在线程处于锁定状态,则将加在目标对象上的锁释放。

在一种可能的实现方式中,目标对象上添加的锁设置有超时时间,则本申请实施例提供的实现业务幂等的装置还可以包括:扫描模块和自动释放模块。

锁扫描模块,用于基于目标对象上加的锁内部的异步定时任务定时扫描目标对象上加的锁。

自动释放模块,用于若在超时时间内对目标对象上的锁执行释放锁操作,且释放失败,则使目标对象上加的锁自动释放。

在一种可能的实现方式中,本申请实施例提供的实现业务幂等的装置还可以包括:超时时间延长模块。

超时时间延长模块,用于若在超时时间内未对目标对象上的锁执行释放锁操作,则延长超时时间。

本申请实施例还提供了一种实现业务幂等的设备。可选的,图3示出了实现业务幂等的设备的硬件结构框图,参照图3,该实现业务幂等的设备的硬件结构可以包括:至少一个处理器301,至少一个通信接口302,至少一个存储器303和至少一个通信总线304;

在本申请实施例中,处理器301、通信接口302、存储器303、通信总线304的数量为至少一个,且处理器301、通信接口302、存储器303通过通信总线304完成相互间的通信;

处理器301可能是一个中央处理器CPU,或者是特定集成电路ASIC(ApplicationSpecific Integrated Circuit),或者是被配置成实施本发明实施例的一个或多个集成电路等;

存储器303可能包含高速RAM存储器,也可能还包括非易失性存储器(non-volatile memory)等,例如至少一个磁盘存储器;

其中,存储器303存储有程序,处理器301可调用存储器403存储的程序,所述程序用于:

扫描业务代码,从业务代码中确定目标对象,目标对象为待进行幂等操作的对象,目标对象标注有注解;

为目标对象加锁,并执行目标对象;

在目标对象执行完后,将加在目标对象上的锁释放。

可选的,所述程序的细化功能和扩展功能可参照上文描述。

本申请实施例还提供一种可读存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时,实现如上述实现业务幂等的方法。

可选的,所述程序的细化功能和扩展功能可参照上文描述。

最后,还需要说明的是,在本文中,诸如和第二等之类的关系术语仅仅用来将一个实体或者操作与另一个实体或操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。而且,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、物品或者设备中还存在另外的相同要素。

本说明书中各个实施例采用递进的方式描述,每个实施例重点说明的都是与其他实施例的不同之处,各个实施例之间相同相似部分互相参见即可。

对所公开的实施例的上述说明,使本领域专业技术人员能够实现或使用本申请。对这些实施例的多种修改对本领域的专业技术人员来说将是显而易见的,本文中所定义的一般原理可以在不脱离本申请的精神或范围的情况下,在其它实施例中实现。因此,本申请将不会被限制于本文所示的这些实施例,而是要符合与本文所公开的原理和新颖特点相一致的最宽的范围。

13页详细技术资料下载
上一篇:一种医用注射器针头装配设备
下一篇:一种立即数转移指令的执行方法、装置及介质

网友询问留言

已有0条留言

还没有人留言评论。精彩留言会获得点赞!

精彩留言,会给你点赞!