-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Description
When using Redis Cluster with the Node.js clients (node-redis / ioredis), multi-key commands such as MGET only work when all keys belong to the same hash slot. Otherwise Redis returns a CROSSSLOT error.
While this behavior is correct according to Redis Cluster semantics, other client libraries (e.g. Go and Python) provide a convenience abstraction where MGET internally performs a scatter-gather:
- compute hash slot for each key
- group keys by cluster node
- send parallel
MGETcommands per node - merge results and return them in the original order
This allows developers to efficiently retrieve multiple keys across the cluster without manually implementing slot grouping and pipelining.
Problem
Currently in Node.js, users must manually implement this logic every time they need a cluster-wide multi-key read. In many applications (cache lookups, session reads, user state fetches, etc.), retrieving multiple unrelated keys is common.
Typical workarounds today are:
- manually issuing multiple
GETcalls - building custom slot-grouping utilities
- redesigning key schemas to force hash-slot colocation
However, the first two approaches lead to duplicated implementations across projects.
Proposed Solution
Provide an optional helper API that performs scatter-gather internally without modifying the semantics of the existing mget command.
Example API:
await cluster.mgetCluster(["k1", "k2", "k3"])Possible implementation strategy:
- calculate slot for each key
- map slots to cluster nodes
- group keys per node
- send
MGETcommands to each node in parallel (pipelined if needed) - merge responses while preserving the original key order
This keeps the current behavior of mget() unchanged while providing an opt-in utility for cluster users.
Benefits
- reduces duplicated scatter-gather implementations
- improves ergonomics for cluster users
- maintains compatibility with existing Redis semantics
- aligns with convenience features provided in other Redis client ecosystems
Alternatives
- continue implementing custom scatter-gather utilities in application code
- enforce key schema design using hash tags
Additional Context
Many high-throughput systems already implement this logic internally to efficiently fetch multiple keys across Redis Cluster nodes. Providing a helper at the client level could standardize this pattern for the Node.js ecosystem.
Basic Code Example
async function mgetScatter(keys) {
const nodeGroups = new Map();
const results = new Array(keys.length);
const keyIndex = new Map();
// store original ordering
keys.forEach((key, i) => keyIndex.set(key, i));
// group keys by node
for (const key of keys) {
const slot = calculateSlot(key);
const node = cluster.nodes("master").find(n => {
const slots = n.slots;
return slots.some(([start, end]) => slot >= start && slot <= end);
});
if (!nodeGroups.has(node)) {
nodeGroups.set(node, []);
}
nodeGroups.get(node).push(key);
}
// send parallel MGET per node
const tasks = [];
for (const [node, nodeKeys] of nodeGroups.entries()) {
tasks.push(
node.mget(...nodeKeys).then(values => {
values.forEach((val, i) => {
const key = nodeKeys[i];
results[keyIndex.get(key)] = val;
});
})
);
}
await Promise.all(tasks);
return results;
}