具体实施方式
为了使本技术领域的人员更好地理解本申请中的技术方案,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都应当属于本申请保护的范围。
为了使本技术领域的人员更好地理解本申请中的技术方案,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都应当属于本申请保护的范围。
图1是本申请所述一种业务处理方法一个实施例的方法流程图。虽然本申请提供了如下述实施例或附图所示的方法操作步骤或装置结构,但基于常规或者无需创造性的劳动在所述方法或装置中可以包括更多或者更少的操作步骤或模块单元。在逻辑性上不存在必要因果关系的步骤或结构中,这些步骤的执行顺序或装置的模块结构不限于本申请实施例描述及附图所示的执行顺序或模块结构。所述的方法或模块结构的在实际中的装置或终端产品应用时,可以按照实施例或者附图所示的方法或模块结构连接进行顺序执行或者并行执行(例如并行处理器或者多线程处理的环境,甚至分布式处理环境)。
具体的如图1所述,本申请一种实施例提供的一种业务处理方法可以包括:
S101:确定进程请求的行级锁是否处于可分配状态;
基于数据库的分布式锁方案,是完全基于数据库的悲观锁实现,即,数据库连接会在整个业务方法执行周期内一直被保持,那么,如果需要处理的业务用时比较长,数据库连接就会长时间被占用,在高并发的场景下,数据库连接就存在被用光的风险。
对于页级锁和行级锁而言,是不存在被用光的风险的,但是行级锁,被用光的可能性就很高,所谓行级锁就是仅对指定的记录进行加锁,在这种情况下,其它进程还是可以对同一个表中的其它记录进行操作的,仅是不可以对使用了行级锁的记录进行操作。即,行级锁是是排它锁,被锁定行不可进行修改,删除。
因此,锁存在一个被占用和未被占用的情况,对于进程而言,可以申请未被占用的行级锁,但是不能申请被占用的行级锁。
在一个实施方式中,为了确定当前进程所请求的行级锁是否可以被请求,可以采用行级锁状态表的方式记录每个行级锁的状态,该行级锁状态表可以采用表格的形式,也可以采用一条条记录的形式,如果是表格的形式,可以每一行记录一个行级锁的占用情况,如果是一条条记录的形式,可以每一条记录中记录有该行级。
即,可以从预先建立的行级锁状态表中查找所述进程请求的行级锁是否处于可分配状态;相应的,设置所述进程请求的行级锁为锁定状态的过程还可以包括:在所述预先建立的行级锁状态表中,将所述进程请求的行级锁的状态设置为锁定状态。即,实时更新行级锁状态表中各个行级锁的状态信息,以便新的进程请求的时候,可以获得较为准确的行级锁的状态信息。
考虑到在实现的时候,虽然控制进程在一拿到行级锁就立马释放掉这个行悲观锁的数据库连接,即,一拿到锁就释放该锁,但是毕竟是存在时差的,难免会有小机率发生数据库行悲观锁冲突的情况。为了减少这种冲突的影响,可以先确定在预先建立的行级锁状态表中,是否存在进程请求的行级锁的记录;如果存在,则确定是否可获取所述进程请求的行级锁,如果没有获取到进程请求的行级锁,那么就表明当前存在小概率的冲突,该锁正被占用,那么就可以确定该进程请求的行级锁处于不可分配的状态,如果可以获取,那么可以根据进程请求的行级锁在所述行级锁状态表中的记录,确定所述进程请求的行级锁是否处于可分配状态。例如,可以通过该行级锁在预先建立的行级锁状态表中对应的行内容里的locked flag字段来确定该锁当前是否被持有(N标识未被持有,Y标识被持有),从而确定进程请求的行级锁是否处于可分配状态。
举例而言,对于每个行级锁而言,可以设置一个唯一性标识(lock_key)用于唯一标识一个行级锁,通过一个状态标识(locked_flag)来标识该行级锁是否被某个进程持有。每个行级锁对应一个行记录,通过对行记录的查找,可以实现对锁状态的判断。
在一个实施方式中,考虑到有时会出现一个行级锁被一个应用长期占用,而导致死锁情况的发生,为了解决这种问题,在本例中,设置了一个锁失效时间,也可以称之为分配时长,即,每次在进程请求到行级锁的时候,都为该进程分配一个该锁的可持有时间,过了这个时间之后,如果进程仍未释放该行级锁,那么就设定该锁自动被释放。
可以在上述行级锁状态表中增加一个失效时间字段(lock_expire)用于标识该行级别锁的失效时间。
例如,可以如下表1所示:
表1
Lock_key |
Locked_flag |
lock_expire |
Lock1 |
Y |
20s |
Lock2 |
Y |
5s |
Lock3 |
N |
|
即,通过如上表1所示的行级锁状态表,可以确定出当前进程所请求的行级锁是否处于可分配状态,首选,可以根据进程请求的行级锁在行级锁状态表中的记录,确定进程请求的行级锁是否处于被持有状态;如果不处于被持有状态,则确定所述进程请求的行级锁处于可分配状态。如果处于被持有状态,则确定进程请求的行级锁是否已超出分配时长;如果超出,则确定所述进程请求的行级所处于可分配状态。
为了使得为进程分配的行级锁的失效时间是合理的,可以灵活分配失效时间,例如分配时长可以是按照请求的进程所对应的业务的需求确定的,这样只需要根据进程所要执行的业务的时间需要确定失效时长就可以,使得设置的失效时间灵活且合理。
S102:如果处于可分配状态,则将所述被请求的行级锁分配给所述进程;
通过上述的进程请求的行级锁的状态的确定,如果最终确定是可以分配的,那么就可以将该请求的行级锁分配给该进程。
同时,可以根据该进程所执行的业务的情况,为该行级锁分配一个失效时间,该失效时间,该失效时间可以是按照一个时长方式分配的,也可以是按照当前时间加上业务上认为该锁要保持的最长时间作为失效时间,即,达到该失效时间点,无论进程有没有主动释放该行级锁,都自动释放该行级锁。在实现的时候,可以采用设置时间周期,加上计时器的方式设置失效时间,也可以采用上述当前时间加上业务所需时长的方式,确定一个时间点的方式设置失效时间,具体采用那种方式可以根据实际需要和情况选取,本申请对此不作限定。
举例而言,当前时间为:10:46:10,业务执行所需的时间为1分10秒,那么可以设置失效时间为:10:47:20,即,到10:47:20这个时间点,锁就自动被释放,也可以从当前时间点,开启计时器,当计时器达到1分10秒的时候,锁自动被释放。
以上所列举的仅是一种示意性描述,在实际实现的时候,可以采用其它方式设置,本申请对此不作具体限定。
S103:设置所述被请求的行级锁为锁定状态,并释放数据库与所述进程之间的数据库连接;
在将进程请求的行级锁分配给进程之后,就可以将该进程请求的行级锁设置为锁定状态,例如,可以在上述的行级锁状态表中将该行级锁对应的行内容的持有状态(Locked_flag)设置为Y,即表明该行级锁已经被持有。
在设定为锁定状态之后,就随即释放数据库连接,将数据库连接的释放提前至业务处理之前。
S104:控制所述进程进行业务处理。
即,在分配了行级锁,完成数据库事务之后,就释放数据库连接,然后再开始长业务方案的处理。在业务方案执行完成之后,控制所述进程释放所述进程请求的行级锁,并将所述进程请求的行级锁的状态设置为可分配状态。即,可以将上述行级锁状态表中将该行级锁对应的行内容的持有状态(Locked_flag)设置为N,以释放该行级锁。
在上例中,主要是为了解决现有的基于数据库的分布式锁方案,是完全基于数据库的悲观锁实现,数据库连接会在整个业务方法执行周期内一直被保持。如果需要处理的业务用时较长,那么数据库连接会长时间被占用,在高并发场景下,数据库连接有被用光的危险的问题,在本例中,在获得数据库行级锁后,立即更改状态字段为已锁定,然后立刻释放数据库连接,避免了在整个业务方法执行周期内保持数据库连接。进一步的,还引入了锁超时机制,这样即使获得锁的进程在执行过程中崩溃,其它进程在锁超时后仍然可以重新获得锁。
下面结合一个具体实施例对上述业务处理方法进行说明,然而,值得注意的是,该具体实施例仅是为了更好地说明本申请,并不构成对本申请的不当限定。
在本例中,考虑到现有的通过数据库悲观锁长时间占用数据库连接来实现分布式锁,虽然实现方式简单,但是会在整个业务方法执行周期内占用数据库连接,本例为了解决数据库连接被长时间占用的问题,将数据库的连接释放时间点从业务结束后提前至业务开始阶段,并引入了锁超时机制,避免了死锁的发生。
首先,可以预先建立一个专用于锁定的通用表t_lock,即,上述的行级锁状态表,该表主要可以如下表2所示,包括以下几个字段:
表2
字段名 |
字段类型 |
描述 |
Lock_key |
Varchar2(100) |
锁的key值,唯一性索引 |
Locked_flag |
Varchar2(1) |
锁定标识位,其中,Y标识已锁定,N标识未锁定 |
lock_expire_date |
Timestamp |
锁失效时间,该时间后,锁自动失效 |
具体地,如图2所示,该业务处理方法可以按照如下包括以下步骤:
S1:开启数据库事务;
S2:以nowait的方式试图获得数据库行级悲观锁;
S3:如果行不存在,则先插入一条记录,记录该行级锁的状态,在插入的时候考虑到会出现多个进程请求一个锁的情况,在这种情况下插入时,可以忽略唯一性索引异常;
S4:如果无法获得数据库行级悲观锁,那么说明另一进程正占用,因此,可以终止处理。
即,数据库的行悲观锁被占用,虽然一拿到行锁马上就会释放掉这个行悲观锁,但并发时仍然有小机率发生数据库行悲观锁冲突,该步骤主要是为了处理这种冲突。
S5:如果获得数据库行级悲观锁,那么检查该行级锁对应的行内容;
具体地,如果locked_flag为Y并且当前时间小于等于lock_expire_date,则表明该锁正被另一进程持有,因此,终止处理。
如果locked_flag为N(表明锁未被别的进程持有)或者lock_flag为Y但当前时间已经大于lock_expire_date(表明持有该lock_key的别的进程已意外崩溃),那么可以立刻更新locked_flag为Y,lock_expire_date为当前时间加上业务上认为该锁要保持的最长时间。
S6:结束数据库事务,释放数据库连接;
S7:开始长业务方案处理;
S8:业务方案执行完后,更新locked_flag=N,释放锁。
图3示出了根据本申请的一示例性实施例的基于服务器或者终端的电子设备的示意结构图。请参考图3,在硬件层面,该电子设备包括处理器、内部总线、网络接口、内存以及非易失性存储器,当然还可能包括其他业务所需要的硬件。处理器从非易失性存储器中读取对应的计算机程序到内存中然后运行,在逻辑层面上形成业务实现装置。当然,除了软件实现方式之外,本申请并不排除其他实现方式,比如逻辑器件抑或软硬件结合的方式等等,也就是说以下处理流程的执行主体并不限定于各个逻辑单元,也可以是硬件或逻辑器件。
请参考图4,在软件实施方式中,该业务处理装置应用于数据库服务器中,也可以应用终端中,可以包括:确定模块、分配模块、释放模块和控制模块。其中:
确定模块,用于确定进程请求的行级锁是否处于可分配状态;
分配模块,用于在确定处于可分配状态的情况下,将所述被请求的行级锁分配给所述进程;
释放模块,用于设置所述被请求的行级锁为锁定状态,并释放数据库与所述进程之间的数据库连接;
控制模块,用于控制所述进程进行业务处理。
可选的,确定模块具体可以用于从预先建立的行级锁状态表中查找所述进程请求的行级锁是否处于可分配状态;相应的,释放模块还可以用于在所述预先建立的行级锁状态表中,将所述进程请求的行级锁的状态设置为锁定状态。
可选的,确定模块可以包括:第一确定单元,用于确定在所述预先建立的行级锁状态表中,是否存在所述进程请求的行级锁的记录;第二确定单元,用于在确定存在的情况下,确定是否可获取所述进程请求的行级锁;第三确定单元,用于在确定可以获取的情况下,根据所述进程请求的行级锁在所述行级锁状态表中的记录,确定所述进程请求的行级锁是否处于可分配状态。
可选的,第三确定单元可以包括:第一确定子单元,用于根据所述进程请求的行级锁在所述行级锁状态表中的记录,确定所述进程请求的行级锁是否处于被持有状态;第二确定子单元,用于在确定处于被持有状态的情况下,确定所述进程请求的行级锁是否已超出分配时长;第三确定子单元,用于在确定超出的情况下,确定所述进程请求的行级所处于可分配状态。
可选的,上述分配时长可以是按照请求的进程所对应的业务的需求确定的。
可选的,第三确定单元还可以包括:第四确定子单元,用于在确定不处于被持有状态的情况下,确定所述进程请求的行级锁处于可分配状态。
可选的,控制模块还可以用于在控制所述进程进行业务处理之后,控制所述进程释放所述进程请求的行级锁,并将所述进程请求的行级锁的状态设置为可分配状态。
本申请提供的业务处理方法和装置,采用了在为进程分配行级锁之后就随即释放数据库连接,将数据库连接的释放操作放在业务处理之前,而不是放在业务处理之后。利用本申请实施方案,使得数据库连接不会长时间被占用了,从而避免了数据库连接被用光的问题的产生。
在20世纪90年代,对于一个技术的改进可以很明显地区分是硬件上的改进(例如,对二极管、晶体管、开关等电路结构的改进)还是软件上的改进(对于方法流程的改进)。然而,随着技术的发展,当今的很多方法流程的改进已经可以视为硬件电路结构的直接改进。设计人员几乎都通过将改进的方法流程编程到硬件电路中来得到相应的硬件电路结构。因此,不能说一个方法流程的改进就不能用硬件实体模块来实现。例如,可编程逻辑器件(Programmable Logic Device,PLD)(例如现场可编程门阵列(Field Programmable GateArray,FPGA))就是这样一种集成电路,其逻辑功能由用户对器件编程来确定。由设计人员自行编程来把一个数字系统“集成”在一片PLD上,而不需要请芯片制造厂商来设计和制作专用的集成电路芯片。而且,如今,取代手工地制作集成电路芯片,这种编程也多半改用“逻辑编译器(logic compiler)”软件来实现,它与程序开发撰写时所用的软件编译器相类似,而要编译之前的原始代码也得用特定的编程语言来撰写,此称之为硬件描述语言(Hardware Description Language,HDL),而HDL也并非仅有一种,而是有许多种,如ABEL(Advanced Boolean Expression Language)、AHDL(Altera Hardware DescriptionLanguage)、Confluence、CUPL(Cornell University Programming Language)、HDCal、JHDL(Java Hardware Description Language)、Lava、Lola、MyHDL、PALASM、RHDL(RubyHardware Description Language)等,目前最普遍使用的是VHDL(Very-High-SpeedIntegrated Circuit Hardware Description Language)与Verilog。本领域技术人员也应该清楚,只需要将方法流程用上述几种硬件描述语言稍作逻辑编程并编程到集成电路中,就可以很容易得到实现该逻辑方法流程的硬件电路。
上述的业务处理方法和装置可以按任何适当的方式实现,例如,可以采取例如微处理器或处理器以及存储可由该(微)处理器执行的计算机可读程序代码(例如软件或固件)的计算机可读介质、逻辑门、开关、专用集成电路(Application Specific IntegratedCircuit,ASIC)、可编程逻辑控制器和嵌入微控制器的形式,进行业务处理的主体可以是控制器,该控制器可以包括但不限于以下微控制器:ARC 625D、Atmel AT91SAM、MicrochipPIC18F26K20以及Silicone Labs C8051F320,存储器控制器还可以被实现为存储器的控制逻辑的一部分。本领域技术人员也知道,除了以纯计算机可读程序代码方式实现控制器以外,完全可以通过将方法步骤进行逻辑编程来使得控制器以逻辑门、开关、专用集成电路、可编程逻辑控制器和嵌入微控制器等的形式来实现相同功能。因此这种控制器可以被认为是一种硬件部件,而对其内包括的用于实现各种功能的装置也可以视为硬件部件内的结构。或者甚至,可以将用于实现各种功能的装置视为既可以是实现方法的软件模块又可以是硬件部件内的结构。
上述实施例阐明的装置,具体可以由计算机芯片或实体实现,或者由具有某种功能的产品来实现。一种典型的实现设备为计算机。具体的,计算机例如可以为个人计算机、膝上型计算机、蜂窝电话、相机电话、智能电话、个人数字助理、媒体播放器、导航设备、电子邮件设备、游戏控制台、平板计算机、可穿戴设备或者这些设备中的任何设备的组合。
为了描述的方便,描述以上装置时以功能分为各种单元分别描述。当然,在实施本申请时可以把各单元的功能在同一个或多个软件和/或硬件中实现。
本领域内的技术人员应明白,本申请的实施例可提供为方法、系统、或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本申请是参照根据本申请实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。
内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。
计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD-ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁带磁磁盘存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体(transitory media),如调制的数据信号和载波。
还需要说明的是,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、商品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、商品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、商品或者设备中还存在另外的相同要素。
本领域技术人员应明白,本申请的实施例可提供为方法、系统或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本申请可以在由计算机执行的计算机可执行指令的一般上下文中描述,例如程序模块。一般地,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程序、对象、组件、数据结构等等。也可以在分布式计算环境中实践本申请,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括存储设备在内的本地和远程计算机存储介质中。
本说明书中的各个实施例均采用递进的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于系统实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。
以上所述仅为本申请的实施例而已,并不用于限制本申请。对于本领域技术人员来说,本申请可以有各种更改和变化。凡在本申请的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在本申请的权利要求范围之内。