Closed kiyonlin closed 3 years ago
Hi:
Re 1: This implementation follows https://redis.io/topics/distlock#correct-implementation-with-a-single-instance
Re 2: The problem with auto-refresh is that errors may occur and those would be happening in the background. This library is designed to be relatively low-level and I don't want to make assumptions on how users would like to handle those refresh errors. That's why I implemented a simple https://pkg.go.dev/github.com/bsm/redislock#Lock.Refresh which allows you to write your very own wrapping logic and error handling. For example:
lock, err := locker.Obtain(ctx, "my-key", 100*time.Millisecond, nil)
// ...
defer lock.Release()
refreshCtx, cancel := context.WithCancel(ctx)
defer cancel()
go func() {
ticker := time.NewTicker(20*time.Millisecond)
defer ticker.Stop()
for {
select {
case <-refreshCtx.Done():
return
case <-ticker.C:
if err := lock.Refresh(refreshCtx, 100*time.Millisecond, nil); err != nil {
// handle refresh errors here: log, instrument, do whatever your app needs ...
}
}
}
}()
Hey, thanks for the awesome work! And I have two questions about current implementation, so I open this issue.
1. Race condition
I found this in official website section Distributed locks with Redis:
What do you think?
2. Auto refresh
Assuming we have code snippet like
We may get problem when business logic takes longer time than the expiration time.
My solution to solve this issue is add a
watch dog
asRedission
does:But yeah, this can be implemented by users themselves.
Thanks! Kiyon.