I work for a small software company and I have been assigned to research a distributed lock manager for us. It should interact with both Java and C ++.
I have been working with ZooKeeper for several weeks, and implemented general locks (read and write locks) in accordance with the documentation. I now need to implement deadlock detection. If every client could maintain a lock schedule, it would be quick and easy. However, you cannot reliably see all the changes that occur with node in ZooKeeper , so maintaining an accurate graph would not be possible. This means that every time I check the deadlock, I will need to load a lot of locks, which seems impractical.
Another solution would be to implement deadlock detection on the ZooKeeper server I'm working on now. Each client would create a node inside '/ expectations', which is named after its session identifier, and its data would block its waiting. Since each castle has an ephemeral owner, I will have enough information to detect a dead end.
The problem is that the ZooKeeper server does not have the synchronization guarantees that the ZooKeeper client has. In addition, the ZooKeeper server is not as well documented as the client, because you usually should not touch it.
So my question is this: how can I implement deadlock detection using Apache ZooKeeper? I see that many people recommend ZooKeeper as a distributed lock manager, but if it cannot support deadlock detection, then no one should use it for this purpose.
EDIT:
I have a working solution. I can not guarantee its correctness, but it passed all my tests.
I use my checkForDeadlock
method, which is the heart of the deadlock detection algorithm. Here is the additional information you need to know:
- Only one client should start blocking detection at a time.
- First, the client tries to obtain a resource lock. If the resource is already locked and the client wants to wait until it becomes available, then the client will check the deadlock. If waiting for the resource does not lead to a deadlock, then it creates a znode in a special directory that identifies that this client is waiting for this resource. This line looks like this:
waitNode = zooKeeper.create(waitingPath + "/" + sessionID, resource.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
- No other client should start checking for a deadlock until this client creates a wait for a node.
- If two clients try to get locks almost at the same time, but providing both leads to a deadlock, it is a little possible that instead of the first client receiving the lock and the second client being rejected, the first client could be rejected and the second client may get a lock. This should not be a problem.
checkForDeadlock
throws a DeadlockException
if it encounters a deadlock. Otherwise, it returns normally.- Locks are provided in order. If the resource has a read lock and write wait lock, and the other client wants to get a read lock, it must wait until a write lock is granted and then released.
bySequenceNumber
is a comparator that sorts znodes according to the sequence that ZooKeeper appends to the end of consecutive znodes.
the code:
private void checkForDeadlock(String pathToResource) throws DeadlockException {
source share