I had a bit of trouble figuring out a scalable way to set up multiple Redis instances on a single Magento server. There are a few posts (1, 2, 3) that were helpful, but included too much manual setup for my purposes. They all also required starting/stopping all redis instances individually.
Note: I have not found a good way to make this work with Upstart. If your Redis installation is using Upstart and you would like to use this method, just move your /etc/init/redis-server.conf file to /etc/init/redis-server.conf.bak. When I figure out a good solution for Upstart, I’ll update this post.
I am using Ubuntu 12.04 LTS, but most of thisĀ applies to any distro. This setup shares a Redis default config among all servers. Each new server only requires that a server specific configuration file be created with only four required settings. All redis instances may be started at once with
service redis-server start
or each server may be started individually with
service redis-server start server1
. This works will all service commands.
Install Redis and PHP Redis Client
apt-get update; apt-get install -y php-pear php5-dev make redis-server; pecl install redis; echo 'extension=redis.so' > /etc/php5/conf.d/redis.ini; service php5-fpm restart; #If you are running PHP-FPM
Set Up Your Init Script
cd /etc/init.d; mv redis-server redis-server.bak; touch redis-server; chmod 0755 redis-server; nano redis-server;
Paste these contents:
#!/bin/bash ### BEGIN INIT INFO # Provides: redis-server # Required-Start: $syslog $remote_fs # Required-Stop: $syslog $remote_fs # Should-Start: $local_fs # Should-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: redis-server - Persistent key-value db # Description: redis-server - Persistent key-value db ### END INIT INFO if [ -n "$2" ] then NAME=$2 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/redis-server DAEMON_ARGS=/etc/redis/servers/$NAME.conf DESC=redis-server RUNDIR=/var/run/redis PIDFILE=$RUNDIR/$NAME.pid test -x $DAEMON || exit 0 set -e case "$1" in start) echo -n "Starting $DESC: " mkdir -p $RUNDIR touch $PIDFILE chown redis:redis $RUNDIR $PIDFILE chmod 755 $RUNDIR if start-stop-daemon --start --quiet --umask 007 --pidfile $PIDFILE --chuid redis:redis --exec $DAEMON -- $DAEMON_ARGS then echo "$NAME." else echo "failed" fi ;; stop) echo -n "Stopping $DESC: " if start-stop-daemon --stop --retry forever/QUIT/1 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON then echo "$NAME." else echo "failed" fi rm -f $PIDFILE ;; restart|force-reload) ${0} stop $2 ${0} start $2 ;; status) echo -n "$DESC is " if start-stop-daemon --stop --quiet --signal 0 --name ${NAME} --pidfile ${PIDFILE} then echo "running" else echo "not running" exit 1 fi ;; *) echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2 exit 1 ;; esac else FILES=/etc/redis/servers/* for f in $FILES do SERVERNAME=$(sed 's|/etc/redis/servers/||g' <<< $f) SERVERNAME=$(sed 's|.conf||g' <<< $SERVERNAME) /etc/init.d/redis-server "$1" "$SERVERNAME" done fi exit 0
Set Up Your Config
Default config file
cd /etc/redis; mkdir servers; cp redis.conf servers/server1.conf; cd servers; nano server1.conf;
Strip out all non server specific configuration from server1.conf. The remaining lines should include pidfile, port, logfile, and dbfilename. pidfile, logfile, and dbfilename should all match the server conf file name “server1″. The resulting file should look something like this:
# Redis server config include /etc/redis/redis.conf # When running daemonized, Redis writes a pid file in /var/run/redis.pid by # default. You can specify a custom pid file location here. pidfile /var/run/redis/server1.pid # Accept connections on the specified port, default is 6379. # If port 0 is specified Redis will not listen on a TCP socket. port 6379 # Specify the log file name. Also 'stdout' can be used to force # Redis to log on the standard output. Note that if you use standard # output for logging but daemonize, logs will be sent to /prod/null logfile /var/log/redis/server1.log # The filename where to dump the DB dbfilename dump-server1.rdb
Restart Redis instances:
service redis-server restart;
Additional Servers
To create new servers, simply copy the server1.conf file to server2.conf and update all relevant strings to your new server name (in this case, server2). If your server name is unique enough, you can just run the file through sed. You’ll also need to update the port manually to a new port.
cd /etc/redis/servers; cp server1.conf server2.conf; sed -i s/server1/server2/g server2.conf; grep -hR ^port . | sort; # Determine the highest used port number nano server2.conf; #Update the port number
Resulting file:
# Redis server config include /etc/redis/redis.conf # When running daemonized, Redis writes a pid file in /var/run/redis.pid by # default. You can specify a custom pid file location here. pidfile /var/run/redis/server2.pid # Accept connections on the specified port, default is 6379. # If port 0 is specified Redis will not listen on a TCP socket. port 6380 # Specify the log file name. Also 'stdout' can be used to force # Redis to log on the standard output. Note that if you use standard # output for logging but daemonize, logs will be sent to /prod/null logfile /var/log/redis/server2.log # The filename where to dump the DB dbfilename dump-server2.rdb
Start the new Redis instance(s):
service redis-server start;
Please let me know if you see any issues with this or have any suggestions. This seems to work for me very well so far.