DLM分布式锁的实现机制
1、AST简介
进程1和进程2拥有数据块S模式的锁,因此在granted queue 中有记录,假设现在进程2要获得X模式的锁,进程2必须先向DLM提出请求;请求提交给DLM后,DLM就要把进程2放在convert queue中。向拥有不兼容模式锁的进程1发送一个blocking ASTs,这是一个异步请求,所以DLM不必等待响应。当进程1接受到这个BAST之后,就会把这个lock降级为null模式,DLM把进程2的锁模式转换为x模式,如下图所示:
然后,DLM发送一个acquisition ASTn(AAST)给进程2,并把进程2放到Granted queue中,如下图所示,进程2就可以继续处理了:
2、在DLM中如何授予锁
为了说明锁定在OPS的DLM中是如何工作的,请考虑一个由两个节点组成的示例集群,它有一个共享磁盘阵列:
(1) 进程p1需要修改实例1上的一个数据块。p1需要检查这个数据块上是否存在锁,然后才能将它读入实例1上的缓冲区缓存中。
(2) 这个数据块中可能存在锁,也可能不存在,因此LCK进程检查SGA结构,以验证缓冲区锁状态。如果存在锁,那么LCK必须请求DLM对这个锁进行降级。
(3) 如果不存在锁,那么LCK必须在本地实例中创建锁元素(LE),其角色是本地的。
(4) LCK必须以独占模式向DLM请求这个LE。如果该资源由实例1主控,那么LM继续处理。否则,必须将这个请求发送到集群中的主控DLM。
(5) 假定这个锁由实例1主控,则这个实例上的DLM在其DLM数据库中进行本地缓存查询,发现实例2上的一个进程已经对同一数据块拥有独占(EX)锁。
(6) 实例1上的DLM向实例2上的DLM发出一个BAST,请求对此锁进行降级。实例2上的DLM向同一实例上的LCK发出另一个BAST,将这个锁由EX降级为NULL。
(7) 实例2上的进程可能已经更新了这个锁,并且可能还没有提交修改。"脏缓冲区写入器"(DBWR)得到信号,将这个数据块写到磁盘上。在写入确认之后,实例2上的LCK将这个锁降级为NULL,向同一实例上的DLM发送一个AAST。
(8) 实例2上的DLM针对锁状态的修改对本地DLM数据库进行更新,并向实例1上的DLM发送一个AAST。
(9) 实例1上的主控DLM更新主控DLM数据库中这个锁(EX)的状态,现在可以将这个锁授予其实例上的进程。DLM自身将这个锁升级到EX。
(10) 实例1上的DLM现在向本地LCK进程发送另一个AAST,向它通知有关锁授予的情况,而且现在可以从磁盘读取该数据块。
Lock modes
A process running within a VMSCluster may obtain a lock on a resource. There are six lock modes that can be granted, and these determine the level of exclusivity being granted, it is possible to convert the lock to a higher or lower level of lock mode. When all processes have unlocked a resource, the system's information about the resource is destroyed.
- Null (NL). Indicates interest in the resource, but does not prevent other processes from locking it. It has the advantage that the resource and its lock value block are preserved, even when no processes are locking it.
- Concurrent Read (CR). Indicates a desire to read (but not update) the resource. It allows other processes to read or update the resource, but prevents others from having exclusive access to it. This is usually employed on high-level resources, in order that more restrictive locks can be obtained on subordinate resources.
- Concurrent Write (CW). Indicates a desire to read and update the resource. It also allows other processes to read or update the resource, but prevents others from having exclusive access to it. This is also usually employed on high-level resources, in order that more restrictive locks can be obtained on subordinate resources.
- Protected Read (PR). This is the traditional share lock, which indicates a desire to read the resource but prevents other from updating it. Others can however also read the resource.
- Protected Write (PW). This is the traditional update lock, which indicates a desire to read and update the resource and prevents others from updating it. Others with Concurrent Read access can however read the resource.
- Exclusive (EX). This is the traditional exclusive lock which allows read and update access to the resource, and prevents others from having any access to it.
The following truth table shows the compatibility of each lock mode with the others:
Mode | NL | CR | CW | PR | PW | EX |
---|---|---|---|---|---|---|
NL | Yes | Yes | Yes | Yes | Yes | Yes |
CR | Yes | Yes | Yes | Yes | Yes | No |
CW | Yes | Yes | Yes | No | No | No |
PR | Yes | Yes | No | Yes | No | No |
PW | Yes | Yes | No | No | No | No |
EX | Yes | No | No | No | No | No |
Obtaining a lock
A process can obtain a lock on a resource by enqueueing a lock request. This is similar to the QIO technique that is used to perform I/O. The enqueue lock request can either complete synchronously, in which case the process waits until the lock is granted, or asynchronously, in which case an AST occurs when the lock has been obtained.
It is also possible to establish a blocking AST, which is triggered when a process has obtained a lock that is preventing access to the resource by another process. The original process can then optionally take action to allow the other access (e.g. by demoting or releasing the lock).
Lock value block
A lock value block is associated with each resource. This can be read by any process that has obtained a lock on the resource (other than a null lock) and can be updated by a process that has obtained a protected update or exclusive lock on it.
It can be used to hold any information about the resource that the application designer chooses. A typical use is to hold a version number of the resource. Each time the associated entity (e.g. a database record) is updated, the holder of the lock increments the lock value block. When another process wishes to read the resource, it obtains the appropriate lock and compares the current lock value with the value it had last time the process locked the resource. If the value is the same, the process knows that the associated entity has not been updated since last time it read it, and therefore it is unnecessary to read it again. Hence, this technique can be used to implement various types of cache in a database or similar application.
Deadlock detection
When one or more processes have obtained locks on resources, it is possible to produce a situation where each is preventing another from obtaining a lock, and none of them can proceed. This is known as a deadlock (E. W. Dijkstra originally called it a deadly embrace).[1]
A simple example is when Process 1 has obtained an exclusive lock on Resource A, and Process 2 has obtained an exclusive lock on Resource B. If Process 1 then tries to lock Resource B, it will have to wait for Process 2 to release it. But if Process 2 then tries to lock Resource A, both processes will wait forever for each other.
The OpenVMS DLM periodically checks for deadlock situations. In the example above, the second lock enqueue request of one of the processes would return with a deadlock status. It would then be up to this process to take action to resolve the deadlock—in this case by releasing the first lock it obtained.