I’ve been using memcached to store session data for the past while, but we ran into a few problems at work that led me to dive in a bit deeper and see how PHP, Sessions, and memcached play along.
Short Version
When you start up a session a new entry is created in memcache, the expiry is the same as session.gc_maxlifetime. Session data is retrieved each time a session is started (either with session_start(), or if you have session.auto_start enabled, etc).
Long Version:
When session_start() is called for a new user several things happen very quickly:
- A session ID is generated for the end user, this is seen in the HTTP response headers.
HTTP/1.x 200 OK
Date: Fri, 10 Jul 2009 16:07:21 GMT
Server: Apache/2.2.11
X-Powered-By: PHP/5.2.6-3ubuntu4.1
Set-Cookie: PHPSESSID=c446fc5309c3b8d3aa6e90343dddab29; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 23
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html
- PHP Contacts memcached and attempts to retrieve any information in that particular session ID
get c446fc5309c3b8d3aa6e90343dddab29
- Memcached returns no data for that entry, as it doesn’t exist yet.
- Your page executes, setting data in the session
- PHP pushes data into memcached:
set c446fc5309c3b8d3aa6e90343dddab29 0 1440 32 name |s:6”asdasd;bar|s:3:”foo”;
On every subsequent page where a session is used, a very similar sequence of events is executed. When the session is started PHP contacts memcached and asks for the session data. When the page is complete it pushes the data now in the session to memcached.
That last step is kind of critical, because it’s what’s controlling the expiry of the data within memcached. Take a quick look at the data being set once more.
set c446fc5309c3b8d3aa6e90343dddab29 0 1440 32 name |s:6”asdasd;bar|s:3:”foo”;
Data is being set, the key is your session id, 0 is a set of flags that the client can use to mark the data (often used to mark data that’s been compressed). The 1440 represents the expiry time for the data, 1440 seconds from now (24 minutes). That value was taken directly from session.gc_maxlifetime . It’s important to keep in mind that what memcached guarantees is that the data will not be available after that expiry runs out, but it promises nothing about how long it will be available. If your memcached instance crashes, or runs out of memory you’re going to start losing data a lot sooner. Finally we have the data in a somewhat truncated version of PHP’s serialize.
The fact that the data is sent to memcached after every request, even if you haven’t changed what’s stored in the session, is rather important. It’s what makes your session last for session.gc_maxlifetime after the user last did something, rather than simply that amount plus the last time you requested a document.