Setting up Multiple Redis Instances on Mac OS X
2020-06-07
The recommended way to use Redis in a dev environment is to install and run multiple instances. Redis does ship with some rudimentary namespacing support--a connection can switch "databases'', but the utility of this approach is limited, mainly by the fact that Redis databases cannot be named, only numbered 0 through 15. In a production deployment, you will have one Redis instance per application. In the interest of having your development environment match production as closely as possible, it makes sense to run multiple redises locally, and have the development configuration connect directly via a localhost port. Note that this is not how I recommend to work with a local RDBMS such as Postgres, where in production you will specify a named database. Therefore, passing a database name involves no extra code complexity with Postgres, whereas with Redis it does.
First, install Redis using brew
, if you don't have it already. The brew
installation will also install a .plist
file at the appropriate location for Redis to be started on system startup. This file can be found by running brew services list
--it should be in the ~/Library/LaunchAgents/
directory. This directory contains service specifier files
for processes to run on system launch. We're going to copy it and create a duplicate Redis instance to run alongside the
one managed by Homebrew.
Copy the Homebrew plist
file to the same directory, and give it a different name. I did something like
cp ~/Library/LaunchAgents/homebrew.mxcl.redis.plist ~/Library/LaunchAgents/$USER.$APPNAME.redis.plist
where $APPNAME
is the name of the application I want to run an extra Redis instance for. Now we need to edit some
key/value pairs in the .plist
file:
vim ~/Library/LaunchAgents/$(whoami).${APPNAME}.redis.plist
- The launch agent label. This should match the file name, minus the
.plist
suffix.
<key>Label</key>
- <string>homebrew.mxcl.redis</string>
+ <string>USER.APPNAME.redis</string>
- The configuration file path. We will copy and edit the
.conf
file in the next step.
<string>/usr/local/opt/redis/bin/redis-server</string>
- <string>/usr/local/etc/redis.conf</string>
+ <string>/usr/local/etc/redis-APPNAME.conf</string>
<string>--daemonize no</string>
- The log file path:
<key>StandardErrorPath</key>
- <string>/usr/local/var/log/redis.log</string>
+ <string>/usr/local/var/log/redis-APPNAME.log</string>
<key>StandardOutPath</key>
- <string>/usr/local/var/log/redis.log</string>
+ <string>/usr/local/var/log/redis-APPNAME.log</string>
Now that we have a service specifier ready to go, we need to make sure that the configuration file points to something.
cp /usr/local/etc/redis.conf /usr/local/etc/redis-$APPNAME.conf
vim /usr/local/etc/redis-$APPNAME.conf
You'll need to edit the port. Hopefully this is obvious, but please enter a real port, not the literal string "$PORT".
You can just use the 6380-6390
block to make it easy to remember which block of ports your Redis instances are
listening on:
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
-port 6379
+port $PORT
You may also want to require a password for connections. This is in line with trying to make our development environment as similar as possible to production:
-requirepass foobared
+requirepass $MYSTRONGPASS
Store that password in a password manager, not in a version control system. The development environment password leaking is not such a big deal, but it's good to build the muscles of devops practice.
Save the modified configuration file, and start the Redis instance:
launchctl load ~/Library/LaunchAgents/$USER.$APPNAME.redis.plist
launchctl load $USER.$APPNAME.redis
launchctl start $USER.$APPNAME.redis
You should be able to tail the log file and see that everything is okay, and Redis is accepting connections.
tail -f /usr/local/var/log/redis-$APPNAME.log