* refactor pubsub, add support for sharded pub sub * run tests in redis 7 only, fix PUBSUB SHARDCHANNELS test * add some comments and fix some bugs * PubSubType, not PubSubTypes 🤦♂️ * remove test.txt * fix some bugs, add tests * add some tests * fix #2345 - allow PING in PubSub mode (remove client side validation) * remove .only * revert changes in cluster/index.ts * fix tests minimum version * handle server sunsubscribe * add 'sharded-channel-moved' event to docs, improve the events section in the main README (fix #2302) * exit "resubscribe" if pubsub not active * Update commands-queue.ts * Release client@1.5.0-rc.0 * WIP * use `node:util` instead of `node:util/types` (to support node 14) * run PubSub resharding test with Redis 7+ * fix inconsistency in live resharding test * add some tests * fix iterateAllNodes when starting from a replica * fix iterateAllNodes random * fix slotNodesIterator * fix slotNodesIterator * clear pubSubNode when node in use * wait for all nodes cluster state to be ok before testing * `cluster.minimizeConections` tests * `client.reconnectStrategry = false | 0` tests * sharded pubsub + cluster 🎉 * add minimum version to sharded pubsub tests * add cluster sharded pubsub live reshard test, use stable dockers for tests, make sure to close pubsub clients when a node disconnects from the cluster * fix "ssubscribe & sunsubscribe" test * lock search docker to 2.4.9 * change numberOfMasters default to 2 * use edge for bloom * add tests * add back getMasters and getSlotMaster as deprecated functions * add some tests * fix reconnect strategy + docs * sharded pubsub docs * Update pub-sub.md * some jsdoc, docs, cluster topology test * clean pub-sub docs Co-authored-by: Simon Prickett <simon@redislabs.com> * reconnect startegy docs and bug fix Co-authored-by: Simon Prickett <simon@redislabs.com> * refine jsdoc and some docs Co-authored-by: Simon Prickett <simon@redislabs.com> * I'm stupid * fix cluster topology test * fix cluster topology test * Update README.md * Update clustering.md * Update pub-sub.md Co-authored-by: Simon Prickett <simon@redislabs.com>
6.7 KiB
Clustering
Basic Example
Connecting to a cluster is a bit different. Create the client by specifying some (or all) of the nodes in your cluster and then use it like a regular client instance:
import { createCluster } from 'redis';
const cluster = createCluster({
rootNodes: [
{
url: 'redis://10.0.0.1:30001'
},
{
url: 'redis://10.0.0.2:30002'
}
]
});
cluster.on('error', (err) => console.log('Redis Cluster Error', err));
await cluster.connect();
await cluster.set('key', 'value');
const value = await cluster.get('key');
createCluster configuration
See the client configuration page for the
rootNodesanddefaultsconfiguration schemas.
| Property | Default | Description |
|---|---|---|
| rootNodes | An array of root nodes that are part of the cluster, which will be used to get the cluster topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster, 3 should be enough to reliably connect and obtain the cluster configuration from the server | |
| defaults | The default configuration values for every client in the cluster. Use this for example when specifying an ACL user to connect with | |
| useReplicas | false |
When true, distribute load by executing readonly commands (such as GET, GEOSEARCH, etc.) across all cluster nodes. When false, only use master nodes |
| minimizeConnections | false |
When true, .connect() will only discover the cluster topology, without actually connecting to all the nodes. Useful for short-term or Pub/Sub-only connections. |
| maxCommandRedirections | 16 |
The maximum number of times a command will be redirected due to MOVED or ASK errors |
| nodeAddressMap | Defines the node address mapping | |
| modules | Included Redis Modules | |
| scripts | Script definitions (see Lua Scripts) | |
| functions | Function definitions (see Functions) |
Auth with password and username
Specifying the password in the URL or a root node will only affect the connection to that specific node. In case you want to set the password for all the connections being created from a cluster instance, use the defaults option.
createCluster({
rootNodes: [{
url: 'redis://10.0.0.1:30001'
}, {
url: 'redis://10.0.0.2:30002'
}],
defaults: {
username: 'username',
password: 'password'
}
});
Node Address Map
A mapping between the addresses in the cluster (see CLUSTER SHARDS) and the addresses the client should connect to.
Useful when the cluster is running on a different network to the client.
const rootNodes = [{
url: 'external-host-1.io:30001'
}, {
url: 'external-host-2.io:30002'
}];
// Use either a static mapping:
createCluster({
rootNodes,
nodeAddressMap: {
'10.0.0.1:30001': {
host: 'external-host.io',
port: 30001
},
'10.0.0.2:30002': {
host: 'external-host.io',
port: 30002
}
}
});
// or create the mapping dynamically, as a function:
createCluster({
rootNodes,
nodeAddressMap(address) {
const indexOfDash = address.lastIndexOf('-'),
indexOfDot = address.indexOf('.', indexOfDash),
indexOfColons = address.indexOf(':', indexOfDot);
return {
host: `external-host-${address.substring(indexOfDash + 1, indexOfDot)}.io`,
port: Number(address.substring(indexOfColons + 1))
};
}
});
This is a common problem when using ElastiCache. See Accessing ElastiCache from outside AWS for more information on that.
Command Routing
Commands that operate on Redis Keys
Commands such as GET, SET, etc. are routed by the first key, for instance MGET 1 2 3 will be routed by the key 1.
Server Commands
Admin commands such as MEMORY STATS, FLUSHALL, etc. are not attached to the cluster, and must be executed on a specific node via .getSlotMaster().
"Forwarded Commands"
Certain commands (e.g. PUBLISH) are forwarded to other cluster nodes by the Redis server. This client sends these commands to a random node in order to spread the load across the cluster.