Entries tagged as memcached
Related tags
memcache mysql mysql cluster mysql56 oracle performance php php session scalability acquisation buffer christmas closures coding conferences cta debugging development dtrace froscon froscon10 fun google goto gsoc gsoc09 ide improvements information_schema ipc ipc08 ipc10 iterator job json launchpad memcche mysql 8.0 mysql analytics mysql fabric mysql js mysql json mysql plugins mysql proxy mysql storage engine mysqlde mysqli mysqlnd mysqlnd plugins mysqlnd_ms berkeley db database db php extensions sqlite sqlite3 storage virtualbox virtualization vmdk zfs zvol api design best practice guidlines oop php 4 php 7 php coding php oo php references planet php .net ajax anniversary apc array assembler barcamp bazaar bc beer garden berlin birthday boredom c# charsets comments commits computer science 101 cvs data center delphi dsp easter ego encoding english events exception file upload froscon08 php.nextNov 17: High Performance PHP Session Storage on Scale


One of the great things about the HTTP protocol, besides status code 418, is that it's stateless. A web server therefore is not required to store any information on the user or allocate resources for a user after the individual request is done. By that a single web server can handle many many many different users easily, and well if it can't anymore one can add a new server, put a simple load balancer in front and scale out. Each of those web servers then handles its requests without the need for communication which leads to linear scaling (assuming network provides enough bandwidth etc.).
Now the Web isn't used for serving static documents only anymore but we have all these fancy web apps. And those applications often have the need for a state. The most trivial information they need is the current user. HTTP is a great protocol and provides a way to do authentication which works well with its stateless nature - unfortunately this authentication is implemented badly in current clients. Ugly popups, no logout button, ... I don't have to tell more I think. For having nicer login systems people want web forms. Now the stateless nature of HTTP is a problem: The user may login and then browse around. On later requests it should still be known who that user is - with a custom HTML form based login alone this is not possible. A solution might be cookies. At least one might think so for a second. But setting a cookie "this is an authorized user" alone doesn't make sense as it could easily be faked. Better is to simply store a random identifier in a cookie and then keep a state information on the server. Then all session data is protected and only the user who knows this random identifier is authenticated. If this identifier is wisely chosen and hard to guess this works quite well. Luckily this is a mostly PHP- and MySQL-focused blog and as PHP is a system for building web applications this functionality is part of the core language: The PHP session module.
The session module, which was introduced in PHP 4, partly based on work on the famous phplib library, is quite a fascinating piece of code. It is open and extendable in so many directions but still so simple to use that everybody uses it, often newcomers learn about it on their first day in PHP land. Of course you can not only store the information whether the user is logged in but cache some user-specific data or keep the state on some transactions by the user, like multi-page forms or such.
In its default configuration session state will be stored on the web server's file system. Each session's data in its own file in serialized form. If the filesystem does some caching or one uses a ramdisk or something this can be quite efficient. But as we suddenly have a state on the web server we can't scale as easily as before anymore: If we add a new server and then route a user with an existing session to the new server all the session data won't be there. That is bad. This is often solved by a configuration of the load balancer to route all requests from the same user to the same web server. In some cases this works quite ok, but it is often seen that this might cause problems. Let's assume you want to take a machine down for maintenance. All sessions there will die. Or imagine there's a bunch of users who do complex and expensive tasks - then one of your servers will have a hard time, giving these users bad response times which feels like bad service, even though your other systems are mostly idle.
A nice solution for this would be to store the sessions in a central repository which can be accessed from all web servers.
Read MoreApr 14: Not only SQL - memcache and MySQL 5.6

This week there are two big events for the MySQL community: The O'Reilly MySQL Conference and Oracle Collaborate run by the IOUG. At these events our Engineering VP, Tomas Ulin, announced the latest milestone releases for our main products. MySQL 5.6 and MySQL Cluster 7.1 as well as our new Windows Installer. There's lots of cool stuff in there but one feature really excited me: MySQL 5.6 contains a memcache interface for accessing InnoDB tables. This means you can access data stored in MySQL not only using SQL statements but also by using a well established and known noSQL protocol.
This works by having the memcache daemon running as plugin as part of the MySQL server. This daemon can then be configured in three ways: Either
- to do what memcached always did - use an in memory hash table to store its data - or
- to access an InnoDB table to store and read data from or
- to use its own hash table in memory and fall back to InnoDB if data is not found directly in memcache.
This combines the power of MySQL and InnoDB's persistent storage with the lightweight protocol memcache uses, which has faster connecting times (no authorization handshake etc.) and faster data access (no SQL parsing, optimization etc.) while you're still able to query the data using SQL when you're doing more complex operations.
Of course I had to give it a run with PHP.
First step for using this is fetching the MySQL preview release and configuring it accordingly. My colleague Jimmy Yang from the InnoDB team has a nice blog posting showing these first steps. After that we have to configure PHP where we have two choices: We can use the a bit older memcache module or the newer memcached module. I've chosen the first one as that was already configured on my system. On most systems the installation should be as easy as querying your package manager or using PECL:
# pecl install memcache or # pecl install memcached
And then adding the corresponding entry (extension=memcache[d].so) to your php.ini file.
So let's do a first test from command line:
$ php -r '$m = memcache_connect("localhost", 11211); ' \ '$m->add("key", "value"); var_dump($m->get("key"));' string(5) "value"
So we store a value in memcache and then load it again to see if it was stored properly. Now we verify the results directly in MySQL:
mysql> SELECT * FROM demo_test WHERE c1 = 'key'; Empty set (0.00 sec)
Uh, what's wrong? - O simple: We didn't read Jimmy's article properly:
If you would like to take a look at what’s in the “demo_test” table, please remember we had batched the commits (32 ops by default) by default. So you will need to do “read uncommitted” select to find the just inserted rows
So we can apply that knowledge and query again:
mysql> set session TRANSACTION ISOLATION LEVEL read uncommitted; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM demo_test WHERE c1 = 'key'; +------+------+------+------+-------+------+------+------+------+------+------+ | cx | cy | c1 | cz | c2 | ca | CB | c3 | cu | c4 | C5 | +------+------+------+------+-------+------+------+------+------+------+------+ | NULL | NULL | key | NULL | value | NULL | NULL | 0 | NULL | 1 | NULL | +------+------+------+------+-------+------+------+------+------+------+------+ 1 row in set (0.00 sec)
And yay! - We see our value in between the other columns for meta-data and other things.
Both PHP modules provide a session handler so you can store your session data easily in memcacheInnoDB. For configuring this we first need to add two entries to our php.ini file:
; when using the "memcache" extension: session.save_handler=memcache ; when using the "memcached" extension: ; session.save_handler=memcached session.save_path="tcp://localhost:11211"
After restarting the web server, so it reads the new configuration we can test it with a simple script:
<?php session_start(); echo "<pre>Session ID: ".session_id()."\n"; var_dump($_SESSION); $_SESSION['foo'] = 'bar'; ?>
When first requesting this we will receive an output like
m1h4iqmp6hc7e4l85qlld0gtd array(0) { }
Then we reload the page and see:
m1h4iqmp6hc7e4l85qlld0gtd1 array(1) { ["foo"]=> string(3) "bar" }
After that we can, again, look directly into MySQL:
mysql> select * from demo_test where c1 = 'm1h4iqmp6hc7e4l85qlld0gtd1'; +------+------+----------------------------+------+----------------+------+------+------+------+------+------+ | cx | cy | c1 | cz | c2 | ca | CB | c3 | cu | c4 | C5 | +------+------+----------------------------+------+----------------+------+------+------+------+------+------+ | NULL | NULL | m1h4iqmp6hc7e4l85qlld0gtd1 | NULL | foo|s:3:"bar"; | NULL | NULL | 0 | NULL | 4 | NULL | +------+------+----------------------------+------+----------------+------+------+------+------+------+------+ 1 row in set (0.00 sec)
I hope this helps you to get started. If you'd like to learn more about MySQL 5.6, MySQL Cluster 7.1 (which btw, also can be access using memcache!) our new installer or such you can watch a recording of Tomas' keynote or visit dev.mysql.com.