Call us Toll-Free:
1-800-218-1525
Live ChatEmail us

 Sponsors

Memcached for PHP Sessions

Dawn Rossi, 10-14-2008
Sessions are a great way to store data pertaining to a single end-user browsing through your site, before the user logged in.

Each user is assigned a unique ID and that ID serves as the key to a dataset, where you can store the user name, email address, referral, affiliate_id etc.

Since sessions are accessed on every page load, it is important to optimize the amount of time it takes to read/write sessions.

PHP sessions can typically be stored as either files or database records.

Files are fast, but don't allow you to scale beyond a single server.
Database records support scaling but are "expensive" to read/write.

As part of this post, I will walk you through the process of using Memcached for PHP sessions.

Memcached is a very efficient in-memory database that supports scaling to multiple machines, expiration and built-in garbage collection. We're going to hit Memcached first on all session queries. If we don't have a match, we read it from the database (once) and store the information into Memcached for later fast retrieval.

Step 1: Install Memcached

Step 2: We're going to use PHP function overrides feature and define new session handling functions. Save dbsession.php in your includes directory and replace all references to "payments" with the name of your global database.

Step 3: Create the sessions table under your global database:


CREATE TABLE sessions
(
session_expire int(11) unsigned NOT NULL DEFAULT '0',
session_value longtext,
session_key char(32) NOT NULL DEFAULT '',
PRIMARY KEY (session_key)
)

Step 4: Save common_cache.php under your includes directory. This file is used by dbsession.php and serves as the wrapper class for accessing the Memcached server. Update the array at the top of common_cache.php with the ip addresses of your Memcached servers. You can have multiple Memcached servers and as long as they're all aware of each other, everything will scale gracefully.

Step 5: Include dbsession.php at the top of your php files (or add it to one of your global includes that is included everywhere). Make sure you include dbsession.php before the first call to session_start

All it takes is a single include at the top of your php files and voila - all sessions are now handled by Memcached first, then reverting to the database if no match found.


require_once("dbsession.php");

James, 10-20-2008
This article confuses me. Why on earth try re-inventing the wheel and writing your own session handler for memcache when you can use the one that the PECL memcache module ships with?

if(MEMCACHE_HAVE_SESSION) {
ini_set('session.save_handler','memcache');
ini_set('session.save_path', <session save path info>);
} else {
// fall back to a db session
}


Unfortunately I don't think that the author has a firm grasp of memcached and/or sessions.

George, 10-24-2008
James,

Your approach would fall back to a db session upon a memcache miss. It doesn't handle reading data from the db, and updating memcache to retain the speed advantage of using memcache. Dawn's approach is designed to use memcache in all instances and update the memcache contents from db in the case of a cache miss. The session handler in the PECL memcache does not do this.

Dawn Rossi, 10-31-2008
Thank you George,

You got it!

We have been implementing Memcached for PHP sessions for a few years now. I'd like to think we know a thing or two about how to get the most out of Memcached.

Sung, 11-17-2008
Functions in common_cache.php doesn't seem to be used in dbsession.php. For example, who calls mcache_connect()? Could you give me an explanation kindly?

Sung, 11-18-2008
One more thing.
Whenever a client JUST reads session variable, sessionWrite() is called to update session expiration time. Thus, it seems that this rarely utilizes memcached.

Caner, 12-17-2008
Can we use this method on a multi-server architecture?

John, 04-17-2009
We are using this exact same approach for our session handling using memcached. it's working brilliantly. However, we are receiving the occasional random logout. As if memcached returned true but didn't actually have the sessionid stored. Has this ever happened to you? Here is an example of our session read() function:

function read($sessionID) {
$db =& $this->_db;
$cache =& $this->_cache;
if($cache->get(CACHE_SESSION . $sessionID) !== false) {
return $cache->get(CACHE_SESSION . $sessionID);
} else {
$sql = "SELECT value FROM session WHERE sessionid = ? AND expiration > ?";
return $db->getOne($sql, array($sessionID, time()));
}
}

Phil, 05-03-2009
Interesting article, however wouldn't the fact you are still doing at least a write to the database every time kinda defeat the object of using memcache? That database write will always be the bottleneck for this script. The PECL memcache package supports writing PHP sessions to multiple memcache servers which is probably best for a redundant solution.

Mike Peters, 06-09-2009
Caner -

Absolutely. This approach is specifically designed to support multi server architecture.

John -

We're not seeing any issues with this method. You may want to check your code and make sure you are calling session set save handler in all places. Otherwise, your web server will be reverting to 'files' session handling. That could possibly explain what you're seeing.

Phil -

Memcached is first checked for the session value. If Memcached has it, no db access is ever initiated.

Mike, 06-23-2009
Do you think we can have an example of using this ?

As in a test login form maybe with the test table for logins/etc

Anton, 07-18-2009
A short treaty on high-performance session caching.

Using memcached for sessions is naive (faster is not always better) and prone to huge issues with random log-outs. In-fact, as your site become more critical and has higher traffic then although it is counter intuitive you need to abandon RAM based caching solutions as users will quickly overwhelm the available storage. Database sessions provide a reasonably robust solution for badly designed server farms that do not use consistent server forwarding for a given user. Consistently forwarding a given user to a given server using file sessions is more efficient, with the only issue being the potential loss of the server and hence a random logout when another working server is selected - but that is a 'blue-moon' issue. However, this issue is tiny in comparison to the loss of the session server database storage which would take down the entire site.
There is also the option of using MCache sessions which access a session server. Distributed session servers are the best option for high-traffic multi-server installations and require only simple server forwarding rules. Distributed = robust, and caching is multi-level moving from RAM to disc and eventually to oblivion (GC) as usage of the session data ages through lack of access.

In the end each solution has a number of points of failure. Memcached is better used for less critical and far more efficient caching of data that can easily be recreated without user intervention. An extra moment to re-cache a lost page or query result is of no consequence to a user; having to log in again because session data was lost is highly annoying and leads to users giving up on the site (Google 'evony login' for a high profile example)

Overall experience in server farms using from ten to over five hundred servers has led us to this recommendation.

1. Make sure your load balancing rules send the same user to the same server consistently. This results is very efficient use of both database and memory caching. This allows for efficient file caching of sessions using the power of disc caches.

2. Even if you can do (1) above then there is still merit in using some form of persistent and properly garbage collected session caching. memcache and memcached both will create random log-outs for users and should be avoided for reasons given in the narrative.
Database session handling is robust across multiple servers, but its speed (or lack thereof) is the reason for this entire discussion.
Here mcache (which does *not* stand for memory cache) provides a session server with all the benefits of both memory caching for recent sessions and disc backup for swapped out session data.
Of course, the overhead in setting up mcache is higher - you may actually have to read a manual rather than using someone else's example from the interweb ;-)

Anton, 07-18-2009
One typo above - I meant to say '...abandon RAM ONLY based caching solutions...'

I realised the original text read as if I was bashing Dawn's solution, which was certainly not the intent!

Richard Ford, 09-16-2009
My issue is that on a cluster I have enabled memcached for sessions (was already using it for db query caching) and it works fine. This is done changing /etc/php.ini

The problem comes with other support sites on the same cluster that don't have memcache support.

So how can one set a per virtual host memcache or file or db session use?

I would have thought a php override in the virtual host .conf fragment - but that does not work either...

:-(

Jane, 09-22-2009
James, you jerk! how dare you be so idiotic and assume that Dawn doesn't know what she is talking about because she has tits. I think tits are realted to greater brain capacity.
Enjoyed this post?

Subscribe Now to receive new posts via Email as soon as they come out.

 Comments
Post your comments












Note: No link spamming! If your message contains link/s, it will NOT be published on the site before manually approved by one of our moderators.



About Us  |  Contact us  |  Privacy Policy  |  Terms & Conditions