Setting up Multiple Redis Instances on Mac OS X
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
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
$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
- The launch agent label. This should match the file name, minus the
<key>Label</key> - <string>homebrew.mxcl.redis</string> + <string>USER.APPNAME.redis</string>
- The configuration file path. We will copy and edit the
.conffile 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
# 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