Comments (30)
We are also hitting this issue as soon as 2 process are trying to lock the same resource. This is 100% reproduceable:
const { client } = require('./utils/RedisClient')
const { default: Redlock } = require('redlock')
const redlock = new Redlock(
[client], {
driftFactor: 0.01, // multiplied by lock ttl to determine drift time
retryCount: 300,
retryDelay: 1000, // time in ms
retryJitter: 200, // time in ms
automaticExtensionThreshold: 500, // time in ms
}
)
const withLock = async (resourceToLock, doSomethingWithLock) => {
let lock = await redlock.acquire([resourceToLock], 30000)
let result
try {
result = await doSomethingWithLock()
} finally {
await lock.release()
}
return result
}
const wait = ms => new Promise((resolve) => setTimeout(resolve, ms))
const main = async () => {
const name = process.argv[2]
try {
await withLock('superId', async () => {
console.log('start wait', name)
await wait(30000)
console.log('done waiting', name)
})
console.log('all done', name)
} catch (error) {
console.error(error.message)
}
process.exit()
}
main()
Result when running twice this process with p1 and p2 name:
start wait p2
done waiting p2
The operation was unable to achieve a quorum during its retry window.
Edit: This seems to happen 100% of the time if the acquire lock time is shorter than the time the function takes to complete, but seems to work when the acquire time is plenty more. This is not an issue if the function releases properly the lock, it might be if it crashes and doesn't though.
wait(30000)
with redlock.acquire([resourceToLock], 30000)
=> crashes
wait(30000)
with redlock.acquire([resourceToLock], 300000)
=> works
from node-redlock.
Any status update on the fix? It looks like a few PRs were made (I saw another github thread). where does this stand? I am also having this issue where I do not know the TTL upfront so I need the autoextending and it is giving me problems.
from node-redlock.
Hey everyone! 👋
Is there a fix for this issue yet, or has anyone found a workaround?
Are we all just waiting for the stable v5 release, or is there something I’ve missed? Any info or updates would be super helpful!
from node-redlock.
Hi folks, I faced this problem, but was a mistake in my code.
I was trying to aquire and make a set in the same key, as:
const main = async () => {
try {
const lock = await redlock.acquire(['myKey], 1000);
redisClient.set("myKey", "newValue")
await lock.release();
} catch (e) {
console.error(e);
throw e;
}
}
But this way is wrong because we need to aquire a resourceKey like "myLokedResouce:myKey" and then make changes in our key (is tihis exemple "myKey") and after release the lock on "myLokedResouce:myKey". Now my code search by "resourceKey" to know if can makes changes in my "key" like:
const key = "project"
const value = "CONFLICT"
const resource = locks:${key}
const lockTtl = 66000
async function lockAndSet(resource , lockTtl) {
const lock = await redlock.acquire([resource], lockTtl)
try {
await redisSet(key, value)
console.log('Time finished, key unlocked!')
await lock.release()
} catch (e) {
console.log(e)
}
}
lockAndSet(resource, lockTtl)
from node-redlock.
Hey, we also encountered this issue on both v4
and v5
.
In our case the problem was, that our lock was expired by the time we tried to release.
Failing code:
// redis and redlock setup is omitted
const wait = async (ms: number) => {
return new Promise((resolve) => setTimeout(() => resolve(ms), ms));
};
const main = async () => {
try {
const lock = await redlock.acquire(['a'], 1000);
await wait(1500);
await lock.release();
} catch (e) {
console.error(e);
throw e;
}
};
main();
Error:
ExecutionError: The operation was unable to achieve a quorum during its retry window.
working code:
// redis, redlock and wait setup is omitted
const main = async () => {
try {
const lock = await redlock.acquire(['a'], 1000);
await lock.extend(1600);
await wait(1500);
await lock.release();
} catch (e) {
console.error(e);
throw e;
}
};
main();
for us switching to redlock.using
, increasing lock duration or using lock.extend
all worked.
I think the best for the library would be to make lock.release()
a noop if it's already expired.
from node-redlock.
Hi folks, I faced this problem, but was a mistake in my code.
I was trying to aquire and make a set in the same key, as:
const main = async () => { try { const lock = await redlock.acquire(['myKey], 1000); redisClient.set("myKey", "newValue") await lock.release(); } catch (e) { console.error(e); throw e; } }
But this way is wrong because we need to aquire a resourceKey like "myLokedResouce:myKey" and then make changes in our key (is tihis exemple "myKey") and after release the lock on "myLokedResouce:myKey". Now my code search by "resourceKey" to know if can makes changes in my "key" like:
const key = "project" const value = "CONFLICT" const resource =
locks:${key}
const lockTtl = 66000async function lockAndSet(resource , lockTtl) { const lock = await redlock.acquire([resource], lockTtl)
try { await redisSet(key, value) console.log('Time finished, key unlocked!') await lock.release()
} catch (e) { console.log(e) } }
lockAndSet(resource, lockTtl)
This was also the solution for my case. The DOCS need updating, I've done so on this PR: #291
from node-redlock.
Hi folks, I faced this problem, but was a mistake in my code.
I was trying to aquire and make a set in the same key, as:
const main = async () => { try { const lock = await redlock.acquire(['myKey], 1000); redisClient.set("myKey", "newValue") await lock.release(); } catch (e) { console.error(e); throw e; } }
But this way is wrong because we need to aquire a resourceKey like "myLokedResouce:myKey" and then make changes in our key (is tihis exemple "myKey") and after release the lock on "myLokedResouce:myKey". Now my code search by "resourceKey" to know if can makes changes in my "key" like:
const key = "project" const value = "CONFLICT" const resource =
locks:${key}
const lockTtl = 66000async function lockAndSet(resource , lockTtl) { const lock = await redlock.acquire([resource], lockTtl)
try { await redisSet(key, value) console.log('Time finished, key unlocked!') await lock.release()
} catch (e) { console.log(e) } }
lockAndSet(resource, lockTtl)
This worked for me. Thank you.
So this project did not document how to use resource keys. (Please update the *.md if possible)
Summary:
We should not use the key of the locked resource as resource keys and prepend something like "redlock:user1111" and this refers to the lock, like a pointer and not the actual item.
from node-redlock.
Solved it using a check for the lock expiration:
const now = new Date().getTime();
if (lock && lock.expiration > now) {
await lock.release();
}
If the lock is expired (TTL), it is no longer in the cache, so don't release it.
from node-redlock.
Downgrading to version 4 for redlock and ioredis solved my issue completely, I guess there's a bug with the v5 implementation.
from node-redlock.
having this same issue too.
from node-redlock.
I have the same problem, is there any solution?
from node-redlock.
@jskorlol try downgrading to version 4 of this package and ioredis
from node-redlock.
yeah, the problem is i would really like the lock auto extend functionality.
from node-redlock.
I'm having this problem too, we use redlock v4 to great success so I'm downgrading for now.
from node-redlock.
any update on this, I am having this problem too
from node-redlock.
We are still seeing this intermittently even with redlock.using
from node-redlock.
I was also running into this on version 5.0.0-beta.2
while using redlock.using
, here's the relevant stack trace:
ExecutionError: The operation was unable to achieve a quorum during its retry window.
at Redlock._execute (file:///workspace/node_modules/redlock/dist/esm/index.js:290:23)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Redlock.acquire (file:///workspace/node_modules/redlock/dist/esm/index.js:207:34)
at async Redlock.using (file:///workspace/node_modules/redlock/dist/esm/index.js:448:20)
... my code ...
With the call to using looking like:
await redlock.using([lockId], 5000, async (signal) => { ... my code ... });
The problem seems to occur when the same resource is trying to be locked multiple times in close succession. Increasing the retryCount
and retryDelay
(to 30
and 1000
respectively for my setup) prevented the quorum error from throwing, but then I'd still have errors about not being able to extend an already expired lock.
from node-redlock.
Got bitten by this as well
"ioredis": "^5.2.3",
"redlock": "^5.0.0-beta.2",
from node-redlock.
I have issue too! I have no idea. I read code and find client.evalsha(args)
function throw error Error: node_redis: The EVALSHA command contains a invalid argument type.
,then I have no idea
from node-redlock.
I believe this is a bug in the v5 implementation. When you attempt to set a lock using acquire()
and the resource is locked, Redlock will throw an ExecutionError
, but it should throw a ResourceLockedError
(as it did in the previous version).
from node-redlock.
I was facing same issue but it was because of me passing redis client as undefined
. You can debug this issue by logging in error event handler of redlock.
from node-redlock.
Downgrading to version 4 for redlock and ioredis solved my issue completely, I guess there's a bug with the v5 implementation.
Can you specify concrete version?
from node-redlock.
Hi folks, I faced this problem, but was a mistake in my code.
I was trying to aquire and make a set in the same key, as:
const main = async () => { try { const lock = await redlock.acquire(['myKey], 1000); redisClient.set("myKey", "newValue") await lock.release(); } catch (e) { console.error(e); throw e; } }
But this way is wrong because we need to aquire a resourceKey like "myLokedResouce:myKey" and then make changes in our key (is tihis exemple "myKey") and after release the lock on "myLokedResouce:myKey". Now my code search by "resourceKey" to know if can makes changes in my "key" like:
const key = "project" const value = "CONFLICT" const resource =
locks:${key}
const lockTtl = 66000async function lockAndSet(resource , lockTtl) { const lock = await redlock.acquire([resource], lockTtl)
try { await redisSet(key, value) console.log('Time finished, key unlocked!') await lock.release()
} catch (e) { console.log(e) } }
lockAndSet(resource, lockTtl)
This resolved my issues. Be sure to add a resource key ^5.0.0-beta.2
from node-redlock.
The operation was unable to achieve a quorum during its retry window.
Is there a way to fix this?
Code:
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
for (let i = 0; i < 30; i++) {
redlock
.using(['test'], 10_000, async () => {
await sleep(200);
console.log('OK');
})
.catch((e) => console.error(e.message));
}
from node-redlock.
I also faced the same problem, but the solution is around the duration of lock which you mentioned.
I mean :
You are configuring 400ms as duration of lock
and trying to release the lock at 600th ms[trying to release already expired lock]. Which could cause this issue.
from node-redlock.
So currently, with what is available, to prevent errors, you have to give a timelock beyond the duration of your service.
That is if your service will run for 2 seconds, make it 5s to be safe, so as long the service does not crash, it will notify Redis when it is done for another service to acquire the lock. Or you can use the extend
method to extend the lock when your service will take longer time.
from node-redlock.
I write this because there's maybe someone who's mistaken like me.
First, I wrote my code like
await redlock.acquire([
'StoreProduct', // table name (static),
storeProduct.id, // record id (dynamic),
], 60 * 1000);
but I faced error ...unable to achieve a quorum during its retry window
.
and after I read lib codes,
I found this codes
so now, I know my case needs to be fixed like
await redlock.acquire([
`StoreProduct:${storeProduct.id}`,
], 60 * 1000);
from node-redlock.
Just stumbled on this now. Downgrading to 4.2.0 was the only solution. As far as I can tell it works with the latest version of ioredis
but you'll need to add a @ts-expect-error
because the two signatures between the expected version of ioredis
and the latest are different.
from node-redlock.
I think it is a bug
If you have any existing lock
than client.evalsha return 0
here
Line 561 in 5138813
and after this place
Line 597 in 5138813
return error because lock key is not implemented (result === 0
), but you have min one row in keys.length > 0
BUT after return error from here
Line 465 in 5138813
from node-redlock.
for lock error vote === 'against'
and after we always return error qurum because skip by this line
Line 446 in 5138813
from node-redlock.
Related Issues (20)
- Submitting a value for the lock
- Migration guide from 4.2.0 to 5.x?
- Redlock 4.x Compatible with Redit 7.x? HOT 1
- Unable to achieve a quorum during its retry window
- Cannot extend an already-expired lock crashes consumer pods. HOT 1
- Throw specific errors when there's an issue either acquiring or releasing the lock HOT 1
- "ioredis": "^5.3.2" incompatible with "redlock": "^5.0.0-beta.2" and "@types/redlock": "^4.0.5", HOT 2
- TypeError: client.evalsha is not a function HOT 3
- No support for redis functions
- Lock in use should throw a specific error HOT 1
- Do not wait for lock (NOWAIT)
- Release with fixed type resolution HOT 2
- Do not execute RELEASE_SCRIPT lock failed with one client
- Return resource name of lock that was not acquired in vote against error
- MOVED Error Handling in Redis Cluster Environment
- Issue with Redlock Stuck in Redis Cluster Setup
- Expiration time is in the past HOT 2
- a few issues after trying beta 5.0.0
- Configure Redis DB # explicitly? HOT 1
- Wrong acquire() lock duration
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from node-redlock.