A Redis Cluster and Sentinel GUI that reaches every node
Clusters live behind bastions, NAT and Docker port mappings, and their nodes announce addresses your laptop cannot dial. Sentinel moves the master when it fails. SQLly routes every command to the node that owns its slot, rewrites the addresses it cannot reach, traces each node step by step, and follows a failover without ever applying a write twice.
Slot routing that follows the cluster
List one or more seed nodes in the Server field, comma-separated, or paste a
redis:// URL with several hosts. Cluster mode detects a cluster
on the first connect of a session, or you can set it to always or never route by slot.
- Every command to its slot’s owner. After a failover or a reshard,
MOVEDandASKreplies are followed and the slot map updated; the Messages pane says how many redirects a script saw. - Every tool across every master. The key browser walks each master in turn, the memory analyzer splits its sample by key count, bulk delete batches
UNLINKby slot, and the Profiler and Pub/Sub viewer add a node column. - Sharded Pub/Sub. Enter a channel with a leading
#, such as#orders, and it is watched withSSUBSCRIBEon the master that owns it.
MGET user:{42}:profile user:{42}:cart
SQLLY.KEYS user:* 1000
SQLLY.TOPOLOGY
SQLLY.TRACE
Keys that share a hash tag share a slot, so the MGET runs. SQLLY.KEYS
walks every master in pages with a cursor that continues across them, and
SQLLY.TOPOLOGY and SQLLY.TRACE are the topology view and its trace as
read-only commands.
A node map for addresses you cannot dial
Cluster nodes tell clients where the other nodes are, using the addresses they were configured
to announce. Behind NAT, a Docker port mapping or an SSH bastion those are often private. The
Cluster node map takes one announced => dial pair per line; the
announced address keeps naming the node in the slot map, in redirects and as the TLS server
name, and only the socket goes to the dial address.
10.0.0.5:7001 => 127.0.0.1:17001 10.0.0.6:7002 => 127.0.0.1:17002 10.0.0.7:7003 => 127.0.0.1:17003
A forward per node through SSH
On a connection with SSH hops or a SOCKS or HTTP proxy, SQLly opens a separate local forward for each node the cluster names, through the same hops, so a node only the bastion can reach still works. The node map is applied first, so it can rewrite what the bastion dials too.
Node map and SSH βTLS checked against the right name
Each node’s certificate is checked against the address it announces, not the local forward, so a correctly issued certificate verifies through the tunnel. Tunnels send a keepalive after 30 seconds of silence and reopen after a drop.
TLS modes βredis-cluster-node-map-editor.webp β the connection editor for the 7100β7105 cluster fixture with Cluster mode set to Redis Cluster and three node map lines rewriting announced addresses to local forwardsThese reported Redis Insight issues describe the situations the node map and per-node forwards were built for: #6537 (a cluster through locally forwarded SSH ports failing with “Failed to refresh slots cache”) and #5722 (an incomplete cluster topology with TLS and hostnames). Check the tracker for where each stands today.
Topology, and a trace for every node
Open Cluster Topology… from a database’s right-click menu, the
command palette, or the Server Dashboard of a cluster connection. It lists every node from
CLUSTER SHARDS (or CLUSTER NODES before 7.0) with its role, slots,
health, replication offset, link state, the address it announces, the address SQLly dials and
the TLS name it sends. The footer checks that all 16,384 slots are covered and names any node
that is unhealthy or remapped.
redis-cluster-topology-trace.webp β Cluster Topology on the 7100β7105 cluster fixture: three masters and three replicas with slots, health and dialed addresses, the footer confirming all 16,384 slots covered, and the Trace rows for one nodeTrace runs the same step-by-step check as Test Connection against each node - name lookup, tunnel or proxy with the node map, TCP, TLS, sign-in, protocol and ping, database, and cluster state - one row per step. A wrong node map entry, a blocked port, a TLS name mismatch or an ACL problem shows up as the first failing row.
What a cluster refuses, and why
Each of these is refused before it is sent, with a message that names the rule and the fix.
| Command | Why, and what to do instead |
|---|---|
| Multi-key commands across slots | MGET, MSET, a multi-key DEL, SUNION, RENAME and the like run only when every key is in one slot. Give related keys a common hash tag: user:{42}:profile and user:{42}:cart. |
SELECT other than 0 | A cluster has one logical database. Copy to Database… and MOVE point you to Copy to Connection… instead. |
KEYS and SCAN | KEYS would block every master and a SCAN cursor belongs to one node. Use the key browser or SQLLY.KEYS. |
MULTI / EXEC | Each command is routed on its own, so a transaction cannot stay on one node from the editor. |
Sentinel: the current master, every time
Turn on Connect through Sentinel, give the master name and the sentinels, and add a sentinel password if the sentinels require one. On every connect SQLly asks the sentinels in turn for the current master, checks that the server really is a master, and connects there; Test names the master and the sentinel that answered.
redis+sentinel://app:[email protected]:26379,10.0.0.2:26379/mymaster/2?sentinelPassword=s3cret
- Prefer replica for reads. Scripts made only of read-only commands run on a healthy replica; anything that writes runs on the master.
- Reads survive a failover. SQLly asks the sentinels again, once per script, and a read-only script re-runs the command that failed and carries on.
- Writes are never re-run. A script that writes stops with master changed, re-run and names the new master, because the write may have landed just before the old master went away.
redis-sentinel-test-result.webp β the connection editor with Connect through Sentinel on, master name mymaster and sentinel 127.0.0.1:26379, and the Test result naming the master that answered and the sentinel that named itWhat Sentinel and Cluster connections do not do yet
- Sentinel connections dial the sentinels, the master and the replicas directly, so SSH tunnels, proxies and Kubernetes port-forwards are refused, and relay routes do not support Sentinel yet. The Profiler and Pub/Sub viewer attach to the current master.
- On a cluster, a Kubernetes port-forward reaches only the seed node, and connections through a relay bridge do not support cluster mode yet.
- ElastiCache cluster mode and MemoryDB have not been tested against a live AWS instance.
ElastiCache cluster mode and MemoryDB
For ElastiCache in cluster mode, point the connection at the cluster’s configuration endpoint and use TLS Require or Verify full when in-transit encryption is on. MemoryDB is always a cluster and always TLS, takes its ACL user name in the Username field, and the Cluster Topology view lists its shards. Both route each command to the shard that owns its slot with the same rules as above. AWS manages their users, so the ACL page is not offered.
Questions about Cluster and Sentinel
Can SQLly connect to a Redis Cluster behind an SSH bastion?
Yes. On a connection with SSH hops or a SOCKS or HTTP proxy, SQLly opens a separate forward for every node the cluster names, through the same route, and the Cluster node map rewrites announced addresses the bastion or your machine cannot dial. A Kubernetes port-forward carries one port, so it reaches only the seed node.
What does the Cluster node map do?
Cluster nodes announce the addresses they were configured with, which behind NAT or a Docker port mapping are often private. One line per node, such as 10.0.0.5:7001 => 127.0.0.1:17001, tells SQLly where to dial instead, while the announced address keeps naming the node for redirects and as the TLS server name.
Why does SQLly refuse KEYS, SCAN or MGET on a cluster?
A cluster cannot run them as typed: KEYS would block every master, a SCAN cursor belongs to one node, multi-key commands need every key in one slot, a cluster has only database 0, and MULTI/EXEC cannot stay on one node from the editor. SQLly refuses them before sending, with a message naming the rule; give related keys a common hash tag such as {42}, or use the key browser.
What happens to a write when Sentinel fails over?
It is never re-run for you. SQLly asks the sentinels for the new master once and moves the connection there; a read-only script carries on, but a script that writes stops with "master changed, re-run", because the write may already have landed on the old master. Check, then run it again.
Can a Sentinel connection read from a replica?
Yes. With Prefer replica for reads on, a script made only of read-only commands runs on a replica the sentinels report healthy, and the master answers when none is. Anything that writes, uses SELECT, or reads server-wide information runs on the master. Replicas are asynchronous, so a read can briefly be older than the master's value.
Does SQLly work with ElastiCache cluster mode and MemoryDB?
Yes, by design: point an ElastiCache connection at the cluster's configuration endpoint, and MemoryDB is always a cluster, with the Cluster Topology view listing its shards. Neither has been tested against a live AWS instance yet.
Read more
From the blog
In the docs
Every node, one window
Free to start on macOS, Windows and Linux, no account required.