首页> 中国专利> 分布式系统及分布式系统中目标对象的调度方法

分布式系统及分布式系统中目标对象的调度方法

摘要

本发明公开了一种分布式系统及分布式系统中目标对象的调度方法。该调度方法包括:创建对应于目标对象的锁资源对象,锁资源对象包括与目标对象相关的锁信息;响应于接收到特定线程发送的锁请求,根据锁请求所针对的目标对象的锁资源对象的锁信息,判断特定线程当前是否能够获取目标对象所对应的锁。由此,可以将分布式环境下的不同特定线程的锁请求映射为同一JVM管理下的锁请求,从而可以统一管理调度分布式环境下的多个锁请求。

著录项

  • 公开/公告号CN106790694A

    专利类型发明专利

  • 公开/公告日2017-05-31

    原文格式PDF

  • 申请/专利权人 广州爱九游信息技术有限公司;

    申请/专利号CN201710092178.7

  • 发明设计人 吴彰合;

    申请日2017-02-21

  • 分类号H04L29/08(20060101);

  • 代理机构11452 北京展翼知识产权代理事务所(特殊普通合伙);

  • 代理人屠长存

  • 地址 510665 广东省广州市天河区黄埔大道西平云路163号广电平云广场B塔13楼自编02单元

  • 入库时间 2023-06-19 02:20:31

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2020-08-28

    专利权的转移 IPC(主分类):H04L29/08 登记生效日:20200807 变更前: 变更后: 申请日:20170221

    专利申请权、专利权的转移

  • 2020-04-14

    授权

    授权

  • 2017-06-23

    实质审查的生效 IPC(主分类):H04L29/08 申请日:20170221

    实质审查的生效

  • 2017-05-31

    公开

    公开

说明书

技术领域

本发明涉及分布式技术领域,特别是涉及一种分布式系统及分布式系统中目标对象的调度方法。

背景技术

分布式锁是实现分布式环境下同步访问共享资源的一种方式。如果不同的分布式系统或是同一分布式系统下的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,需要采取一定的措施防止彼此干扰以保证访问的一致性,在这种情况下,便需要使用到分布式锁。

现有的分布式锁的实现方案大多是简单地锁定一个服务标志(通常用一个字符串代表一个服务处理),在锁定该服务标志期间,分布式环境中的其他逻辑在试图锁定同一个服务标志时将被阻塞,直到最早锁定了该服务标志的线程释放了锁,才有机会进入锁。

该方案存在如下问题:1)都是排他性锁,使用该类锁时服务吞吐率低;2)不支持锁可重入,影响业务代码的设计结构,让代码不能更优雅更灵活地规划;3)未能系统性地识别和处理集群中锁定了某些服务标志的机器单点故障超时等问题,集群中单台机器有问题就能很轻易地影响其他的机器,可靠性,健壮性差;4)不能有效、及时地识别死锁,业务代码的不安全性增加,排查问题困难。

由此,需要一种新的分布式环境下的锁的调度方案以解决上述至少一项问题。

发明内容

本发明主要的目的在于提供一种分布式系统及分布式系统中目标对象的调度方法,以解决上述至少一项问题。

根据本发明的一个方面,提供了一种分布式系统中目标对象的调度方法,包括:创建对应于目标对象的锁资源对象,锁资源对象包括与目标对象相关的锁信息;响应于接收到特定线程发送的锁请求,根据锁请求所针对的目标对象的锁资源对象的锁信息,判断特定线程当前是否能够获取目标对象所对应的锁。

由此,可以将分布式环境下的不同特定线程的锁请求映射为同一JVM管理下的锁请求,从而可以统一管理调度分布式环境下的多个锁请求。

优选地,锁信息可以包括:目标对象的对象ID、持有目标对象的第一线程、第一线程持有的针对目标对象的锁的类型和时间,并且/或者锁请求可以包括:该锁请求所针对的目标对象的对象ID、请求的锁的类型、请求时间。

优选地,锁信息还可以包括:等待目标对象的第二线程、第二线程所请求的针对目标对象的锁的类型和时间。

优选地,判断特定线程当前是否能够获取目标对象所对应的锁的步骤可以包括:对锁请求所对应的锁资源对象进行加锁;进入临界区以访问锁资源对象,并根据锁信息以及预定的锁争用逻辑,判断特定线程当前能否获取锁。

由此,对于特定线程的锁请求,可以对锁请求所对应的锁资源对象加锁,利用锁资源对象的临界区,来判断当前是否允许其获取锁请求所针对的目标对象。

优选地,预定的锁争用逻辑可以包括:允许多个不同线程在同一时间针对同一目标对象分别获取读锁;在一个线程持有针对一个目标对象的写锁的情况下,任何其它线程不能持有针对一个目标对象的读锁和写锁。由此预定的锁争用逻辑可以是模拟JVM线程锁争用逻辑。

优选地,该调度方法还可以包括:在判定特定线程当前不能获取锁的情况下,退出临界区,并在锁资源对象中记录该锁请求;以及/或者在判定特定线程当前能够获取锁的情况下,在锁资源对象中记录该特定线程获取的锁的类型和时间,并退出临界区。

由此,为了提升锁请求的处理效率,可以在进入锁资源对象的临界区后仅执行必要的处理操作,非必要的操作可以在退出临界区后执行。

优选地,在判定特定线程不能获取锁的情况下退出临界区并在锁资源对象中记录该锁请求可以包括:在退出临界区后等待锁的释放;在等待超过预定时间后锁仍未释放时,建立新线程继续等待锁的释放,并将锁请求的等待消息缓存到锁资源对象中。

由此,可以基于建立的新线程及时识别锁的被释放信息,以便让相应的线程及时获得锁。

优选地,该调度方法还可以包括:在判定特定线程当前不能获取目标对象的锁时,向特定线程发送锁等待消息,以便特定线程开启自旋等待模式,以等待锁;以及/或者在判定特定线程当前能够获取目标对象的锁时,向特定线程发送锁,以便特定线程执行后续业务逻辑的处理。

优选地,该调度方法还可以包括:清理锁资源对象中无效的锁信息;以及/或者将强制中断的锁信息和/或标记为无效的锁信息告知客户端。

由此,可以对锁资源对象中的锁数据进行维护,使得其中存储的锁数据均为有效数据,以避免分布式环境下的各种异常和故障对调度造成的影响。

优选地,该调度方法还可以包括:记录接收到的锁请求所针对的目标对象及发送该锁请求的特定线程;在接收到的锁请求所对应的特定线程与之前记录的特定线程为同一线程且所针对的目标对象与之前记录的特定线程所对应的锁请求所针对的目标对象相同时,允许该特定线程获取所请求的目标对象的锁。

由此,在某个线程获取针对目标对象的锁后,再次发出针对该目标对象的锁时可以允许其直接获取所请求的锁,即本发明还支持重入锁请求。

优选地,可以根据特定线程发送锁请求时的机器IP和/或应用端口和/或特定线程ID,记录发送该锁请求的特定线程。

优选地,该调度方法还可以包括:基于分布式系统中锁资源对象中的锁信息,判断锁请求是否会造成死锁;在判定锁请求会造成死锁时,判定特定线程当前不能获取锁。

优选地,判断锁请求是否会造成死锁的步骤可以包括:以线程和目标对象为顶点,构造网状图,其中,线程和其持有的目标对象之间以第一连线连接,线程和其等待的目标对象之间以第二连线连接;在特定线程与其它线程和目标对象构成闭合环,闭合环中的第一连线和第二连线间隔出现的情况下,判定锁请求会造成死锁。

根据本发明的另一个方面,还提出了一种分布式系统,包括:调度节点和至少一个用于运行线程的业务节点,运行在业务节点上的线程能够通过业务节点向调度节点发送锁请求,响应于接收到特定线程发送的锁请求,调度节点能够根据锁请求所针对的目标对象的锁资源对象,判断特定线程当前是否能够获取目标对象所对应的锁,在锁请求所针对的目标对象的锁资源对象未建立的情况下,调度节点创建对应于目标对象的锁资源对象,锁资源对象包括与目标对象相关的锁信息。

优选地,锁信息可以包括:目标对象的对象ID、持有目标对象的第一线程、第一线程持有的针对目标对象的锁的类型和时间,并且/或者锁请求可以包括:对象ID、请求的锁的类型、请求时间。

优选地,锁信息还可以包括:等待目标对象的第二线程、第二线程所请求的针对目标对象的锁的类型和时间。

优选地,调度节点对锁请求所对应的锁资源对象进行加锁,进入临界区以访问锁资源对象,并根据锁信息以及预定的锁争用逻辑,判断特定线程当前能否获取锁。

优选地,预定的锁争用逻辑可以包括:允许多个不同线程在同一时间针对同一目标对象分别获取读锁;在一个线程持有针对一个目标对象的写锁的情况下,任何其它线程不能持有针对一个目标对象的读锁和写锁。

优选地,在判定特定线程当前不能获取锁的情况下,调度节点退出临界区,并在锁资源对象中记录该锁请求,并且/或者在判定特定线程当前能够获取锁的情况下,调度节点在锁资源对象中记录该特定线程获取的锁的类型和时间,并退出临界区。

优选地,调度节点在退出临界区后等待锁的释放,在等待超过预定时间后锁仍未释放时,调度节点建立新线程继续等待锁的释放,并将锁请求的等待消息缓存到锁资源对象中。

优选地,在判定特定线程当前不能获取目标对象的锁时,调度节点向特定线程发送锁等待消息,以便特定线程开启自旋等待模式,以等待锁;以及/或者在判定特定线程当前能够获取目标对象的锁时,调度节点向特定线程发送锁,以便特定线程执行后续业务逻辑的处理。

优选地,调度节点还可以基于分布式环境下所有的锁资源对象中的锁信息,判断锁请求是否会造成死锁,在判定锁请求会造成死锁时,调度节点判定特定线程当前不能获取锁。

优选地,调度节点可以以线程和目标对象为顶点,构造网状图,其中,线程和其持有的目标对象之间以第一连线连接,线程和其等待的目标对象之间以第二连线连接,在特定线程与其它线程和目标对象构成闭合环时,闭合环中的第一连线和第二连线间隔出现的情况下,调度节点判定锁请求会造成死锁。

优选地,发送锁请求的业务节点可以充当调度节点,所创建的锁资源对象保存在Redis数据库中。

本发明的分布式系统及分布式系统中目标对象的调度系统,通过建立分布式环境下的各个目标对象的锁资源对象,对于接收到的特定线程发送的锁请求,就可以根据锁请求所针对的目标对象的锁资源对象中的锁信息,来判断是否允许该特定线程获取对应于目标对象的锁。由此,利用本发明可以将分布式环境下的不同特定线程的锁请求映射为同一JVM管理下的锁请求,从而可以统一管理调度分布式环境下的多个锁请求。

附图说明

通过结合附图对本公开示例性实施方式进行更详细的描述,本公开的上述以及其它目的、特征和优势将变得更加明显,其中,在本公开示例性实施方式中,相同的参考标号通常代表相同部件。

图1示出了根据本发明一实施例的分布式系统中目标对象的调度方法的示意性流程图。

图2示出了根据锁资源对象判断特定线程当前能否获取目标对象所对应的锁的过程的流程图。

图3示出了能造成死锁的资源依赖路径图。

图4示出了根据本发明一实施例的分布式系统的功能框图。

图5示出了分布式系统中调度节点和业务节点的处理流程。

具体实施方式

下面将参照附图更详细地描述本公开的优选实施方式。虽然附图中显示了本公开的优选实施方式,然而应该理解,可以以各种形式实现本公开而不应被这里阐述的实施方式所限制。相反,提供这些实施方式是为了使本公开更加透彻和完整,并且能够将本公开的范围完整地传达给本领域的技术人员。

针对现有的分布式锁的实现方案存在的不足,本发明提出了一种新的分布式环境下的锁的调度方案。图1是示出了根据本发明一实施例的分布式系统中目标对象的调度方法的示意性流程图。本发明的调度方法可以由服务器端执行,方法中述及的目标对象可以是分布式环境下需要协调和/或同步的资源、操作等等。

参见图1,方法开始于步骤S110,创建对应于目标对象的锁资源对象,该锁资源对象包括与目标对象相关的锁信息。

创建锁资源对象的步骤可以是响应于接收到特定线程发送的锁请求而执行的,即可以创建锁请求所针对的目标对象的锁资源对象。其中,每个目标对象有且仅有一个对应的锁资源对象,因此在锁请求所针对的目标对象的锁资源对象已被创建的情况下,可以直接复用该锁资源对象,而无须再重建锁资源对象。

锁资源对象中记录有与目标对象相关的锁信息,例如可以是目标对象的对象ID、持有目标对象的线程及该线程持有的对应于目标对象的锁的类型(例如读锁、写锁)和时间、等待目标对象的线程及该线程所请求的对应于目标对象的锁的类型(例如读锁、写锁)和时间等等。其中,对象ID可以是预先设定的具有全局唯一性的ID,其可以用于指示其所对应的目标对象。

在步骤S120,响应于接收到特定线程发送的锁请求,根据锁请求所针对的目标对象的锁资源对象的锁信息,判断特定线程当前是否能够获取目标对象所对应的锁。

特定线程在发送锁请求时可以连同该锁请求所针对的目标对象的对象ID一并发送,以便于确定锁请求所针对的目标对象。因此,特定线程所发送的锁请求可以包括请求所针对的目标对象的对象ID、请求的锁的类型和请求时间等等。其中,本文述及的特定线程中的“特定”仅是为了便于描述,不应理解为对本发明的限制,可以由分布式系统中的用例运行本发明中的特定线程,运行特定线程的用例可以视为客户端。

综上,本发明通过建立分布式环境下的各个目标对象的锁资源对象,对于接收到的特定线程发送的锁请求,就可以根据锁请求所针对的目标对象的锁资源对象中的锁信息,来判断是否允许该特定线程获取对应于目标对象的锁。由此,利用本发明可以将分布式环境下的不同特定线程的锁请求映射为同一JVM管理下的锁请求,从而可以统一管理调度分布式环境下的多个锁请求。其中,由于本发明的调度方法的应用场景为分布式系统,因此可以优选地在同一时间仅处理一个锁请求,以避免同时处理多个锁请求而造成死锁的情况的发生。

下面就步骤S120中根据锁资源对象判断特定线程当前能否获取目标对象所对应的锁的过程做进一步详细说明。

参见图2,首先可以执行步骤S210,对锁请求所对应的锁资源对象进行加锁。例如,可以利用Java语言的关键字synchronized对目标对象加锁,即可以对锁资源对象加synchronized锁。

然后执行步骤S220,进入临界区以访问锁资源对象,并根据锁信息以及预定的锁争用逻辑,判断特定线程当前能否获取锁。由此,在处理锁请求时,可以对锁请求所针对的目标对象的锁资源对象加锁,然后进入锁资源对象的临界区来判断当前是否允许线程获取锁请求所针对的目标对象的锁。此处对锁资源对象加的锁一般为排斥锁,即在加锁期间,其它对应于该锁资源对象的锁请求不能获取该锁资源对象的锁,以访问该锁资源对象,这样可以避免同时处理多个对应于同一锁资源对象的锁请求的情况的发生,从而可以保证锁请求的处理逻辑不会出错。

本发明述及的锁争用逻辑可以是模拟JVM的线程锁争用逻辑。具体来说,本发明中锁请求所请求的锁可以分为读锁和写锁,持有读锁的线程仅对对应的目标对象进行读操作,持有写锁的线程则需要对对应的目标对象进行写操作。因此本发明述及的锁争用逻辑可以被设定为,允许多个不同线程在同一时间针对同一目标对象分别获取读锁;在一个线程持有针对某个目标对象的写锁的情况下,任何其它线程不能持有针对该目标对象的读锁和写锁。即同一目标对象同一时间可以被多个请求读锁的线程持有,但同一时间仅能被一个请求写锁的线程持有。

在判定特定线程当前不能获取目标对象的锁时,可以向特定线程发送锁等待消息,以便特定线程开启自旋等待模式,以等待锁的释放。在判定特定线程当前能够获取目标对象的锁时,可以向特定线程发送锁,使得特定线程可以持有目标对象,以执行后续业务逻辑的处理。

至此结合图1、图2对本发明的分布式系统中目标对象的调度方法的过程做了基本说明,下面对其中涉及的细节做进一步说明。

1、进入临界区的处理

为了提升锁请求的处理效率,在进入锁资源对象的临界区后可以优选地仅处理与当前锁请求相关的必要操作,该操作可以是耗时很短的操作,非必要的操作可以在退出临界区后另做处理。例如,在进入临界区后执行的操作可以包括:

(1)惰性清理与当前请求的目标对象相关的失效了的锁数据(可以称为触发式惰性清理),减少干扰。

此处,分布式系统中用于运行线程的实例可以周期性地发送运行在其上的线程有效信息,使得可以基于接收到的线程有效信息,清理锁资源对象中无效的锁信息。

(2)根据当前锁资源对象内部缓存的锁信息,计算能否立即获得请求锁。

在判定特定线程当前能够获取锁的情况下,可以在锁资源对象中记录该特定线程获取的锁的类型和时间,然后再退出临界区。

在进入临界区后判定特定线程当前不能获取锁的情况下,可以先退出临界区,然后在锁资源对象中记录该锁请求,即记录等待该目标对象的线程及该线程所请求的针对该目标对象的锁的类型和时间。具体地,可以在退出临界区后等待锁的释放,在等待超过预定时间后锁仍未释放时,可以建立新线程继续等待锁的释放,并将锁请求的等待消息缓存到锁资源对象中。

(3)获得当前整个集群中的锁信息快照,通过死锁算法检查当前锁请求是否会造成死锁。其中,死锁算法的具体判断原理将在下文进行详细说明,这里暂不赘述。

2、支持可重入锁请求

可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后,内层递归函数仍然有获取该锁的代码,但不受影响。例如,一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法,而无需重新获得锁。可重入锁最大的作用是避免死锁。

为了识别锁请求为重入锁请求,需要记录记录接收到的锁请求及其对应的特定线程。在本发明中,可以将特定线程发送锁请求时的机器IP和/或应用端口和/或特定线程ID作为特定线程标记,以此记录发送该锁请求的特定线程。另外,在记录接收到的锁请求的特定线程时,还可以根据发送锁请求的请求时间+特定线程标记来精确标记锁请求。

在识别接收到的锁请求为重入锁请求时,可以允许该锁请求所对应的特定线程获取所针对的目标对象的锁。具体地,在接收到的锁请求所对应的特定线程与之前记录的特定线程为同一线程且所针对的目标对象与之前记录的特定线程所对应的锁请求所针对的目标对象相同时,可以认为该锁请求即为重入锁请求,对于被认定为重入锁请求的锁请求,可以直接允许其获取所针对的目标对象的锁。

3、死锁识别算法

由于分布式环境下多个线程对不同目标对象的锁请求可能会造成死锁,因此在接收到特定线程发送的锁请求后,可以优先判断是否会造成死锁,如果判定会造成死锁,则可以抛出异常,并可以强迫该特定线程业务逻辑回退,释放已占有的部分资源锁。

简要来说,可以基于分布式环境下所有的锁资源对象中的锁信息,判断锁请求是否会造成死锁,在判定锁请求会造成死锁时,判定特定线程当前不能获取锁。

下面详细介绍下本发明的死锁检查算法的原理。图3示出了一种分布式环境下多个线程与对象之间的依赖关系图。图中的T1-T7代表线程,R1-R11代表对象,线程与对象之间的实箭头表示线程持有该对象,线程与对象之间的虚箭头表示线程等待该对象。

如图3所示,线程T1等待对象R5并持有对象R2,线程T2持有对象R5并等待对象R6,线程T4持有对象R6并等待对象R10,线程T6持有对象R10并等待对象R2。因此,线程T1→T2→T4→T6之间的依赖关系会造成死锁。本发明人经过观察分析后发现,如果网状图中实线和虚线之间间隔出现,并且最后能够产生一个闭合环,则该闭合环上的依赖关系必定会出现死锁。

由此,可以获取当前分布式环境下各个线程持有对象和等待对象的快照,并以线程和对象为顶点,构造线程和对象之间互相引用关系的网状图。其中,线程和其持有的目标对象之间可以用第一连线连接,线程和其等待的目标对象之间可以以第二连线连接,第一连线不同于第二连线。在某个线程与其它线程和目标对象构成闭合环,闭合环中的第一连线和第二连线间隔出现的情况下,可以判定该线程所对应的锁请求会造成死锁。

4、异常情况的处理

本发明的调度方法充分考虑了如下几种异常情况。

A.客户端发出了一个锁请求,但是获取服务器端的返回超时,其可能由于在服务器端产生一个失控的锁。

B.客户端成功申请到了一个锁,但是在后续进行业务代码的处理期间客户端与服务器端失联。

C.客户端申请到一个锁后,客户端因某种原因重启应用,此时客户端已占有的锁理应释放,不能干扰分布式系统中其他客户端上的线程获取该锁。

D.服务器端通过某种规则识别并标记了一个被废弃或者强制中断的锁,但是已经持有该锁的失联的客户端上的线程仍然在有效运行。

E.在一个有锁嵌套现象的代码结构中,外层资源锁如果出现了问题,服务器端要能识别并强制内层嵌套的锁相关请求也失效,要让嵌套类型的锁在逻辑上保持一致。

F.因为本发明支持嵌套锁的写法,多个线程对各种不同资源锁的请求可能会造成死锁,因此在服务器端在接收到客户端的锁请求之时优先检测是否会造成死锁,如果发现会造成死锁,则抛出异常,强迫锁客户端业务逻辑回退,释放已占有的部分资源锁。

对于异常情况A、B、C,可以通过建立客户端与服务器端之间的心跳机制来实现,例如,客户端可以周期性地向服务器端发送运行在其上的有效线程的线程信息,以使得服务器端可以基于接收到的线程信息识别出所建立的锁资源对象中的无效的锁信息。

对于异常情况D,服务器端可以将被判定为失效或强制终止的锁信息告知相应的客户端,由此能够让客户端上的线程感知到其持有的锁的变动并通过抛出相关异常,让客户端做出相应处理。

对于异常情况E,可以对获取的锁请求进行标记,以确定其属于哪个客户端下的哪个线程。例如,可以将特定线程发送锁请求时的机器IP和/或应用端口和/或特定线程ID作为特定线程标记,以此记录发送该锁请求的特定线程。另外,在记录接收到的锁请求的特定线程时,还可以根据发送锁请求的请求时间+特定线程标记来精确标记锁请求。

对于异常情况F,可以由上文述及的死锁识别算法解决,这里不再赘述。

至此,结合图1至图3对本发明的分布式系统中目标对象的调度方法做了详细说明。另外,本发明还提出了一种分布式系统,图4是示出了根据本发明一实施例的分布式系统400的功能框图。

如图4所示,分布式系统400包括调度节点410和一个或多个用于运行线程的业务节点420,调度节点410和业务节点420均可以部署在分布式集群中的机器上。其中,可以在一台独立的机器上单独部署调度节点410,在分布式集群中其它机器上部署业务节点420,此时部署有业务节点420的机器可以视为客户端,部署有调度节点410的机器可以视为服务器端。服务器端(即调度节点410)可以接收并处理各个客户端(即业务节点420)发送的锁请求。

本发明的调度节点410和业务节点420可以被配置为,运行在业务节点420上的线程能够向调度节点410发送锁请求。响应于接收到特定线程发送的锁请求,调度节点410可以根据锁请求所对应的目标对象的锁资源对象,判断特定线程当前是否能够获取目标对象所对应的锁。其中,在锁请求所针对的目标对象的锁资源对象未建立的情况下,调度节点410还可以创建对应于目标对象的锁资源对象。

下面结合图5就本发明的分布式系统400中调度节点410和业务节点420可以执行的操作进行说明,其中,调度节点410可以执行的具体操作可以参见上文结合图1至图3所述内容,即本发明的调度节点410可以执行上文述及的目标对象的调度方法,因此这里仅结合图5对调度节点410和业务节点420调度目标对象的过程做简要说明,对于其中涉及的细节部分均可以参见上文相关说明。

如图5所示,业务节点420可以视为锁客户端,调度节点410可以视为锁服务器端。锁客户端对外仅提供了两个接口:通过锁客户端申请锁、通过锁客户端释放锁。

为了处理各种异常情况,保证锁数据的一致性和正确性,在锁客户端和锁服务器端还具有很多内部的交互逻辑,不过这些交互处理对锁使用者来说都是透明的,后面在合适位置会介绍其中关键的逻辑。下面结合图5对锁客户端和锁服务器端的处理流程进行说明。

参见图5,首先,用户可以通过锁客户端提供的申请锁API,申请指定目标对象的读/写锁,此时锁客户端会对该锁请求进行相关的包装处理,然后向锁服务端发送锁请求。例如,锁客户端会将请求的目标对象的对象ID、请求的锁的类型及请求时间包装在锁请求中,发送给锁服务器端。

锁服务器端接收到锁请求后,可以申请一个公共对象的锁(也就是图5中标出的全局锁),进入该公共对象的临界区后,这意味着在同一时刻,在整个分布式环境中只处理当前锁请求。为了提升锁服务器的吞吐量,在这个全局锁的临界区内可以优选地只处理锁当前锁请求的必要部分的逻辑,而且是耗时很短的逻辑,非必要部分的逻辑可以在退出全局锁临界区后另做处理。

如图5所示,在全局锁的临界区主要做的事情包括:创建/复用与资源ID相关的锁资源对象;惰性清理与当前请求的锁资源相关的失效了的锁数据,减少干扰(触发式惰性清理);根据当前锁资源对象内部缓存的锁信息,计算能否立即获得请求锁(如能,立即返回);获得当前整个集群中的锁信息快照,通过死锁算法检查当前锁请求会否造成死锁。

如果锁服务器端识别当前锁请求为重入锁,或者计算得到当前锁请求能够立即获得锁,则可以立即返回申请锁成功信息,并将锁信息缓存到锁资源对象的内部数据结构中。如果通过计算发现当前锁请求因各种关联原因被强制中断,则可以抛出强制中断异常。

如果发现当前锁请求不能立即获得锁,可以首先在3秒钟内尝试同步等待该锁(此时已经退出了上面提到的全局锁的临界区),如果超过3秒仍未能争取到锁,则创建一个新线程继续等待,同时当前主线程返回锁等待标志给客户端,并将锁等待信息缓存到锁资源对象的内部数据结构中。

锁客户端如果得到锁请求返回结果为得到锁,则相应地继续进行后续业务逻辑的处理。如果发现锁服务端抛出异常,则锁客户端也抛出锁请求失败异常。如果得到等待锁标志,则实现相关的自旋等待逻辑(这个对锁使用者透明),锁服务器端发现当前锁客户端线程获得锁后会通过回调终结该自旋等待。

某个锁客户端线程释放了某个对象的锁时,会唤醒锁服务器端的其他相关的锁等待线程,等待该对象的锁的线程被唤醒后会继续尝试占有该对象的锁。具体地,首先进入锁资源对象的临界区,然后通过该锁资源对象内部缓存的各个线程的锁持有、锁等待信息,计算当前锁请求能否获得锁,此处可以模拟JVM自身的线程锁临界区、锁等待的处理逻辑进行计算,在计算了得到结果后很快退出当前锁资源对象的临界区,不会阻塞其他相关的锁等待线程。如果某个处于动态锁等待的线程最终获得了目标对象的锁时,会回调锁客户端,告知其请求的某个线程得到了锁,终结客户端的自旋等待;服务端被唤醒的锁等待线程通过计算仍然无法获得锁,则继续等待。

为了识别和处理异常情况下产生的锁数据,防止这些垃圾数据干扰正常的锁调度,在锁客户端和锁服务器端都有相关的线程定时检查缓存的锁信息,并清理一些过期的数据;其中锁客户端有个线程定时同步本地有效的线程信息到锁服务器端,锁服务器端以此数据为基准清理掉锁服务器端无效的锁信息,并将在锁服务器端强制中断的锁信息告知锁客户端,影响锁客户端的锁处理流程。

锁服务器端还可以设有回调重试线程,用于解决因网络异常而导致的锁服务器端回调锁客户端失败的情况。

利用本发明的分布式系统,可以在项目任何需要进行同步处理的位置申请针对目标对象的锁,这样分布式环境中其他也申请针对同一目标对象的锁的线程将在此处进行同步。本发明在某种程度上可以取代memcache机制的全局锁,而且它的功能更强大,可以支持锁读写分离、锁可重入、智能识别死锁、锁嵌套等功能,使得可以以更灵活的方式设计业务代码的结构,而且吞吐量比memcache机制的全局锁更高。

在本发明的分布式系统中,锁客户端和锁服务器端可以是通过HTTP协议进行通信的,但这种通信方式使得通信耗时较长,而且在HTTP协议模式下,锁客户端和锁服务器端之间短连接通信模式在处理网络异常导致的异常的锁数据时需要更复杂的逻辑。并且,图4所示的分布式系统只支持一个锁服务器端进行资源锁的调度,扩展性较差。

本发明人在深入研究后发现,可以通过引入Redis数据库来重新架构本发明的分布式系统,此时不再做调度节点和业务节点的划分。分布式系统中每个发起锁请求的机器可以既是调度节点,也是业务节点,即业务节点可以充当调度节点,所创建的锁资源对象可以存储在分布式的Redis数据库中。

具体地,调度节点和业务节点之间的通信可以调整为通过识别Redis数据库中约定关键字值的变更,使用Redis机制下的简单的全局锁功能模拟JVM的synchronized功能,集群中某个服务导致的锁状态变更可以通过广播(例如可以使用Netty)和单机服务内部利用wait+notify以及loop轮询机制,确保集群中任一应用更改了锁的状态,能够唤醒其他机器及时作出应对,达到单JVM中wait+notify的效果。

由此,利用Redis(主从备份)+Netty(通信),可以解决图4所示的分布式系统扩展性的问题,而且在集群机器单点故障、网络异常处理、同步锁信息的处理方面可以有更简约有效的代码设计。

综上,本发明能够在分布式环境中进行锁的管理和调度,从而支持同步和协调分布式环境下有依赖或关联关系的服务,本发明支持的锁功能如下:

A.能够识别客户端同一线程下的多次锁请求为同一个客户端线程。

B.支持对同一对象加读锁或写锁,读写锁分离;针对同一资源的读锁线程可以并发运行,不同客户端线程间的读、写锁互斥。

C.支持可重入锁请求,对于识别为同一客户端线程的锁请求,支持锁重入。

D.在接收到客户端的锁请求时,能够通过死锁识别算法及时有效地检查是否会导致死锁,如果会产生死锁,则立即抛出异常。

E.客户端申请目标对象的锁时,如果发现该目标对象已被其他客户端线程持有,能让当前锁请求阻塞等待。被等待的目标对象被其他线程释放了锁后,服务器能及时识别并能模拟单JVM内置的锁调度功能选中一个等待的客户端线程,及时让该等待的锁客户端线程获得锁并停止等待。

F.本发明尽量考虑了分布式环境下的各种异常和故障对锁协调调度的影响,能有效解决的部分将通过一些识别和弥补逻辑让锁相关数据保持一致和正确,难以有效解决的部分则平滑失败,尽量减少分布式锁使用的复杂性,优先保证锁服务的正确性。

E.本发明对外提供简单明确的接口以供使用,封装了锁调度的复杂逻辑。

上文中已经参考附图详细描述了根据本发明的分布式系统及分布式系统中目标对象的调度系统。

此外,根据本发明的方法还可以实现为一种计算机程序,该计算机程序包括用于执行本发明的上述方法中限定的上述各步骤的计算机程序代码指令。或者,根据本发明的方法还可以实现为一种计算机程序产品,该计算机程序产品包括计算机可读介质,在该计算机可读介质上存储有用于执行本发明的上述方法中限定的上述功能的计算机程序。本领域技术人员还将明白的是,结合这里的公开所描述的各种示例性逻辑块、模块、电路和算法步骤可以被实现为电子硬件、计算机软件或两者的组合。

附图中的流程图和框图显示了根据本发明的多个实施例的系统和方法的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段或代码的一部分,所述模块、程序段或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标记的功能也可以以不同于附图中所标记的顺序发生。例如,两个连续的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。

以上已经描述了本发明的各实施例,上述说明是示例性的,并非穷尽性的,并且也不限于所披露的各实施例。在不偏离所说明的各实施例的范围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更都是显而易见的。本文中所用术语的选择,旨在最好地解释各实施例的原理、实际应用或对市场中的技术的改进,或者使本技术领域的其它普通技术人员能理解本文披露的各实施例。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号