How to talk raw Redis

Published

Find out how to talk to a Redis database with nothing more than echo and the netcat command and get a deeper understanding of why developers love Redis.

Redis has, as we've shown in the past, many many drivers. One of the reasons for situation is that, by design, Redis has a very simple protocol, RESP, for communicating with the server. Building on that simple protocol has allowed people to create these many drivers and their various levels of abstraction or idiomatic appropriateness. But let's talk about getting down to basics here; sometimes resource constraints demand you create the smallest possible connection code.

Our first command

For this example, we're going to get some status information from the Redis server; the INFO command returns lots of useful information so we will use that. Now, to send strings with Redis's RESP protocol, you need to say how long the string is. That's done by preceding your string with a $ and the number of characters in the string so that's 4 characters. After the number and after the string should be the carriage return and newline, \r\n. Let's build our string to send:

$4\r\nINFO\r\n

Redis's RESP also wants to know how many strings are in a command. It has a "bulk-strings" indicator which is like the $ operator, except uses a * and the number following it is the number of strings in the command. For this command, that's... 1. So we need to precede the string with *1.

*1\r\n\$4\r\nINFO\r\n

We can use the nc - net cat - command to send this string to our server. That server, for this example is at sl-eu-lon-2-portal.1.dblayer.com and on port 10030. If we echo our string and pipe it into nc we should get information:

$ echo -e "*1\r\n$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030

-ERR Protocol error: expected '$', got ' '
$

The problem here is the old classic shell thing of unexpected expansion. The shell sees that $ and wants to expand it from an environment variable $4 which is, of course, blank. We need to escape that and try again.

$ echo -e "*1\r\n\$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030
-NOAUTH Authentication required.
$

Time to log on

Because who would put a completely open Redis server up on the internet. The Compose Redis servers start up with authentication on and a 16 character password set. If you are doing this against a server that you own and it worked, check now that that server isn't externally visible. Other people do not value your data. Anyway, back to getting authenicated. We need to construct another command, the AUTH command and follow it with our password. This time, there's two strings in the command, the AUTH command itself and the password, let's say it's FLIBBERTIGIBBETS for now. That gives us *2\r\n\$4\r\nAUTH\r\n\$16\r\nFLIBBERTIGIBBETS\r\n which we can put into the front of out command now:

$ echo -e  "*2\r\n\$4\r\nAUTH\r\n\$16\r\nFLIBBERTIGIBBETS\r\n*1\r\n\$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030
+OK
$2306
# Server
redis_version:3.2.6  
redis_git_sha1:00000000  
redis_git_dirty:0  
redis_build_id:dafadbf6141a77d5  
redis_mode:standalone  
os:Linux 3.19.0-39-generic x86_64  
arch_bits:64  
multiplexing_api:epoll  
gcc_version:4.8.4  
process_id:36  
run_id:275d6af5f6ccf9be4efde1dbcb8223483386cf42  
tcp_port:6379  
...
$

That goes on for a little while... There are 2,306 characters of information in total. We know that because that's the first thing Redis told us. In the same way, as we tell it how long strings are, it does the same back, so the second line, $2306 is telling us how many characters are coming back. That's the response to the INFO command. Immediately preceding that is +OK, the response to the AUTH command. The + is the signal that this is a simple non-binary safe string; a minimal OK.

Let's make it tidy

Anyway now we can pipe those results to any command we want for post-processing. Add a | tail -n +3 to chop off the Redis RESP responses and we have a clean output, just like entering INFO at the redis-cli command line. We're good people and good people don't leave passwords in shell scripts. Let's pop the password into an environment variable...

export REDISAUTH="FLIBBERTIGIBBETS"  

And change the command to use that. This time we want that shell expansion to happen.

echo -e "*2\r\n\$4\r\nAUTH\r\n\$16\r\n$REDISAUTH\r\n*1\r\n\$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030  | tail -n +3  

Now the command is sharable without giving away your password. There's one last thing to do for this example. That INFO data is quite a lot to work through and we only really, say, want the STATS section. That's not a problem, we just need to add that to the INFO command, first by bumping the string count at the start of the command to 2 and then appending \$5\r\nSTATS\r\n to the end.

$ echo -e "*2\r\n\$4\r\nAUTH\r\n\$16\r\n$REDISAUTH\r\n*2\r\n\$4\r\nINFO\r\n\$5\r\nSTATS\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030  | tail -n +3
# Stats
total_connections_received:1700495  
total_commands_processed:40375802  
instantaneous_ops_per_sec:7  
total_net_input_bytes:1984826397  
total_net_output_bytes:2497942423646  
instantaneous_input_kbps:0.41  
instantaneous_output_kbps:1.10  
rejected_connections:0  
sync_full:5  
sync_partial_ok:0  
sync_partial_err:0  
expired_keys:0  
evicted_keys:0  
keyspace_hits:194  
keyspace_misses:6  
pubsub_channels:1  
pubsub_patterns:0  
latest_fork_usec:469  
migrate_cached_sockets:0  
$

Now we just have our statistics. And it's still one shell command.

What this gets us

You'll note that the Redis RESP protocol is remarkably simple. You can find out more about it on the RESP specification page. There are some other response types (- for an error, which we saw when we got the NOAUTH message and : for integers) and some other rules to take note of but it's also pretty simple to code for.

If you have a new language on your hands and no Redis driver, it is good to know that the protocol is so simple and readily implementable in even the most constrained of languages. As long as you can open a TCP socket to a port and read/write to it, you are good to go.

This should also help explain the types of Redis drivers that are around. The minimalist drivers basically provide enough to make sending commands to and receiving data from Redis; the user of the driver sends the strings for the commands.

Also, it's got its uses in the Internet of Things. In a future article, we'll be looking at that when we add Redis stats gathering (among other things) to a very resource-constrained device. Until then, have fun going low with Redis.


If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at articles@compose.com. We're happy to hear from you.

attributionPatrick Hendry

Dj Walker-Morgan
Dj Walker-Morgan is Compose's resident Content Curator, and has been both a developer and writer since Apples came in II flavors and Commodores had Pets. Love this article? Head over to Dj Walker-Morgan’s author page to keep reading.

Conquer the Data Layer

Spend your time developing apps, not managing databases.