Highly Performant PHP Sessions with Redis
By: Ben Lobaugh
Tags: Scalability, Redis, Performance, PHP, Sessions

Photo by Green Chameleon on Unsplash

The web is stateless, but often the apps we build are not. To facilitate state in web apps, PHP provides a session handling mechanism. Sessions are off by default, and enabled with the `session_start()` function.

Read more about PHP session handling at https://www.php.net/manual/en/book.session.php

If you have worked with PHP sessions before you may have noticed performance issues caused by the `session_start()` function. On a small scale your app may be ok, but as you scale up issues will pop up. In particular, if the app makes several ajax calls back to the server during a page load there will see issues. This happens because PHP stores its sessions as files on the drive. During each request, PHP opens the session file for reads and writes. The file is locked during the request. That means if there are three ajax requests to the server, request two and three will be blocked waiting on the request in front of them.

By way of example, let’s assume the web server responds in 300 milliseconds for a single request and we have the initial request with three ajax requests that run asynchronously.

The load time should be:

300 ms initial request + 300 ms ajax requests = 600 ms

When using PHP’s default session the load time becomes:

300 ms initial request + 300 ms ajax request one + 300 ms ajax request two + 300 ms ajax request three = 1,200 ms or about 1.2 seconds!

And that is a light example. With content systems, such as WordPress, shipping with a built in API, it has become common practice to send many requests to the server during a single page load.

To get around the file locking issue we have to change the session storage mechanism. PHP provides the ability to write custom session handlers. We could do that, or we can tap into the Redis session handler. Redis does not have the locking issue, and it is already set up to be highly scalable. File based sessions are dubiously scalable at best.

To get it running all we need to do is update two lines in the php.ini file to instruct PHP to use Redis and where to find the Redis server. I will not cover how to set up a Redis server in this article.

Open the php.ini file and add or update the following two config values:

session.save_handler

session.save_path

The session.save_path value instructs PHP where to find the Redis server.

For example, the config values may look something like:

session.save_handler = redis

session.save_path = tcp://1.2.3.4:6379

Restart the PHP service and you will see sessions being stored in Redis instead of the filesystem.

If you do not have access to the php.ini file do not give up hope! It is also possible to set these values during the application runtime with the following PHP code:

ini_set('session.save_handler', 'redis');

ini_set('session.save_path', 'tcp://1.2.3.4:6379');

Make sure those two lines run before the session_start() function is called.

Depending on the server configuration, it may also be possible to set this in a .htaccess file.

Congratulations! Your users will now experience a considerable performance boost, and you have taken another step towards building a highly scalable and performant site.