Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

About etcd clientv3 non-blocking distributed locks #10493

Closed
codefast-cn opened this issue Feb 21, 2019 · 7 comments · Fixed by #11104
Closed

About etcd clientv3 non-blocking distributed locks #10493

codefast-cn opened this issue Feb 21, 2019 · 7 comments · Fixed by #11104

Comments

@codefast-cn
Copy link

codefast-cn commented Feb 21, 2019

File: etcd/clientv3/concurrency/mutex.go#L42
func (*Mutex).Lock(ctx Context) error {}

This function always blocks when it requests a lock that has been occupied. How can i make it non-blocking return with error?

@codefast-cn codefast-cn changed the title About etcd non-blocking distributed locks About etcd clientv3 non-blocking distributed locks Feb 21, 2019
@jingyih
Copy link
Contributor

jingyih commented Feb 23, 2019

As described in the function comment, you can pass a context with timeout when calling Lock(). Upon timeout, the context is canceled, and Lock() returns with error.

// Lock locks the mutex with a cancelable context. If the context is canceled
// while trying to acquire the lock, the mutex tries to clean its stale lock entry.

@jingyih jingyih closed this as completed Feb 23, 2019
@codefast-cn
Copy link
Author

codefast-cn commented Feb 25, 2019

As described in the function comment, you can pass a context with timeout when calling Lock(). Upon timeout, the context is canceled, and Lock() returns with error.
etcd/clientv3/concurrency/mutex.go

Lines 40 to 41 in 8c228d6

// Lock locks the mutex with a cancelable context. If the context is canceled
// while trying to acquire the lock, the mutex tries to clean its stale lock entry.

@jingyih
I mean that if the lock is occupied when tryLock, it will return immediately, instead of waitDeletes. Passing a context with a timeout when calling Lock() does not return immediately if the lock is occupied. How long is the timeout setting appropriate?

For example:
If we need to handle an event and only be processed once by one goroutine, it will take some time to do this, such as 1ms. The context timeout passed in Lock() is set to 2ms. When a goroutine obtain the lock, the lock is released after 1ms, and other goroutine can still obtain the lock. This event will be processed multiple times.

@jingyih
Copy link
Contributor

jingyih commented Feb 25, 2019

I see what you mean. I think 'tryLock' is a nice to have function. In the meantime, for your use case, can you try not to hold the lock while processing the event. Instead, use a flag to record if the event is being processed or not. And use the lock to protect this flag.

@jingyih jingyih closed this as completed Mar 11, 2019
@codefast-cn
Copy link
Author

@jingyih @technoweenie @bmizerany @drnic This feature will not be added?

@jingyih jingyih reopened this Mar 13, 2019
@jingyih
Copy link
Contributor

jingyih commented Mar 13, 2019

Personally I am not aware of any ongoing effort on this. You are welcome to add this feature if you are interested:)

@leonchen83
Copy link

leonchen83 commented Mar 14, 2019

tryLock feature is a good idea. we are facing the same issue.
We write a service that can switch master and slave via etcd lock
and do not want to block the service. so we also need a tryLock method to periodically check lock status.
we found that when lease was expired, the lock method also blocked.
pseudo code like following

Future<id> future = lease.grant(15); // 15 seconds
long leaseId = future.get();
Future<String> lockFuture = lock.lock("some lock", leaseId);
lockFuture.get(); // blocking here, when lease is expired, also blocking here
// lockFuture.get(5, TimeUnit.SECONDS); this will not block invoke, but the server also runing lock method

@jingyih @technoweenie @bmizerany @xiang90
Is there a way to implement the tryLock in client side.
We use our own gadget-etcd to access etcd server.

@vsbogd
Copy link

vsbogd commented Aug 7, 2019

@Dglei, I have read your case and my understanding is that you have two go-routines which are trying to use lock as flag that some event is processed. But for event processing it should be more natural to implement the following in each thread:

acquire lock
get event from queue
release lock

Then second thread after acquiring lock will find that queue is empty and event will be processed only once.
Could you please explain your case further?

vimalk78 added a commit to vimalk78/etcd that referenced this issue Sep 2, 2019
TryLock locks the mutex is not already locked by another session.
If lock is held by another session, return immediately after attempting necessary cleanup

Fixes etcd-io#10493
vimalk78 added a commit to vimalk78/etcd that referenced this issue Sep 2, 2019
TryLock locks the mutex if not already locked by another session.
If lock is held by another session, return immediately after attempting necessary cleanup

Fixes etcd-io#10493
vimalk78 added a commit to vimalk78/etcd that referenced this issue Sep 2, 2019
TryLock locks the mutex if not already locked by another session.
If lock is held by another session, return immediately after attempting necessary cleanup

Fixes etcd-io#10493
vimalk78 added a commit to vimalk78/etcd that referenced this issue Sep 10, 2019
TryLock locks the mutex if not already locked by another session.
If lock is held by another session, return immediately after attempting necessary cleanup

Added integration test

Fixes etcd-io#10493
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants