-
Notifications
You must be signed in to change notification settings - Fork 178
Open
Description
My package's version:
redlock: 5.0.0-beta.2
ioredis: 5.4.1
redis server: 7.4.0
node: v22.6.0
My code:
const express = require("express");
const Redlock = require("redlock").default;
const { promisify } = require("util");
const Client = require("ioredis");
require("log-timestamp");
// Create and configure a webserver.
const app = express();
app.use(express.json());
const host = "192.168.1.211";
const redis1 = new Client({
port: 26377,
host,
});
const redis2 = new Client({
port: 26378,
host,
});
const redis3 = new Client({
port: 26379,
host,
});
const redlock = new Redlock([redis1, redis2, redis3], {
driftFactor: 0.01,
retryCount: 5,
retryDelay: 200,
retryJitter: 200,
});
redlock.on("clientError", function (err) {
console.error("A redis error has occurred:", err);
});
// Adding a simple function to wait some time.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Create and endpoint to lock a key value paire and set the value.
app.post("/lockAndSetValue", async (req, res) => {
console.log("Request received!");
if (req.body.key && req.body.value) {
try {
const resource = `lock:${req.body.key}:${Date.now()}`;
console.log(`Resource: ${resource}`);
const ttl = 2000;
redlock.acquire([resource], ttl).then(async function (lock) {
console.log("Lock acquired!");
await redisSet(req.body.key, req.body.value);
console.log(`SET key=${req.body.key} value=${req.body.value}`);
console.log("Waiting some time...");
await sleep(1000);
console.log("Time finished, key unlocked!");
return lock.unlock().catch(function (err) {
console.error(err);
});
});
// redlock.using([resource], ttl, async (signal) => {
// console.log(`Lock acquired for ${resource}`);
// try {
// console.log("Do something...");
// } catch (error) {
// console.error(error);
// } finally {
// console.log(`Lock released for ${resource}`);
// }
// });
console.log("Sending response!");
res.send(resource);
} catch (e) {
res.json(e);
}
} else {
res.status(400).json({ error: "Wrong input." });
}
});
// Create an endpoint to set a key value pair.
app.post("/setValue", async (req, res) => {
if (req.body.key && req.body.value) {
try {
await redisSet(req.body.key, req.body.value);
console.log(`SET key=${req.body.key} value=${req.body.value}`);
res.send();
} catch (e) {
res.json(e);
}
} else {
res.status(400).json({ error: "Wrong input." });
}
});
// Create an endpoint to get a key value pair.
app.get("/getValue/:key", async (req, res) => {
if (!req.params.key) {
return res.status(400).json({ error: "Wrong input." });
}
try {
const value = await redisGet(req.params.key);
console.log(`GET key=${req.params.key} value=${value}`);
res.json(value);
} catch (e) {
res.json(e);
}
});
// Start the webserver.
app.listen(3000, () => {
console.log("Server is up on port 3000");
});
My docker-compose file to run redis sentinels:
services:
redis-master:
image: redis:6
container_name: redis-master
hostname: redis-master
ports:
- "6379:6379"
volumes:
- ./data/master:/data
command:
[
"redis-server",
"--appendonly",
"yes",
"--repl-diskless-load",
"on-empty-db",
"--replica-announce-ip",
"${HOST_IP}",
"--replica-announce-port",
"6379",
"--protected-mode",
"no"
]
networks:
redis-net:
ipv4_address: 172.21.0.3
redis-slave-1:
image: redis:6
container_name: redis-slave-1
hostname: redis-slave-1
depends_on:
- redis-master
ports:
- "6380:6379"
volumes:
- ./data/slave1:/data
command:
[
"redis-server",
"--appendonly",
"yes",
"--replicaof",
"redis-master",
"6379",
"--repl-diskless-load",
"on-empty-db",
"--replica-announce-ip",
"${HOST_IP}",
"--replica-announce-port",
"6380",
"--protected-mode",
"no"
]
networks:
redis-net:
ipv4_address: 172.21.0.4
redis-slave-2:
image: redis:6
container_name: redis-slave-2
hostname: redis-slave-2
depends_on:
- redis-master
ports:
- "6381:6379"
volumes:
- ./data/slave2:/data
command:
[
"redis-server",
"--appendonly",
"yes",
"--replicaof",
"redis-master",
"6379",
"--repl-diskless-load",
"on-empty-db",
"--replica-announce-ip",
"${HOST_IP}",
"--replica-announce-port",
"6381",
"--protected-mode",
"no"
]
networks:
redis-net:
ipv4_address: 172.21.0.5
sentinel-1:
image: redis:6
container_name: sentinel-1
hostname: sentinel-1
depends_on:
- redis-master
ports:
- "26379:26379"
command: >
sh -c 'echo "bind 0.0.0.0" > /etc/sentinel.conf &&
echo "sentinel monitor mymaster ${HOST_IP} 6379 2" >> /etc/sentinel.conf &&
echo "sentinel resolve-hostnames yes" >> /etc/sentinel.conf &&
echo "sentinel down-after-milliseconds mymaster 10000" >> /etc/sentinel.conf &&
echo "sentinel failover-timeout mymaster 10000" >> /etc/sentinel.conf &&
echo "sentinel parallel-syncs mymaster 1" >> /etc/sentinel.conf &&
redis-sentinel /etc/sentinel.conf'
networks:
redis-net:
ipv4_address: 172.21.0.6
sentinel-2:
image: redis:6
container_name: sentinel-2
hostname: sentinel-2
depends_on:
- redis-master
ports:
- "26378:26379"
command: >
sh -c 'echo "bind 0.0.0.0" > /etc/sentinel.conf &&
echo "sentinel monitor mymaster ${HOST_IP} 6379 2" >> /etc/sentinel.conf &&
echo "sentinel resolve-hostnames yes" >> /etc/sentinel.conf &&
echo "sentinel down-after-milliseconds mymaster 10000" >> /etc/sentinel.conf &&
echo "sentinel failover-timeout mymaster 10000" >> /etc/sentinel.conf &&
echo "sentinel parallel-syncs mymaster 1" >> /etc/sentinel.conf &&
redis-sentinel /etc/sentinel.conf'
networks:
redis-net:
ipv4_address: 172.21.0.7
sentinel-3:
image: redis:6
container_name: sentinel-3
hostname: sentinel-3
depends_on:
- redis-master
ports:
- "26377:26379"
command: >
sh -c 'echo "bind 0.0.0.0" > /etc/sentinel.conf &&
echo "sentinel monitor mymaster ${HOST_IP} 6379 2" >> /etc/sentinel.conf &&
echo "sentinel resolve-hostnames yes" >> /etc/sentinel.conf &&
echo "sentinel down-after-milliseconds mymaster 10000" >> /etc/sentinel.conf &&
echo "sentinel failover-timeout mymaster 10000" >> /etc/sentinel.conf &&
echo "sentinel parallel-syncs mymaster 1" >> /etc/sentinel.conf &&
redis-sentinel /etc/sentinel.conf'
networks:
redis-net:
ipv4_address: 172.21.0.8
networks:
redis-net:
driver: bridge
ipam:
config:
- subnet: 172.21.0.0/16
When I run curl:
curl --location 'localhost:3000/lockAndSetValue' \
--header 'Content-Type: application/json' \
--data '{
"key": "name",
"value": "Roberto"
}'
I got the error message:
/Users/ajackti/Downloads/Code/Nodejs/node-redis-example-5/webservice-ver2/node_modules/redlock/dist/cjs/index.js:296
throw new ExecutionError("The operation was unable to achieve a quorum during its retry window.", attempts);
^
ExecutionError: The operation was unable to achieve a quorum during its retry window.
at Redlock._execute (/Users/ajackti/Downloads/Code/Nodejs/node-redis-example-5/webservice-ver2/node_modules/redlock/dist/cjs/index.js:296:23)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Redlock.acquire (/Users/ajackti/Downloads/Code/Nodejs/node-redis-example-5/webservice-ver2/node_modules/redlock/dist/cjs/index.js:213:34) {
attempts: [
Promise {
{
membershipSize: 3,
quorumSize: 2,
votesFor: Set(0) {},
votesAgainst: Map(3) {
Commander {
options: [Object],
scriptsSet: {},
addedBuiltinSet: Set(0) {},
status: 'ready',
isCluster: false,
reconnectTimeout: null,
connectionEpoch: 1,
retryAttempts: 0,
manuallyClosing: false,
_autoPipelines: Map(0) {},
_runningAutoPipelines: Set(0) {},
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
commandQueue: [Denque],
offlineQueue: [Denque],
connector: [StandaloneConnector],
condition: [Object],
stream: [Socket],
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
} => ReplyError: ERR unknown command `evalsha`, with args beginning with: `96da70f7716f27d278a5218544df37fd8b0a5e4c`, `1`, `{resource}lock:name:1724811013590`, `beb20712d5d04dafa8e4b62f2b51a6fc`, `2000`,
at parseError (/Users/ajackti/Downloads/Code/Nodejs/node-redis-example-5/webservice-ver2/node_modules/redis-parser/lib/parser.js:179:12)
at parseType (/Users/ajackti/Downloads/Code/Nodejs/node-redis-example-5/webservice-ver2/node_modules/redis-parser/lib/parser.js:302:14) {
command: [Object]
},
Commander {
options: [Object],
scriptsSet: {},
addedBuiltinSet: Set(0) {},
status: 'ready',
isCluster: false,
reconnectTimeout: null,
connectionEpoch: 1,
retryAttempts: 0,
manuallyClosing: false,
_autoPipelines: Map(0) {},
_runningAutoPipelines: Set(0) {},
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
commandQueue: [Denque],
offlineQueue: [Denque],
connector: [StandaloneConnector],
condition: [Object],
stream: [Socket],
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
}
Please help me. I spent several days trying to address this, and my task’s deadline is approaching. I really need your help.
Metadata
Metadata
Assignees
Labels
No labels