|
| 1 | +Redis Cluster Architecture Diagram |
| 2 | +=================================== |
| 3 | + |
| 4 | + ┌─────────────────────────────────────────┐ |
| 5 | + │ RedisCluster (Root) │ |
| 6 | + │ │ |
| 7 | + │ - _options: RedisClusterOptions │ |
| 8 | + │ - _slots: RedisClusterSlots │ |
| 9 | + │ - _commandOptions │ |
| 10 | + │ │ |
| 11 | + │ Methods: │ |
| 12 | + │ + connect() │ |
| 13 | + │ + sendCommand() │ |
| 14 | + │ + MULTI() │ |
| 15 | + │ + SUBSCRIBE() / UNSUBSCRIBE() │ |
| 16 | + │ + SSUBSCRIBE() / SUNSUBSCRIBE() │ |
| 17 | + │ + close() / destroy() │ |
| 18 | + └──────────────┬──────────────────────────┘ |
| 19 | + │ |
| 20 | + │ contains |
| 21 | + │ |
| 22 | + ┌──────────────────────────┴──────────────────────────┐ |
| 23 | + │ │ |
| 24 | + │ RedisClusterSlots │ |
| 25 | + │ │ |
| 26 | + │ - slots: Array<Shard>[16384] │ |
| 27 | + │ - masters: Array<MasterNode> │ |
| 28 | + │ - replicas: Array<ShardNode> │ |
| 29 | + │ - nodeByAddress: Map<string, Node> │ |
| 30 | + │ - pubSubNode?: PubSubNode │ |
| 31 | + │ - clientSideCache?: PooledClientSideCacheProvider │ |
| 32 | + │ │ |
| 33 | + │ Methods: │ |
| 34 | + │ + connect() │ |
| 35 | + │ + getClient() │ |
| 36 | + │ + rediscover() │ |
| 37 | + │ + getPubSubClient() │ |
| 38 | + │ + getShardedPubSubClient() │ |
| 39 | + │ + getRandomNode() │ |
| 40 | + │ + getSlotRandomNode() │ |
| 41 | + └───────┬─────────────────┬─────────────────┬─────────┘ |
| 42 | + │ │ │ |
| 43 | + ┌──────────┘ │ └─────────────┐ |
| 44 | + │ │ │ |
| 45 | + │ has many │ optionally has │ has many |
| 46 | + ▼ ▼ ▼ |
| 47 | + ┌────────────────────────┐ ┌────────────────────────┐ ┌────────────────────────┐ |
| 48 | + │ Shard │ │ PubSubNode │ │ RedisClient │ |
| 49 | + │ │ │ │ │ (per node) │ |
| 50 | + │ - master: MasterNode │ │ - address: string │ │ │ |
| 51 | + │ - replicas?: Array │ │ - client: RedisClient │ │ Socket, Queue, etc. │ |
| 52 | + │ - nodesIterator │ │ - connectPromise │ │ │ |
| 53 | + └──────────┬─────────────┘ └────────────────────────┘ └────────────────────────┘ |
| 54 | + │ |
| 55 | + │ contains |
| 56 | + │ |
| 57 | + ┌────────────┴────────────┐ |
| 58 | + │ │ |
| 59 | + ▼ ▼ |
| 60 | +┌──────────────────┐ ┌──────────────────┐ |
| 61 | +│ MasterNode │ │ ShardNode │ |
| 62 | +│ │ │ (replica) │ |
| 63 | +│ - id: string │ │ │ |
| 64 | +│ - host: string │ │ - id: string │ |
| 65 | +│ - port: number │ │ - host: string │ |
| 66 | +│ - address │ │ - port: number │ |
| 67 | +│ - readonly: no │ │ - address │ |
| 68 | +│ - client? │ │ - readonly: yes │ |
| 69 | +│ - pubSub? │ │ - client? │ |
| 70 | +│ └─> client │ │ │ |
| 71 | +│ └─> promise │ │ │ |
| 72 | +└──────────────────┘ └──────────────────┘ |
| 73 | + |
| 74 | + |
| 75 | +Additional Components: |
| 76 | +───────────────────── |
| 77 | + |
| 78 | +┌────────────────────────────────────┐ |
| 79 | +│ RedisClusterMultiCommand │ |
| 80 | +│ │ |
| 81 | +│ Used for MULTI/PIPELINE: │ |
| 82 | +│ - Batches commands │ |
| 83 | +│ - Routes to single node │ |
| 84 | +│ - Returns typed results │ |
| 85 | +│ │ |
| 86 | +│ Methods: │ |
| 87 | +│ + addCommand() │ |
| 88 | +│ + exec() │ |
| 89 | +│ + execAsPipeline() │ |
| 90 | +└────────────────────────────────────┘ |
| 91 | + |
| 92 | +┌────────────────────────────────────┐ |
| 93 | +│ PooledClientSideCacheProvider │ |
| 94 | +│ (BasicPooledClientSideCache) │ |
| 95 | +│ │ |
| 96 | +│ RESP3 Client-Side Caching: │ |
| 97 | +│ - Shared across all nodes │ |
| 98 | +│ - Invalidation tracking │ |
| 99 | +│ - TTL & eviction policies │ |
| 100 | +│ │ |
| 101 | +│ Methods: │ |
| 102 | +│ + get() / set() │ |
| 103 | +│ + invalidate() │ |
| 104 | +│ + clear() / enable() / disable() │ |
| 105 | +└────────────────────────────────────┘ |
| 106 | + |
| 107 | + |
| 108 | +Key Relationships: |
| 109 | +───────────────── |
| 110 | + |
| 111 | +1. RedisCluster |
| 112 | + └─> RedisClusterSlots (manages topology) |
| 113 | + └─> Shard[] (16,384 hash slots) |
| 114 | + ├─> MasterNode (read/write) |
| 115 | + │ └─> RedisClient |
| 116 | + │ └─> PubSub RedisClient (sharded pub/sub) |
| 117 | + └─> ShardNode[] (replicas, read-only if useReplicas=true) |
| 118 | + └─> RedisClient |
| 119 | + |
| 120 | +2. RedisCluster |
| 121 | + └─> RedisClusterMultiCommand (for transactions) |
| 122 | + |
| 123 | +3. RedisClusterSlots |
| 124 | + └─> PubSubNode (global pub/sub) |
| 125 | + └─> RedisClient |
| 126 | + |
| 127 | +4. RedisClusterSlots |
| 128 | + └─> PooledClientSideCacheProvider (shared cache, RESP3 only) |
| 129 | + |
| 130 | + |
| 131 | +Command Flow: |
| 132 | +──────────── |
| 133 | + |
| 134 | +Single Command: |
| 135 | + Client.sendCommand() |
| 136 | + → Cluster._execute() |
| 137 | + → Slots.getClient(key, isReadonly) |
| 138 | + → Calculate slot from key |
| 139 | + → Get Shard for slot |
| 140 | + → Return master or replica client |
| 141 | + → Client.sendCommand() |
| 142 | + → [If MOVED/ASK error] |
| 143 | + → Slots.rediscover() |
| 144 | + → Retry with new node |
| 145 | + |
| 146 | +Transaction (MULTI): |
| 147 | + Client.MULTI(routing) |
| 148 | + → RedisClusterMultiCommand |
| 149 | + → Accumulate commands |
| 150 | + → All commands must route to same node |
| 151 | + → client.exec() |
| 152 | + |
| 153 | +Pub/Sub: |
| 154 | + Global: Uses single PubSubNode |
| 155 | + Sharded: Uses per-master pubSub client based on channel hash |
| 156 | + |
| 157 | + |
| 158 | +Discovery & Failover: |
| 159 | +───────────────────── |
| 160 | + |
| 161 | +1. Initial Connect: |
| 162 | + - Try rootNodes in random order |
| 163 | + - Execute CLUSTER SLOTS command |
| 164 | + - Build slot → shard mapping |
| 165 | + - Create client connections |
| 166 | + |
| 167 | +2. Rediscovery (on MOVED error): |
| 168 | + - Clear cache |
| 169 | + - Re-fetch CLUSTER SLOTS |
| 170 | + - Update topology |
| 171 | + - Reconnect clients to new nodes |
| 172 | + |
| 173 | +3. Node Address Mapping: |
| 174 | + - nodeAddressMap translates cluster IPs |
| 175 | + - Useful for NAT/Docker scenarios |
0 commit comments