Stop Writing to Disk: Accelerating PHP Sessions with Redis
If you have ever watched top on a busy Friday afternoon and seen your CPU wait percentage (wa) spike while your load average climbs through the roof, you know the panic. You check the MySQL process list—it's clean. You check Apache—it's serving requests. So what is choking the server?
Nine times out of ten, on a high-traffic PHP application (like Magento or Drupal), it is the session handler. Default PHP setups write session data to flat files in /var/lib/php/session. On a site with concurrent users, the file locking overhead and disk I/O thrashing can bring even a powerful server to its knees.
It is 2010. We have better options than flat files. While Memcached has been the standard for years, there is a new player gaining traction that solves Memcached’s biggest flaw: lack of persistence. That player is Redis.
The Disk I/O Bottleneck
Here is the reality of spinning rust—even the 15k RPM SAS drives we use in enterprise arrays. Every time a user loads a page, PHP locks a session file, reads it, executes code, writes back to the file, and unlocks it. Multiply that by 500 concurrent users.
If you are hosting on a budget VPS provider where you share a spindle with fifty other noisy neighbors, your seek times destroy your Time To First Byte (TTFB). This is why at CoolVDS, we are aggressively rolling out Enterprise SSD storage tiers for our KVM instances in Oslo—because IOPS matter. But even with SSDs, memory is orders of magnitude faster.
Why Redis over Memcached?
Memcached is fast. But if you restart the Memcached daemon (or the server reboots), poof—every logged-in user is kicked out. Shopping carts are emptied. Customers are angry.
Redis (currently version 1.2.6) offers the speed of in-memory operations but allows us to snapshot data to disk asynchronously. You get the performance of RAM with the durability of a database.
Configuring Redis for Sessions
First, get Redis running. On a standard CentOS 5 or Debian Lenny box, you'll likely need to compile from source as it's not in the standard repos yet.
$ wget http://redis.googlecode.com/files/redis-1.2.6.tar.gz
$ tar xzf redis-1.2.6.tar.gz
$ cd redis-1.2.6
$ make
$ sudo cp redis-server /usr/local/bin/
$ sudo cp redis-cli /usr/local/bin/
Once installed, configure your redis.conf to handle persistence intelligently. We don't need AOF (Append Only File) for sessions; RDB snapshots are sufficient.
# /etc/redis.conf
daemonize yes
port 6379
timeout 300
# Save the DB on disk:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
save 900 1
save 300 10
Connecting PHP to Redis
Native support isn't in PHP core yet. You have two choices: the pure PHP library Predis or the C-extension phpredis (which requires PECL). For raw performance on a high-load production server, I recommend compiling the C-extension.
However, for a quick implementation using a custom session handler in your code, you can use the logic below. This bypasses the default file handler entirely.
class RedisSessionHandler {
private $redis;
public function __construct(){
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function open($savePath, $sessionName) {
return true;
}
public function close() {
return true;
}
public function read($id) {
return $this->redis->get("session:$id");
}
public function write($id, $data) {
// Expire session after 1 hour (3600 seconds)
$this->redis->set("session:$id", $data);
$this->redis->expire("session:$id", 3600);
return true;
}
public function destroy($id) {
$this->redis->del("session:$id");
return true;
}
public function gc($maxlifetime) {
// Redis handles expiration natively, no GC needed
return true;
}
}
$handler = new RedisSessionHandler();
session_set_save_handler(
array($handler, 'open'),
array($handler, 'close'),
array($handler, 'read'),
array($handler, 'write'),
array($handler, 'destroy'),
array($handler, 'gc')
);
Pro Tip: If you are running multiple web servers behind a load balancer (like HAProxy), point all your PHP nodes to a single Redis instance on a private LAN. CoolVDS offers private backend networking between VPS instances, which is perfect for this. It keeps latency low and data secure within the Norwegian jurisdiction, satisfying the Datatilsynet requirements.
The Results
By moving sessions to Redis, we eliminate file locking. I recently migrated a client from a standard LAMP stack to a Redis-backed session architecture. Their Wait I/O dropped from 35% to nearly 0%, and page generation times improved by 200ms.
However, remember that Redis stores everything in RAM. If you have 100,000 active sessions and each is 10KB, you need 1GB of RAM just for sessions. Plan your instance sizing accordingly.
Final Thoughts
File-based sessions are a relic of the past. If you are serious about performance, you need to be in memory. Redis provides the bridge between the speed of Memcached and the reliability of disk storage.
Need a sandbox to test this out? CoolVDS allows you to spin up a clean Debian or CentOS instance in under a minute. Our servers are located right here in Norway, connected directly to NIX for the lowest possible latency to your local users. Don't let your infrastructure be the bottleneck.