High-performance centralized PHP session storage - php

My application can store up to dozens or even low hundreds of KB of data in the session. I'm currently storing PHP sessions in MySQL blobs, and traffic volume is now putting session-related queries on the database around 25-75 per second. It's causing some problems.
Is there a centralized storage option for PHP sessions of this size that will perform well? I'd prefer to avoid sticky sessions at the load-balancer level if possible for other performance reasons. I can try to reduce the session size, but regardless I'm going to need this information on most requests, so I'm going to have to stash it somewhere.

Scache is ideal for that. You can probably split your session data to smaller parts, some might even be cacheable to all sessions and so on. Scache has api for all that.
There's nothing bad in big session data, it's bad only if you store it to $_SESSION.

memcached is always a favorite option.
The memcache PHP extension helpfully comes with a session handler that will store sessions with memcached.

Zend's own session cluster daemon:
http://www.zend.com/en/products/server-cluster-manager/high-availability

Related

redis vs native sessions

I am using sessions in PHP to track if a user is logged in. I do not use it to store any other data about the user; essentially it is like checking a hash table to see if the user has authenticated.
Would there be some advantage to using redis instead of native PHP sessions?
I'm curious about performance, scalability, and security (not really concerned with code complexity).
Using something like Redis for storing sessions is a great way to get more performance out of load balanced servers.
For example on Amazon Web Services, the load balancers have what's called 'sticky sessions'. What this means is that when a user first connects to your web app, e.g. when logging in to it, the load balancer will choose one of your app servers and this user will continue to be served from this server until they exit your application. This is because the sessions used by PHP, for example, will be stored on the app server that they first start using.
Now, if you use Redis on a separate server, then configure your PHP on each of your app servers to store it's sessions in Redis, you can turn this 'sticky sessions' off. This would mean that any of your servers can access the sessions and, therefore, the user be served from a different server with every request to your app. This ultimately makes for more efficient use of your load balancing set-up.
You want the session save handler to be fast. This is due to the fact that a PHP session will block all other concurrent requests from the same user until the first request is finished.
There are a variety of handlers you could use for PHP sessions across multiple servers: File w/ NFS, MySQL Database, Memcache, and Redis.
The database method (using InnoDB) was the slowest in my experience followed by File w/ NFS. Locking and write contention are the main factors. Memcache and Redis provide similar performance and are by far the better alternatives since all operations are in RAM. Redis is my choice because you can enable disk persistence, and Memcache is only memory based.
I explain Redis Sessions in PHP with Kohana if you want more detail. Here is our dashboard for managing Redis keys:
I don't really think you need to worry much about sessions unless you get MASSIVE ammounts of traffic, PHP handle sessions nicely, and if you store only that little data, it should be fine even with a lot of requests, and about performance it should be close, as redis is not native to PHP.
With 10k users, if each user uses like 1kb data of sessions, it would consume 10,000kb or 10~mb, which is not much; PHP is smart enough to use a good enough data structure to hold and quickly write and read those values. The problem is if the session data is too big, or for some reason the server consumes too many resources reading the session data, but that's normally if it's the data is too big.

What are the implications of storing large amounts of data in the session cookie?

Could anyone explain disadvantages of storing large amounts of data within the session or point me to some reading ?
I would also be interested if there is any difference between storing data in a session and reading data from datafiles ?
If you store a large amount of data within a session, you'll have input/output performance drops since there's going to be a lot of reading/writing.
Sessions in PHP, by default, are stored in /tmp directory in a flat file. Therefore, your session data is written in a data-file of some sort.
PHP allows you to override its default session handler by session_set_save_handler() function where you can redefine the way sessions are read / written / maintained.
You can also override this via php.ini file where you specify it via session.save_handler directive.
Now, the implication of having a large number of sessions storing large data is that a lot of files will be created and it will take some time to find them due to the ways hard drives operate (mechanical ones of course, which are the common ones still).
The more you have, the longer it takes to find it. The larger they are, longer it takes to read it. If you have a lot of them and they are large - double the trouble, a change in approach is needed.
So what's the solution?
Usually, when met with performance drop - people load balance their websites. That doesn't work with sessions unfortunately because load balancing is choosing which computer to use that will serve the current request. That means that different computers will serve pages you browse at some website. Which means, if those computers use default mechanism of session storage (/tmp directory), the sessions will not be preserved across the servers since they cannot access each other's /tmp directory.
You can solve this by mounting a NAS and making it globally visible to all of the computers in the cluster, but that's both expensive and difficult to maintain.
The other option is to store the sessions in a database. A database is accessible from any of the computers in our fictional cluster. Usually, there are specialised databases used for handling sessions, specialised in sense of being separate from the database storing your website content or whatever.
In the time of NoSQL popularity - in my opinion, NoSQL is great for handling sessions. They scale easily, they are faster in writing the data to storage devices than RDBMSs are.
Third option is to boost all of this, ditch hard drives as permanent storage solution and just use your server's memory for session storage.
What you get is incredible performance, however all your RAM might be quickly gone.
You can also create a cluster of computers that store sessions in their RAM.
Redis and Memcache are great for this task, googling a bit will give you good resources that explain how to use Redis or Memcache to store sessions.
Bottom line of all this is: don't store too much data in your sessions.
According to your needs and budget - there are 3 options available how to store and work with sessions.
This is a good link: http://tuxradar.com/practicalphp/10/1/0
Session data is very expensive workload too. The best way to do it is to store a cookie, or session_id and use that to look up what you need from a dbfile/rdbms. This also allows your site to run across a multi-server environment where as session data is limited to a single.

mySQL AND memcached for PHP sessions?

For a high traffic web site we are planning to scale up to use 2 web servers in a HA setup.
One issue we will need to tackle is the management of PHP sessions.
The obvious answer is to move session handling to the DB which is easy and example code is widely available ton the internet.
On the other hand we are aware of the benefits of memcached but once a memcached node fails, users on that node will lose their session.
So we are thinking of implementing a setup where sessions are handled in memcached by default but also written in the DB. When we get a memcached MISS we would try to also retrieve it from the DB.
Does the above make sense and are there any implementation examples you are aware of?
thanks in advance
I refer you to Dormando's oft-cited explanation of how to store sessions in MySQL with memcached caching. The original LiveJournal post is more wordy but more thoroughly explains why storing sessions in memcached only is a bad idea.
In short:
Read session data from memcached first, look in MySQL on a cache miss.
Write session data to memcached on every update.
Only write to MySQL if cache data hasn't been synced for 120 seconds or so.
Run a periodic script that checks MySQL for expired sessions. For every expired session, update from memcached and only expire the ones that are truly expired.
Sessions it's a temporary thing, there is nothing to worry about if once per month memcache-server will fail and truncate sessions. I'm sure you can use just memcache for sessions, without replication in DB.
But if you still want to dump sessions to disk, as existing solution you can use Redis:
Redis works with an in-memory dataset.
Depending on your use case, you can
persist it either by dumping the
dataset to disk
...
Redis also supports trivial-to-setup master-slave replication, with very
fast non-blocking first
synchronization, auto-reconnection on
net split and so forth.

Using cache systems for session storage?

Say I have a caching system that i can use for storing sessions:
// example i have a cache class
$memcached->add('key','value');
// then i can get the session from
$memcached->get('key');
What are the advantages and disadvantages of using caching (e.g. memcached, maybe Redis can fit in, or other things) for sessions rather than using PHP's built-in sessions?
I want to start by clarifying. When you're using PHP session storage, the sessions are being stored in a file (usually in /tmp). Each session becomes it's own file.
When you use memcached or redis to store sessions, nothing in your PHP code changes.
You can simply configure php to use redis or memcache to store the sessions instead (configured via session save handler in php.ini).
Pros:
session storage/retrieval becomes much much faster
cons:
you need to configure php.ini (or implement the session save handler yourself)
now, I would actually recommend using redis instead of memcache, simply because the sessions will become permanent, so if you need to reboot the server, all your users wont get logged out.
For redis:
https://github.com/owlient/phpredis (see "session handler" lower on the page)
You should be able to have PHP store session data in Apache's runtime memory by setting session.save_handler to mm. However, to do this you need to compile PHP with the memory management module (--with-mm), which I don't think is available for Windows.
If you want to use memcached or some other caching mechanism, then it'd probably be best to implement user-defined storage handlers using session_set_save_handler so you don't have to rewrite your session management code.
If you do that, then I don't think there are any obvious disadvantages to storing session data in that way. The obvious advantage is speed.
Edit:
I came across this page which discusses, aside from speed, the main advantages/disadvantages of using memcached for storing sessions, namely:
It's easy to share sessions across multiple webservers without using sticky sessions.
However, memcached makes no promises of keeping the data up until expiration—only that the data will not be available after expiration. So if memcached is low on ram, hasn't been used lately, or the server goes down at all, the session data will be lost.

Are there problems using PHP sessions in a server cluster?

We are developing a web site in PHP, and we have to use sessions. The site will be published in a server cluster. How can we make that work?
Thanks.
Yes this is possible, you need to store your sessions in a central location like a database though. This is pretty simple and just requires you to make some changes to session_set_save_handler - there's a good example of the process you need to follow here
I would use memcache to store your sessions. It will be much faster than storing them in a database or disk.
Database storage is good but you will need more databases when your site becomes very high traffic. Sessions on disk will also cause a lot of IO issues when your site gets a lot of traffic. Memcache on the other hand scales much better than a DB and files.
I personally use memecache and the sites i work on get millions of hits a day. I have never had any issues with storing sessions in memcache.
If you've got multiple PHP boxes, you'll want a central session store.
Your best choices are probably database (that link from seengee's answer is a good explanation) or a dedicated memcache box.
A shared NFS mount for the session directory would be an option, though I've always found nfs performance a bit slow. Alternatives are to write your own session handler using memcache or database for the sessions.
An alternative option is to load balance your web servers using sticky sessions, which will ensure that requests from the same client always go to the same server during the course of the session.

Categories