<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jurriaanpersyn.com &#187; oemebamo</title>
	<atom:link href="http://www.jurriaanpersyn.com/archives/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jurriaanpersyn.com</link>
	<description></description>
	<lastBuildDate>Tue, 10 Jan 2012 16:58:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Meet Engagor.</title>
		<link>http://www.jurriaanpersyn.com/archives/2011/10/25/meet-engagor/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2011/10/25/meet-engagor/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 09:32:10 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/?p=510</guid>
		<description><![CDATA[It&#8217;s almost half a year now, since we returned from our No Worries trip, and in that time I&#8217;ve switched jobs and started working on a new version of an exciting start-up in Gent; Engagor, a Swiss Army Knife for the social web. Today, I&#8217;m proud to share that with you. Here&#8217;s 20 screenshots to [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s almost half a year now, since we returned from our <a href="http://noworries.jurriaanpersyn.com/">No Worries</a> trip, and in that time I&#8217;ve switched jobs and started working on a new version of an exciting start-up in Gent; Engagor, a Swiss Army Knife for the social web. Today, I&#8217;m proud to share that with you. Here&#8217;s 20 screenshots to give you an idea of what it&#8217;s about;</p>
<p><script src="http://speakerdeck.com/embed/4ea573a615006a053d001218.js"></script></p>
<p>Interested in a demo? Drop me a line at <a href="mailto:jurriaan@engagor.com">jurriaan@engagor.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2011/10/25/meet-engagor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to memcached</title>
		<link>http://www.jurriaanpersyn.com/archives/2010/05/27/introduction-to-memcached/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2010/05/27/introduction-to-memcached/#comments</comments>
		<pubDate>Thu, 27 May 2010 21:52:32 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[ikdoeict]]></category>
		<category><![CDATA[invalidation]]></category>
		<category><![CDATA[kaho st. lieven]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/?p=354</guid>
		<description><![CDATA[These are the slides to a talk I did earlier this week for students of the professional bachelor in ICT course at KaHo St. Lieven. I wanted to give a clear and simple introduction to the memcached service, as I think it&#8217;s an invaluable tool in today&#8217;s web development.]]></description>
			<content:encoded><![CDATA[<p>These are the slides to a talk I did earlier this week for students of the <a href="http://www.ikdoeict.be/en">professional bachelor in ICT course</a> at <a href="http://www.kahosl.be">KaHo St. Lieven</a>. I wanted to give a clear and simple introduction to the memcached service, as I think it&#8217;s an invaluable tool in today&#8217;s web development. </p>
<div style="width:710px" id="__ss_4296041"><object id="__sse4296041" width="710" height="568"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontomemcached-kahost-lieven-may25th2010-100525142530-phpapp02&#038;stripped_title=introduction-to-memcached" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse4296041" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introductiontomemcached-kahost-lieven-may25th2010-100525142530-phpapp02&#038;stripped_title=introduction-to-memcached" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="710" height="568"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2010/05/27/introduction-to-memcached/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Developing Social Games in the Cloud</title>
		<link>http://www.jurriaanpersyn.com/archives/2010/05/25/developing-social-games-in-the-cloud/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2010/05/25/developing-social-games-in-the-cloud/#comments</comments>
		<pubDate>Tue, 25 May 2010 08:48:17 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[amazon aws]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[gatcha]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[social games]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/?p=345</guid>
		<description><![CDATA[These are slides from a presentation I gave with Pieter De Schepper at a PHP Benelux meeting last month on the topic of building a social gaming platform, Gatcha &#8211; the project I&#8217;m currently working on, on top of Amazon Web Services.]]></description>
			<content:encoded><![CDATA[<p>These are slides from a presentation I gave with <a href="http://nl.netlog.com/Pieter">Pieter De Schepper</a> at a <a href="http://phpbenelux.eu/en/2010-meeting-ghent">PHP Benelux</a> meeting last month on the topic of building a social gaming platform, <a href="http://www.gatcha.com/">Gatcha</a> &#8211; the project I&#8217;m currently working on, on top of <a href="http://aws.amazon.com/">Amazon Web Services</a>.</p>
<div style="width:710px" id="__ss_3901151"><object id="__sse3901151" width="710" height="568"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=developingsocialgamesinthecloud-slideshare-100429072040-phpapp02&#038;stripped_title=developing-social-games-in-the-cloud" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse3901151" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=developingsocialgamesinthecloud-slideshare-100429072040-phpapp02&#038;stripped_title=developing-social-games-in-the-cloud" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="710" height="568"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2010/05/25/developing-social-games-in-the-cloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Sharding at Netlog, with MySQL and PHP</title>
		<link>http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#comments</comments>
		<pubDate>Thu, 12 Feb 2009 13:03:02 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[federation]]></category>
		<category><![CDATA[high performance]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[netlog]]></category>
		<category><![CDATA[parallel processing]]></category>
		<category><![CDATA[partitioning]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[sharding]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/?p=274</guid>
		<description><![CDATA[This article accompanies the slides from a presentation on database sharding. Sharding is a technique used for horizontal scaling of databases we are using at Netlog. If you're interested in high performance, scalability, MySQL, php, caching, partitioning, Sphinx, federation or Netlog, read on ... This presentation was given at the second day of FOSDEM 2009 [...]]]></description>
			<content:encoded><![CDATA[<style>
.slide {
width: 500px; 
margin: 0 auto;
margin-bottom: 10px;
}
.slide p {
margin: 0; 
display: block; 
padding: 5px; 
color: grey; 
text-align: right;
font-style: italic;
}
</style>
<p>This article accompanies the <a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#slides">slides</a> from a presentation on database sharding. Sharding is a technique used for horizontal scaling of databases we are using at Netlog. If you're interested in high performance, scalability, MySQL, php, caching, partitioning, Sphinx, federation or Netlog, read on ...</p>
<p>This presentation was given at the second day of <a href="http://www.fosdem.org/2009/">FOSDEM 2009</a> in Brussels. FOSDEM is an annual conference on open source software with about <em>5000 hackers</em>. I was invited by <a href="http://www.krisbuytaert.be/blog/">Kris Buytaert</a> and <a href="http://friendfeed.com/lenzgr">Lenz Grimmer</a> to give a talk in the <a href="http://forge.mysql.com/wiki/FOSDEM_2009">MySQL Dev Room</a>. The talk was based on an <a href="http://www.slideshare.net/oemebamo/database-sharding-at-netlog-presentation">earlier talk</a> I gave at <a href="http://barcampgent2.wikispaces.com/">BarcampGent 2</a>.</p>
<h3>Overview</h3>
<ul>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#more-274#whoami">Who am I?</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#aboutnetlog">What is Netlog?</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#history">A history of scaling database systems</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#hittinglimits">Hitting limits</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#shardingbasics">Sharding basics</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#shardingschemes">Sharding schemes</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#implications">Implications</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#solutions">Existing solutions</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#implementation">Implementation</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#tacklingproblems">Tackling the problems</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#finalthoughts">Final thoughts</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#slides">Slides</a></li>
<li><a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#resources">Resources</a></li>
</ul>
<p><span id="more-274"></span></p>
<h3 id="whoami">Who am I?</h3>
<p>Currently I am a Lead Web Developer at Netlog working with php, MySQL and other frontend technologies to develop and improve the features of our social network. I've been doing this for 3 years now. For this paper it is important to mention that I am neither a DBA nor a sys-admin, so I approach the problem of scaling databases from an application / developer point of view.<br />Of course the solutions presented in this presentation are the result of a lot of effort from the Development and IT Services Department at Netlog.</p>
<h3 id="aboutnetlog">What is Netlog?</h3>
<p>For those of you, who are unfamiliar with Netlog, it's best to sketch a little overview of who and what we are, and especially where we come from in terms of userbase and growth. It will let you see things in perspective regarding scalability. At the moment we have over 40 million active members, resulting in over 50 million unique visitors per month. This adds up to 5+ billion page views per month and 6 billion online minutes per month. We're active in 26 languages and 30+ countries with our 5 most active countries being Italy, Belgium, Turkey, Switzerland and Germany. <em>(If you're interested in more info about the company, check our <a href="http://netlog.com/go/about">About Pages</a> and <a href="http://netlog.com/go/register">sign-up for an account</a>.)</em></p>
<div style="text-align: center;"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/europe.png" /><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/africa-asia.png" /></div>
<p>In terms of database statistics, this type of usage results among others in huge amounts of data to store (eg. 100+ million friendships for nl.netlog.com). The nature of ourapplication (lots of interaction) results in a very write-heavy app (with a read-write ratio of about 1.4 to 1). A typical database, before sharding, had an average of 3000+ queries per second during the peaktime (15h - 22h local time, for nl.netlog.com).<br />Of course, these requirements do not have to be met by every application, and different applications require different scaling strategies. Nevertheless we wouldn't have thought (or hoped) to be where we are today, when we started off 7 years ago as a college student project. We are convinced that we can give you further insight into scalability and share some valuable suggestions.<br />Below is a graph of our growth in the last year.</p>
<div style="text-align: center;"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/growthstats.png" style="width: 100%;" /></div>
<p>This growth has of course resulted in several performance issues. The bottleneck for us has often been the database layer, because this layer is the only layer in the web stack that isn't stateless. The interactions and dependencies in a relational database system, make scaling horizontally less evident.</p>
<p>Netlog is (being) built and runs on open source software such as <a href="http://www.php.net">php</a>, <a href="http://www.mysql.com">MySQL</a>, <a href="http://www.apache.org">Apache</a>, <a href="http://www.debian.org">Debian</a>, <a href="http://www.danga.com/memcached/">Memcached</a>, <a href="http://www.sphinxsearch.com/">Sphinx</a>, <a href="http://www.lighttpd.net/">Lighttpd</a>, <a href="http://www.squid-cache.org/">Squid</a>, and many more. Our solutions for scaling databases are also built on these technologies. That's why we want to give something back by documenting and sharing our story. </p>
<h3 id="history">A history of scaling database systems</h3>
<p>As every hobby project, Netlog (then <a href="http://web.archive.org/web/20001018021036/http://asl.to/">asl.to</a>, "your internet passport") started off, more then 7 years ago, with a single database instance on a - probably virtual - server in a shared hosting environment. As traffic grew and load increased, we moved to a separate server, with eventually a split setup for MySQL and php (<a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#databasesetup1">database setup 1</a>).</p>
<div id="databasesetup1" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/master.png" />
<p>Database Setup 1: Master (W)</p>
</div>
<p>A next step to be taken was introducing new databases configured as "slaves" of the "master" database. Because a single MySQL server couldn't serve all the requests from our application, we distributed the read and write traffic to separate hosts. Setting up a slave is pretty easy through MySQL's replication features. What happens in a master-slave configuration is that you direct all write-queries (INSERT/UPDATE/DELETE) to the master database and all (or most) read queries to one or more slave databases. Slaves databases are typically kept in sync with the master by reading the binlog files of the master and replaying all write-queries (<a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#databasesetup2">database setup 2</a>).<br />Problems to tackle for this set-up include increased complexity for your DBA-team (that needs to monitor multiple servers), and the possibility of "replication lag"; your slaves might get out-of-sync with the master database (because of locking read-queries, downtime, inferior hardware, etc.), resulting in out-of-date results being returned when querying the slave databases.<br />Not in every situation real-time results are required, however you'll have situations where you have to force some read-queries to your master database to ensure data integrity. Otherwise you will end up with the painful consequences of (possible) race conditions.</p>
<div id="databasesetup2" class="slide">
<img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/master-slave.png" /></p>
<p>Database Setup 2: Master (W) + Slaves (R)</p>
</div>
<p>A good idea for the master-slave set-up is to introduce roles for your slaves. Typically you might assign all search, backend and/or statistics related queries to a "search-slave", where you don't care that much about replication lag, since real time results are seldom required for those kind of use cases.</p>
<p>This system works especially well for read-heavy applications. Say you've got a server load of 100% and a read/write ratio of 4/1, your master server will be executing SELECT-queries 80% of the time. If you add a single slave to this set-up, the SELECT capacity doubles and you can handle twice the amount of SELECT-queries.<br />But in a write-heavy application, or a situation where your master database is executing write-queries for 90% of the time, you'll only win another 10% capacity by adding another slave, since your slaves will be busy syncing with their master for about 90% of the time. The problem here is that you're only distributing read traffic and no write traffic. In fact you're replicating the write traffic. Considering the fact that the efficiency of a Master-Slave setup is limited, you end up with lots of identic copies of your data.</p>
<p>At this point you'll have to start thinking about distributing write traffic. The heavier your application relies on write traffic, the sooner you'll have to deal with this. A simple, and straightforward, first step is to start partitioning your application on feature-level. This process is called vertical partitioning.<br /> In your application you identify features (and by that MySQL tables) that more or less can exist on separate servers. If you have tables that are unrelated and don't require JOINs, why not put them on separate servers? For Netlog we have been able to put most of the tables containing details about a the items of a user (eg. photos, blogs, videos, polls, ...) on separate servers. By replicating some important tables (eg. a table with userids, nicknames, etc.) to all separate partitions, you can still access and JOIN with those tables if you might need to.<br /> In <a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#databasesetup3">database setup 3</a>, you see an example where we don't bother our master database anymore for friends or messages related queries. The write and read queries for these features go directly to the database responsible for that feature. These feature-specific hosts are still configured as slaves of the "TOP" master database, because that way we can replicate a few of those really important tables.<br /> A good idea here is to split up the tables for <a href="http://en.wikipedia.org/wiki/OLAP">OLAP</a> use cases (data warehouses) from <a href="http://en.wikipedia.org/wiki/OLTP">OLTP</a> use cases (front-end, real time features), since these require a different approach and have different needs regarding speed and uptime, anyways.</p>
<div id="databasesetup3" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/verticalpartitioning.png" />
<p>Database Setup 3: Vertical Partitioning</p>
</div>
<p>What we did in setup 2, can be easily repeated for each of the vertically partitioned features. If any of your databases have trouble keeping up with the traffic requirements, configure a slave for that database and distribute the read and write traffic. This way you create a tree of databases replicating some tables through the whole system and a database class responsible for distributing the right queries to the right databases (<a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#databasesetup4">database setup 4</a>).</p>
<div id="databasesetup4" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/verticalpartitioning-slave.png" />
<p>Database Setup 4: Vertical Partitioning / Replication Tree</p>
</div>
<p>If necessary, you might dive deeper into your application and find more features to partition. Unfortunately this will become harder and harder, because with every feature you split up, you again lose some JOIN-functionality you might want or need. And, sometimes, you're even stuck with a single table that's growing too large and grows beyond what a single database host can easily manage. The first feature to hit this single-table-on-a-single-database limit, was a table with friendships between our users. This table grew so rapidly that the performance and uptime of the host responsible for this feature wasn't guaranteed anymore, no matter how many slaves we added to it. Of course you can always choose to scale up, instead of scale out, by buying boxes with an incredibly insane hardware setup, but apart from being nice to have, they're expensive and they'll still hit limits if you continue growing.<br /> This approach to scaling has a limit (<a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#databasesetup5">database setup 5</a>) and if you hit that limit, you have to rethink your scaling strategy.</p>
<div id="databasesetup5" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/verticalpartitioning-overload.png" />
<p>Database Setup 5: Hitting Limits</p>
</div>
<h3 id="hittinglimits">So, what's next?</h3>
<p>What could we do now? Vertical partitioning has helped us a great deal, but we are stuck. Does master-to-master replication help? Will a cluster set-up help? Not really; these systems are designed for high availability and high performance. They work by replicating data and don't offer solutions for distributing write traffic.<br /> What about caching? Oh, how can we forget about caching! Of course, caching will help a great deal in lowering the load on your database servers. (The read/write-ratio mentioned earlier would be completely different if we did no caching.) But the same problem remains: caching will lower the read traffic on your databases, but doesn't offer a solution for write traffic. Caching will delay the moment your database is only returning "1040 Too many connections" errors, but no matter how good your caching strategy is, it can't prevent your visitor metrics going nuts at some point.</p>
<h3 id="shardingbasics">The Holy Grail!</h3>
<p>You can't split a table vertically, but can you easily split it horizontally? Sharding a table is putting several groups of records of that table in separate places (be it physically or not). You cut your data into arbitrarily sized pieces / fragments / shards and distribute them over several database hosts. Instead of putting all 100+ million friendships records on 1 big expensive machine, put 10 million friendships on each of 10 smaller and cheaper machines.</p>
<div id="theholygrail" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/theholygrail.png" /></div>
<p>Sharding, or horizontal partitioning, is a term that was already in active use in 1996 in the MMO (Massive Multiplayer Online) Games world. If you're searching for info on sharding, you'll see it's a technique used by among others <a href="http://www.scribd.com/doc/35222/Flickr-Architecture-Presentation">Flickr</a>, <a href="http://highscalability.com/livejournal-architecture">LiveJournal</a>, <a href="http://www.slideshare.net/guest0e6d5e/sharding-architectures">Sun</a> and Netlog.</p>
<div id="shardingfederationmodulo" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/sharding-federation-modulo.png" />
<p>Sharding a photos table over 10 servers with a modulo partitioning scheme</p>
</div>
<p>In the image above you see an example of splitting up a photos-table over 10 different servers. The algorithm that's used to decide where you data goes or where you can access your data is eg. a modulo function on the userid of the owner of that photo. If you know the owner of a photo, you then know where to fetch the photo's other details, fetch its comments, etc.<br /> Let's hvae a look at another simple example. </p>
<ul>
<li>Use case: a simple blog site.</li>
<li>We've got a table with blog posts, with these columns: postid, title, message, dateadd, authorid
</li>
<li>authorid is a FK (foreign key) to a users table</li>
<li>We shard the blog posts table (because our authors have been very productive writers) over 2 databases.</li>
<li>Posts from authors with an even authorid go to database 1.</li>
<li>Posts from authors with an uneven authorid go to database 2.</li>
<li>Query: "Give me the blog messages from author with id 26."</li>
</ul>
<p>In a non sharded environment, somewhere in your application, you'd find code that looks like this:</p>
<div class="igBar"><span id="lphp-4"><a href="#" onclick="javascript:showPlainTxt('php-4'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PHP:</span>
<div id="php-4">
<div class="php">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span> = DB::<span style="color:#006600;">getInstance</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// fetch a database instance</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">prepare</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"SELECT title, message FROM BLOG_MESSAGES WHERE userid = {userID}"</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// prepare a query</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">assignInt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">'userID'</span>, <span style="color:#0000FF;">$userID</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// assign query variables</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// execute the query</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$results</span> = <span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">getResults</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// fetch an array of results </span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>In this example we first fetch an instance of our database class that connects to our database. We then prepare a query, assign the variables (here the id of the author $userID), execute the query and fetch the resultset. If we introduce sharding based on the author's $userID, the database we need to execute this query on, is depending on that $userID (whether or not it is an even number). An approach to handle this could be to include the logic of "which user is on which database" into our database class and pass on that $userID to that class. You could end up with something like this: you pass on the $userID to the DB::getInstance() function, which then returns an object with the connection details based on the result of $userID % 2:</p>
<div class="igBar"><span id="lphp-5"><a href="#" onclick="javascript:showPlainTxt('php-5'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PHP:</span>
<div id="php-5">
<div class="php">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span> = DB::<span style="color:#006600;">getInstance</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$userID</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// fetch a database instance, specific for this user</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">prepare</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"SELECT title, message FROM BLOG_MESSAGES WHERE userid = {userID}"</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">assignInt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">'userID'</span>, <span style="color:#0000FF;">$userID</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$results</span> = <span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">getResults</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Instead of passing the $userID as a parameter to your DB-class, you could try to parse it from the prepared query you supply your class, or you could do your calculation of which DB connection you need on a different level, but the key concept remains the same: you need to pass some extra information to your database class to know where to execute the query. That is one of the most challenging requirements that has to be met for successful sharding.</p>
<h3 id="shardingschemes">How to shard your data?</h3>
<p>When you want to split up your data two questions spring to mind: which property of the data (which column of the table) will I use to make the decisions on where the data should go? And what will the algorithm be? Let's call the first one the "sharding/partitioning key", and the second one the "sharding/partitioning scheme".</p>
<p>Which sharding key will be used is basically a decision that depends on the nature of your application, or the way you'll want to access your data. In the blog example, if you display overviews of blog messages per author, it's a good idea to shard on the author's $userID. Say your site's navigation is through archives per month or per category, it might be smarter to shard on publication date or $categoryID. <em>(If your application requires both approaches it might even be a good idea to set up a dual system with sharding on both keys.)</em></p>
<p>What you can do with the "shard key" to find its corresponding shard basically falls into 4 categories: </p>
<ul>
<li><strong>Vertical Partitioning</strong>: Splitting up your data on feature/table level can be seen as a kind of sharding, where the "shard key" is eg. the table name. As mentioned earlier this way of sharding is pretty straightforward to implement and has a relatively low impact on the application on the whole.</li>
<li><strong>Range-based Partitioning</strong>: In range based partitioning you split up your data according to several ranges. Blog posts from before the 2000 and before go to database 1, blog posts from the new millenium go to the other database. This approach is typical for logging or other time based data. Other examples of range based partitioning could include federating users according to the first number of their postal code.</li>
<li><strong>Key or Hash based Partitioning</strong>: The modulo-function used in the photos example is a way of partitioning your data based on hashing or other mathematical functions of the key. In the simple example of a modulo function you can use your number of shards for the modulo-operation. Of course, changing your number of shards would mean rebalancing your data. This might be a slow process. A way to solve this is to use a more consistent hashing mechanism, or choose the original number of your shards right and work with "virtual shards".</li>
<li><strong>Directory based Partitioning</strong>: The last and most flexible scheme is where you have a directory lookup for each of the possible values of your shard key, mapped to a certain shard's id. This makes it possible to move all data from a certain shard key (eg. a certain user) from shard to shard, by altering the directory. A directory could on the other hand introduce more overhead or be a SPOF (Single Point Of Failure).</li>
</ul>
<p>As shown in the blog example, you need to know your "shard key" before you can actually execute your query on the right database server. It means that the nature of your queries and application determines the way of partitioning your data. The demanded flexibility, the projected growth and the nature of your data will be other factors helping you decide on what scheme to use.<br /> You also want to choose your keys and scheme so the data is optimally balanced over the databses and the load to each of the servers in the pool is equal.</p>
<p>The end result of sharding your data should be that you have distributed write-queries to different independent databases, and that you end up with a system of more, but cheaper machines, that each have a smaller amount of the data and thus can process queries faster on smaller tables.<br /> If you succeed, you're online again. Users appreciate it and your DBA is happy, because each of the machines in the setup now has less load and crashes less so there is no tussing and turning through the nights. <em>(Smaller tables means faster queries, and that includes maintainance or ALTER-queries, which again helps in keeping your DBA and developers happy.)</em></p>
<h3 id="implications">If there's a Holy Grail, there's a Killer Rabbit</h3>
<div id="killerrabbit" class="slide" style="margin-top: 15px;"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/killerrabbit.png" />
<p>Photo from <a href="http://www.flickr.com/photos/kt">The Rocketeer</a>. (Creative Commons Licensed)</p>
</div>
<p>Of course, sharding isn't the silver bullet of horizontal database scaling that will easily solve all your problems. Introducing sharding in your application comes with a significant cost of development. Here are some of its implications:</p>
<ul>
<li><strong>No cross-shard SQL queries</strong>: If you ever want to fetch data that (possibly) resides on different shards, you won't be able to do this with a JOIN on SQL-level. If you shard on $userID a JOIN with data from the same user is possible. However once you fetch results from several users on a shard, this will probably be an incomplete resultset. The key here is to design your application so there's no need for cross-shard queries. Other solutions could be the introduction of parallel querying on application level, but then of course you lose the aspect of distributing your database traffic. Depending on the use case, this could be a problem or not (eg. parallel querying for backend purposes is not as crazy as it may sound).<br /> Other options could be to denormalize your data and make some of the needed info available in several tables on several shards. You could duplicate the nickname of the author of a comment in the comments table to avoid having to do an extra query for that nickname. (The shard where you fetch the comment from, might be different than the shard where you'll find the nickname of the author.)<br /> If you have a table with guestbook messages that you want to shard, but require fetching both a list of messages by guestbook owner userid as on message poster userid, you could denormalize it by putting your messages (or references) on both the owner's and the poster's shard.</li>
<li><strong>Data consistency and referential integrity</strong>: Since data from a same "table" resides on several stand-alone database servers it becomes impossible to imply foreign keys, globally unique auto_increment values or execute cross-shard transactions. This means you have to deal with enforcing integrity on the application level, and you might eventually end up spending a significant amount of your development time on check and fix routines.<br /> One way to reduce the integrity problems is to fake transactions across databases by starting a database transaction on two servers and only committing each of them once you know both servers are up. There will still be a delay in between the two commits of the transaction (which can then again cause problems), but it is one step closer to keeping your data healthy.</li>
<li><strong>Balancing shards</strong>: If you shard on $userID, your sharding system might be(come) unbalanced because of power users versus inactive users. Not all hardware in your setup might have the same specs. And what if you add more shards, how will you be able to rebalance your setup? <br />Keeping the load on every database equal might take some effort. The choice of partitioning scheme is very important at this point. A directory based approach is the most flexible, but introduces overhead and a possible SPOF.</li>
<li><strong>Is your network ready?</strong> Your application servers will now possibly fetch and store data on several different servers in one request, your network topology and configuration settings have to be ready. Will you keep connections open for the full page render? Or will you close the connection to your database after every query?</li>
<li><strong>Your backup strategy will be different</strong>: Your actual data is fragmented over different servers affecting your backup strategy.</li>
</ul>
<h3 id="solutions">Existing solutions?</h3>
<p>At the moment Netlog is the 67<sup>th</sup> most visited website in the world, according to Alexa's ranking. This means that there's at least 66 other websites out there probably facing similar problems as we do. 16 of the 20 most popular websites are powered by MySQL so, we are definitely not alone, are we?<br /> Let's have a look at some of the existing technologies that implement or are somehow related to sharding and scaling database sysems, and let's see which ones could be interesting for Netlog.</p>
<p><strong><a href="http://www.mysql.com/products/database/cluster/">MySQL Cluster</a></strong> is one of the technologies you could think would solve similar problems. The truth is that a database cluster is helpful when it comes to high availability and performance, but it's not designed for the distribution of writes.</p>
<p><strong><a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning.html">MySQL Partitioning</a></strong> is another relatively new feature in MySQL that allows for horizontal splitting of large tables into smaller and more performant pieces. The physical storage of these partitions are limited to a single database server though, making it not relevant for when a single table grows out of the capacities of a single database server.</p>
<p><strong><a href="http://www.hscale.org">HSCALE</a></strong> and <strong><a href="http://spockproxy.sourceforge.net/">Spock Proxy</a></strong>, that both build on <strong><a href="http://forge.mysql.com/wiki/MySQL_Proxy">MySQL Proxy</a></strong>, are two other projects that help in sharding your data. MySQL Proxy introduces <a href="http://en.wikipedia.org/wiki/Lua_(programming_language)">LUA</a>, as an extra programming language to instruct the proxy (for eg. finding the right shard for this query). At the time we needed a solution for sharding neither of these projects seemed to support directory based sharding the way we'd wanted it to.</p>
<p><strong><a href="http://www.hivedb.org/">HiveDB</a></strong> is a sharding framework for MySQL in Java, that requires the Java Virtual Machine, with a php interface currently being in an infancy state. Being a Java solution makes it less interesting for us, since we prefer the technologies we are experts in and our application is written in: php.</p>
<p>Other technologies that aren't MySQL or php related include <a href="http://hypertable.org/">HyperTable</a> (HQL), <a href="http://hadoop.apache.org/hbase/">HBase</a>, <a href="http://labs.google.com/papers/bigtable.html">BigTable</a>, <a href="http://www.hibernate.org/414.html">Hibernate Shards</a> (*shivers*), <a href="http://www.sqlalchemy.org/">SQLAlchemy</a> (for Python), <a href="http://www.oracle.com/technology/products/database/clustering/index.html">Oracle RAC</a>, etc ... The memcached SQL-functions or storage engine for MySQL is also a related project that we could mention here.</p>
<p>None of these projects really seemed to come in line with our requirements. But what exactly are they?</p>
<ul>
<li><strong>Flexible for the hardware department.</strong><br />We project growth and want the sharding system to be flexible. Knowing that our traffic will increase, we need to be able to add more shards quickly. With a growing amount of data, a proportional growth in hardware is requested. For this reason we opt for a directory based partitioning scheme.</li>
<li><strong>No massive rewrite.</strong><br />We can't introduce a whole new database layer or incompatible abstraction layer. We want to keep on using our database class as we are doing now and only implement sharding for those features that really require that amount of scaling. That's why we've opted for a solution that builds on what we have and allows for incremental implementation. We also wanted to use the sharding API, without having the data to be physically sharded, so the development and IT departments can independently decide when to do their part of the job.</li>
<li><strong>Support for multiple sharding keys.</strong><br /> Most of our data will probably be sharded on $userID, but we want the system to be flexible so we can implement other keys and/or sharding schemes too.</li>
<li><strong>Easy to understand.</strong><br />We can't expect each and every of our developers to know everything about scalability and performance. Even if this was the case, the API to access and store data in a sharded environment should make it transparent to them so they shouldn't care about performance and can focus on what's really fun to do: developing and improving on features.<br />So, it's best if the API is a php API which makes it easy for them to use in the rest of our application.</li>
</ul>
<h3 id="implementation">Sharding Implementation at Netlog</h3>
<p>So, what did we come up with? An in-house solution, written 100% in php. The implementation is mostly middleware between application logic and the database class. We've got a complete caching layer built in (using memcached). Since our site is mainly build around profiles, most of the data is sharded on $userID.</p>
<p>In this system we are using the shard scheme <a href="http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/#shard-database-host-structure">below</a>, where a shard is identified by a unique number ($shardID) that also serves as a prefix for the tables in the sharding system. Several shards (groups of tables) sit together in a "shard database", and several of those databases (not instances) are on a certain "shard database host".<br /> So a host has more then one shard. This allows us to move shards as a whole, or databases as a whole to help in balancing all the servers in the pool and it allows us to play with the amount of shards in a database and amount of shards on a server to find the right balance between table size and open files for that server.<br />When started using this system in production we had 4000 shards on 40 hosts. Today we've got 80 hosts in the pool.</p>
<div id="shard-database-host-structure" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/shard-database-host-structure.png" />
<p>Shards live in databases, databases live on hosts</p>
</div>
<p>From the php side there are two parts of the implementation. The first being a series of management and maintainance related functions allowing to add, edit, delete shards, databases and hosts to the system and a lookup system. The second series of classes provides an API consisting of a database access layer and a caching layer.</p>
<h4>The Sharding Management Directory</h4>
<p>The directory or lookup system is in fact a single MySQL table translating shard keys to $shardIDs. Typically these are $userID-$shardID combinations. This is a single table with the amount of records being the number of users on Netlog. With only id's saved in that table it's still manageable and can be kept very performant through master-to-master-replication, memcached and/or a cluster set-up.<br /> Next to that there's a series of configuration files that translate $shardIDs to actual database connection details. These configuration files allow us to flag certain shards as not available for read and/or write queries. (Which is interesting for maintainance purposes or when a host goes down.)</p>
<h4>The Sharded Tables API</h4>
<p><em>Note: The API we implemented allows for handling more than the typical case I'll discuss next, and also allows for several caching modes and strategies based on the nature and use of its application.</em></p>
<p>Most records and data in the shard system have both a $userID field and an $itemID field. This $itemID is a $photoID for tables related to photos or $videoID for tables related to videos. (You get the picture ...) The $itemID is sometimes an auto_increment value, or a foreign key and part of a combined primary key with $userID. Each $itemID is thus unique per $userID, and not globally unique, because that would be hard to enforce in a distributed system. </p>
<p><em>(If you use an auto_increment value in a combined key in MySQL, this value is always a MAX()+1 value, and not an internally stored value. So if you add a new item, delete it again, and insert another record, the auto_increment value of that last insert will be the same as the previously inserted and deleted record. Something to keep in mind ...)</em></p>
<p>If we want to access data stored in the sharding system we typically create an object representing a table+$userID combination. The API provides all the basic CRUD (Create/Read/Update/Delete) functionalities typically needed in our web app. If we go back to the first example of fetching blog messages by a certain author we come to the following scenario;</p>
<p>Query: Give me the blog messages from author with id 26.</p>
<ol>
<li>Where is user 26?<br />User 26 is on shard 5.</li>
<li>On shard 5; Give me all the $blogIDs ($itemIDs) of user 26.<br />That user's $blogIDs are: array(10,12,30);</li>
<li>On shard 5; Give me all details about the items array(10,12,30) of user 26.<br />Those items are: array(array('title' => "foo", 'message' => "bar"), array('title' => "milk", 'message' => "cow"));</li>
</ol>
<p>In this process step 1 is executed on a different server (directory db) then step 2 and 3 (shard 5). Step 2 and 3 could easily be combined into one query, but there's a reason why we don't do it, which I'll explain when discussing our caching strategy.<br />It's important to note that the functionality behind step 2 allows for adding WHERE, ORDER and LIMIT clauses so you can fetch only the records you need in the order you need.</p>
<p><em>(One could argue that for the example given here and the way we are using MySQL here, it's not needed to have a relational database and you could try to use simpler database systems. While that could be the case, there's still advantages in using MySQL, for cases you're bypassing this API. It's not that bad to have all your data in the same format either, sharded or not. The possible overhead of still using MySQL hasn't been the bottleneck for us today, but it is certainly something we might consider improving on.)</em></p>
<h4>Shard Management</h4>
<p>To keep the servers in the sharding system balanced we are monitoring several parameters such as number of users, filesize of tables and databases, amount of read and write queries, cpu load, etc. Based on those stats we can make decisions to move shards to new or different servers, or even to move users from one shard to another.<br />Move operations of single users can be done completely transparently and online without that user experiencing downtime. We do this by monitoring write queries. If we start a move operation for a user, we start copying his data to the destination shard. When a write query is executed for that user, we abort the move process, clean up and try again later. So a move of a user will be successful if the user himself/herself isn't active at that time, or if no other user is interacting with him/her (for features in the sharding system).<br /> Moving a complete shard or database at a time is a more drastic approach to balancing the load of servers and requires some downtime which we can keep to a minimum by configuring shards as read only / using a master-slave setup during the switch, etc.</p>
<p>Inherent to this sytem is that if one database goes down, only the users (or interactions with the users) on that database are affected. We (can) improve the availability of shards by introducing clusters, master-master setups or master-slave setups for each shard, but the chance of a shard database server being in trouble are slim to none because of the minor load on shard db's compared to the pre-sharding-era.</p>
<h3 id="tacklingproblems">Tackling the problems</h3>
<p>The difficulties of sharding are partially tackled by implementations with these 3 technologies: Memcached, parallel processing and Sphinx.</p>
<h4>Memcached</h4>
<p>"memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load." By putting a memory caching layer in between our application logic and the SQL-queries to our shard database we are able to get results much, much faster. This caching layer also allows us to do some of the cross-shard data fetching, previously thought impossible on SQL-level.</p>
<p>For those unfamiliar with memcached, below is a very simple and stripped-down example of Memcached usage where we try to fetch a key-value pair from the cache and if it's not found we compute the value and store it into the system so a subsequent call to the function will instantly return the cached value without stressing the database.</p>
<div class="igBar"><span id="lphp-6"><a href="#" onclick="javascript:showPlainTxt('php-6'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PHP:</span>
<div id="php-6">
<div class="php">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#000000; font-weight:bold;">function</span> isObamaPresident<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$memcache</span> = <span style="color:#000000; font-weight:bold;">new</span> Memcache<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$result</span> = <span style="color:#0000FF;">$memcache</span>-&gt;<span style="color:#006600;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">'isobamapresident'</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#FF9933; font-style:italic;">// fetch</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#616100;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$result</span> === <span style="color:#000000; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#FF9933; font-style:italic;">// do some database heavy stuff</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$db</span> = DB::<span style="color:#006600;">getInstance</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$votes</span> = <span style="color:#0000FF;">$db</span>-&gt;<span style="color:#006600;">prepare</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"SELECT COUNT(*) FROM VOTES WHERE vote = 'OBAMA'"</span><span style="color:#006600; font-weight:bold;">&#41;</span>-&gt;<span style="color:#006600;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$result</span> = <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$votes</span>&gt; <span style="color:#006600; font-weight:bold;">&#40;</span>USA_CITIZEN_COUNT / <span style="color:#CC66CC;color:#800000;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> ? <span style="color:#FF0000;">'Sure is!'</span> : <span style="color:#FF0000;">'Nope.'</span>; <span style="color:#FF9933; font-style:italic;">// well, ideally</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#0000FF;">$memcache</span>-&gt;<span style="color:#006600;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">'isobamapresident'</span>, <span style="color:#0000FF;">$result</span>, <span style="color:#CC66CC;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#616100;">return</span> <span style="color:#0000FF;">$result</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Memcached is being used in several ways and on several levels in our application code, and for sharding the main ones include;</p>
<ul>
<li>Each $userID to $shardID call is cached. This cache has a hit ratio of about 100% because every time this mapping changes we can update the cache with the new value and store it in the cache without a TTL (Time To Live).</li>
<li>Each record in sharded tables can be cached as an array. The key of the cache is typically tablename + $userID + $itemID. Everytime we update or insert an "item" we can also store the given values into the caching layer, making for a theoretical hit-ratio of again 100%. </li>
<li>The results of "list" and "count" queries in the sharding system are cached as arrays of $itemIDs or numbers with the key of the cache being the tablename + $userID (+ WHERE/ORDER/LIMIT-clauses) and a revision number.</li>
</ul>
<p>The revision numbers for the "list" and "count" caches are itself cached numbers that are unique for each tablename + $userID combination. These numbers are then used in the keys of "list" and "count" caches, and are bumped whenever a write query for that tablename + $userID combination is executed. The revisionnumber is in fact a timestamp that is set to "time()" when updated or when it wasn't found in cache. This way we can ensure all data fetched from cache will always be the correct results since the latest update.<br />If, with this in mind, we again return to the blog example, we get the following scenario.</p>
<p>Query: Give me the blog messages from author with id 26.</p>
<ol>
<li>Where is user 26?<br />The result of this query is almost always available in memcached.</li>
<li>On shard 5; Give me all the $blogIDs ($itemIDs) of user 26.<br />The result of this query is found in cache if it has been requested before since the last time an update to the BLOGS-table for user 26 was done.</li>
<li>On shard 5; Give me all details about the items array(10,12,30) of user 26.<br />The results for this query are almost always found in cache because of the big hit-ratio for this type of cache. When fetching multiple items we make sure to do a multi-get request to optimize traffic from and to Memcached.</li>
</ol>
<p>Because of this caching strategy the two separate queries (list query + details query) which seemed a stupid idea at first, result in better performance. If we hadn't split this up into two queries and cached the list of items with all their details (message + title + ...) in Memcached, we'd store much more copies of the record's properties.</p>
<p>There is an interesting performance tweak we added to the "list" caches is that. Let's say we request a first page of comments (1-20), we actually query for the first 100 items, store that list of 100 in cache and then only return the requested slice of that result. A likely, following call to the second page (21-40) will then always be fetched from cache. So the window we ask from the database is different then the window requested by the app.</p>
<p>For features where caching race conditions might be a problem for data consistency, or for use cases where caching each record separately would be overhead (eg. because the records are only inserted and selected and used for 1 type of query), or for use cases where we do JOIN and more advance SQL-queries, we use different caching modes and/or different API-calls. </p>
<p>This whole API requires quite some php processing we are now doing on application level, where previously this was all handled and optimized by the MySQL server itself. Memory usage and processing time on php-level scale alot better then databases though, so this is less of an issue.</p>
<h4>Parallel processing</h4>
<p>It is not strange to fetch data stored on different shards in one go, because most data is probably available from memory. If we fetch a friends of friends list, one way to do this could be to fetch your own friends loop over them and fetch their friends and then process those results to get a list of people your friends know, but you don't know yet. <br />The amount of actual database queries needed for this will be small, and even so, the queries are simple and superfast. Problems start to occur if we are processing this for users which have a couple of hundreds of friends each. For this we've implemented a system for splitting up certain big tasks into several smaller ones we can process in parallel.<br />This parallel processing in php is done by doing several web requests to our php server farm that each process a small part of the task. It is actually faster to process 10 smaller tasks simultaneously than to do the whole thing at once. The overhead of the extra web requests and cpu cycles it takes to split up the task and combine the results, are irrelevant compared to the gain. </p>
<h4>Using Sphinx</h4>
<p>Other typical queries that become impossible for sharded data are overview queries. Say you'd like a page of all the latest photos uploaded by all users. If you'd have your user's photos distributed over a hundred of databases, you'd have to query each, and then process all of those results. Doing that for several features would not be justifiabled, so most of our "Explore" pages (where you browse through and discover content from the community) are served from a different system.<br /> Sphinx is a free and open source SQL full-text search engine. We use it for more than your average input field + search button search engine. In fact a list of most viewed videos of the day, can also be a query result from Sphinx. For most of the data on these overview pages it's not a problem if the data isn't real time. So it's possible to retrieve those results from indexes that are regularly built from the data on each shard and then combined.</p>
<p>For a full overview of how we use Sphinx (and how we got there), I encourage you to have a look at the presentation of my colleague Jayme Rotsaert, "<a href="http://www.slideshare.net/_jayme/scaling-optimizing-search-on-netlog-presentation">Scaling and optimizing search on Netlog</a>", who's put a lot of effort into using Sphinx.</p>
<h3 id="finalthoughts">Final thoughts</h3>
<p>If there are only two things I could say about sharding it'd be these two quotes; </p>
<ul>
<li>"Don't do it, if you don't need to!" (37signals.com)</li>
<li>"Shard early and often!" (startuplessonslearned.blogspot.com)</li>
</ul>
<p>Sounds like saying two opposite things? Well, yes and no.</p>
<p>You don't want to introduce sharding in your architecture, because it definitely complicates your set-up and the maintenance of your server farm. There are more things to monitor and more things that can go wrong. <br /> Today, there is no out-of-the-box solution that works for every set-up, technology and/or use case. Existing tool support is poor, and we had to build quite some custom code to make it possible.<br /> Because you split up your data, you lose some of the features you've grown to like from relational databases.<br /> If you can do with simpler solutions (better hardware, more hardware, server tweaking and tuning, vertical partitioning, sql query optimization, ...) that require less development cost, why invest lots of effort in sharding?</p>
<p>On the other hand, when your visitor statistics really start blowing through the roof, it is a good direction to go. After all, it worked for us.<br /> The hardest part about implementing sharding, has been to (re)structure and (re)design the application so that for every access to your data layer, you know the relevant "shard key". If you query details about a blog message, and blog messages are sharded on the author's userid, you have to know that userid before you can access/edit the blog's title.<br /> Designing your application with this in mind ("What are the possible keys and schemes I could use to shard?"), will definitely help you to implement sharding more easily and incrementally at the moment you might need to. </p>
<p>In our current set-up not everything is sharded. That's not a problem though. We focus on those features that require this scaling strategy, and we don't spend time on <em>premature optimization</em>.<br /> Today, we're spending less ca$h on expensive machines, we've got a system that is available, it can handle the traffic and it scales.</p>
<div id="conclusion" class="slide"><img src="http://www.jurriaanpersyn.com/projects/netlog/sharding/conclusion.png" /></div>
<h3 id="slides">Presentation</h3>
<div style="width: 500px; text-align: right; margin: 0 auto;" id="__ss_1004297"><object style="margin:0px" width="500" height="417"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=database-sharding-at-netlog-final-1234116512031629-2&#038;stripped_title=database-sharding-at-netlog" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=database-sharding-at-netlog-final-1234116512031629-2&#038;stripped_title=database-sharding-at-netlog" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="417"></embed></object>
<div>View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/oemebamo">Jurriaan Persyn</a>.<br /> <em>(tags: <a href="http://slideshare.net/tag/fosdem2009">fosdem2009</a> <a href="http://slideshare.net/tag/fosdem">fosdem</a>)</em></div>
</div>
<h3 id="resources">Resources</h3>
<ul>
<li>the great development and it services team at Netlog</li>
<li><a href="http://www.netlog.com/go/developer">www.netlog.com/go/developer</a></li>
<li><a href="http://www.37signals.com/svn/posts/1509-mr-moore-gets-to-punt-on-sharding">www.37signals.com/svn/posts/1509-mr-moore-gets-to-punt-on-sharding</a></li>
<li><a href="http://www.addsimplicity.com/adding_simplicity_an_engi/2008/08/shard-lessons.html">www.addsimplicity.com/adding_simplicity_an_engi/2008/08/shard-lessons.html</a></li>
<li><a href="http://www.scribd.com/doc/2592098/DVPmysqlucFederation-at-Flickr-Doing-Billions-of-Queries-Per-Day">www.scribd.com/doc/2592098/DVPmysqlucFederation-at-Flickr-Doing-Billions-of-Queries-Per-Day</a></li>
<li><a href="http://startuplessonslearned.blogspot.com/2009/01/sharding-for-startups.html">startuplessonslearned.blogspot.com/2009/01/sharding-for-startups.html</a></li>
<li><a href="http://www.codefutures.com/weblog/database-sharding">www.codefutures.com/weblog/database-sharding</a></li>
<li><a href="http://www.25hoursaday.com/weblog/2009/01/16/BuildingScalableDatabasesProsAndConsOfVariousDatabaseShardingSchemes.aspx">www.25hoursaday.com/weblog/2009/01/16/BuildingScalableDatabasesProsAndConsOfVariousDatabaseShardingSchemes.aspx</a></li>
<li><a href="http://highscalability.com">highscalability.com</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning.html">dev.mysql.com/doc/refman/5.1/en/partitioning.html</a></li>
<li><a href="http://www.hibernate.org/414.html">www.hibernate.org/414.html</a></li>
<li><a href="http://en.wikipedia.org/wiki/SQLAlchemy">en.wikipedia.org/wiki/SQLAlchemy</a></li>
<li><a href="http://spockproxy.sourceforge.net">spockproxy.sourceforge.net</a></li>
<li><a href="http://www.scribd.com/doc/3865300/Scaling-Web-Sites-by-Sharding-and-Replication">www.scribd.com/doc/3865300/Scaling-Web-Sites-by-Sharding-and-Replication</a></li>
<li><a href="http://oracle2mysql.wordpress.com/2007/08/23/scale-out-notes-on-sharding-unique-keys-foreign-keys">oracle2mysql.wordpress.com/2007/08/23/scale-out-notes-on-sharding-unique-keys-foreign-keys</a></li>
<li><a href="http://www.flickr.com/photos/kt">www.flickr.com/photos/kt</a></li>
<li><a href="http://oreilly.com/catalog/9780596101718/">High Performance MySQL, Second Edition (O'Reilly)</a></li>
</ul>
<p>For further questions or remarks, feel free to contact me at <a href="mailto:jurriaan@netlog.com">jurriaan@netlog.com</a> and subscribe to my blog at <a href="http://www.jurriaanpersyn.com">www.jurriaanpersyn.com</a> and the Netlog developer blog at <a href="http://www.netlog.com/go/developer/blog">www.netlog.com/go/developer/blog</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
		<item>
		<title>Database sharding at Netlog (FOSDEM talk slides)</title>
		<link>http://www.jurriaanpersyn.com/archives/2009/02/09/database-sharding-at-netlog-fosdem-talk-slides/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2009/02/09/database-sharding-at-netlog-fosdem-talk-slides/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 09:48:29 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[federation]]></category>
		<category><![CDATA[fosdem]]></category>
		<category><![CDATA[fosdem2009]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[partitioning]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sharding]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/?p=270</guid>
		<description><![CDATA[Here are the slides from yesterday's presentation about horizontal database scaling through sharding at the mySQL dev room at FOSDEM 2009. I've got a ton of notes and remarks to these slides, which will become available here soon.]]></description>
			<content:encoded><![CDATA[<p>Here are the slides from yesterday's presentation about horizontal database scaling through sharding at the mySQL dev room at FOSDEM 2009. </p>
<div style="width:710px;text-align:left;margin:0 auto;" id="__ss_1004297"><object style="margin:0px" width="710" height="570"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=database-sharding-at-netlog-final-1234116512031629-2&#038;stripped_title=database-sharding-at-netlog" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=database-sharding-at-netlog-final-1234116512031629-2&#038;stripped_title=database-sharding-at-netlog" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="710" height="570"></embed></object></div>
<p>I've got a ton of notes and remarks to these slides, which will become available here soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2009/02/09/database-sharding-at-netlog-fosdem-talk-slides/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Accessing data saved in the class property of DOM-elements with Prototype</title>
		<link>http://www.jurriaanpersyn.com/archives/2009/01/21/accessing-data-saved-in-the-class-property-of-dom-elements-with-prototype/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2009/01/21/accessing-data-saved-in-the-class-property-of-dom-elements-with-prototype/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 19:04:20 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[dom-elements]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[prototype]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/?p=249</guid>
		<description><![CDATA[Every so often, when in JavasScript-code-mode, there's the need to make some decisions based on data that's not available in the document itself. Say your templating engine comes up with the following HTML, which is basically a list of friends linking to their respective profiles; PLAIN TEXT HTML: &#60;ul class="myfriends"&#62; &#160; &#160; &#60;li&#62;&#60;a href="/wolksken"&#62;Laura Bogaert&#60;/a&#62;&#60;/li&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>Every so often, when in JavasScript-code-mode, there's the need to make some decisions based on data that's not available in the document itself. Say your templating engine comes up with the following HTML, which is basically a list of friends linking to their respective profiles;</p>
<div class="igBar"><span id="lhtml-15"><a href="#" onclick="javascript:showPlainTxt('html-15'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-15">
<div class="html">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">&lt;ul</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"myfriends"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/wolksken"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Laura Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/izewizai"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Isaï Persyn<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/boogie"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Maarten Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ul&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Now you'd want to mix in some extra-js-fu, by displaying a mini profile when you click any of the links. For that you'll be using your AJAX-API that needs eg. a user-identification integer or string as parameter. How is your JavaScript gonna know what this userID is for each of the listed friends? Right, you need some extra information for this.</p>
<h4>Different approaches</h4>
<p>There's a few ways of including data you need on a js-application level to your DOM-tree, some of which I list here;</p>
<ul>
<li>
		<strong>Hidden form elements</strong>:<br />
		You could nest some forms with hidden elements containing the data you need into your DOM. But I guess for the use case here, that would make your html quite cluttered and you'll have quite some overhead traversing the DOM to find the elements related to the click-event of your link. On the upside though, you can store about any value in those form elements as long as they're properly escaped. Example HTML:
<div class="igBar"><span id="lhtml-16"><a href="#" onclick="javascript:showPlainTxt('html-16'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-16">
<div class="html">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/wolksken"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Laura Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><a href="http://december.com/html/4/element/form.html"><span style="color: #000000; font-weight: bold;">&lt;form&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">"hidden"</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">"userid"</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">"1043"</span> /<span style="color: #000000; font-weight: bold;">&gt;</span></a></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/form&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
	</li>
<li>
		<strong>Custom attributes</strong>:<br />
		Why not just add some custom userID-attributes to the elements you need? It's very readable and flexible, it works in all browsers that support XHTML and - as with form elements - allows for about any type of text string, thus is <a href="http://unspace.ca/discover/attributes/">an excellent solution</a>. And in fact, the X in XHTML is for extensible right? But of course, there's the <em>Standards Police</em>™, who might not like that you're adding new custom attributes that aren't in the original specification, to put you off from using this technique. Example HTML:
<div class="igBar"><span id="lhtml-17"><a href="#" onclick="javascript:showPlainTxt('html-17'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-17">
<div class="html">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/wolksken"</span> userid=<span style="color: #ff0000;">"1043"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Laura Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
	</li>
<li>
		<strong>Abuse an existing attribute</strong>:<br />
		You could hide the fact you actually want to use custom attributes, by just abusing some of the existing ones. Let's for instance take the rel="" attribute; an existing attribute, available on anchors, left mostly unused; if we use it to store a userid in, validators won't complain, so we're all set? Well, quite an ugly hack, isn't it? Not semantic, not always available and you still have no easy solution for key-value pairs. Example HTML:
<div class="igBar"><span id="lhtml-18"><a href="#" onclick="javascript:showPlainTxt('html-18'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-18">
<div class="html">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/wolksken"</span> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">"1043"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Laura Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
	</li>
<li>
		<strong>(Ab)use your class-attribute</strong>:<br />
		There is one attribute that does fit for using to save data though, since it's available on every element, flexible enough, and it (can) even make sense on a semantic level. While class names will in 99% of the cases play a purely visual role, you could use them for application logic too. Isn't that what microformats are doing? Since you're using class names, you have to deal with some of it's limitations though; they can't have spaces, and <a href="http://gosnip.net/blog/2008/04/17/css-class-names-dont-use-underscore/"><em>some browsers</em> might not like all characters</a>. Example HTML:
<div class="igBar"><span id="lhtml-19"><a href="#" onclick="javascript:showPlainTxt('html-19'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-19">
<div class="html">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/wolksken"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"userid_1043"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Laura Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p>
</li>
</ul>
<p>Each of these 4 techniques have their own reasons to exist, and I'm not here to tell you which one is best, or which one you should use. I'm here to share two helper methods I've written for the class names approach.</p>
<h4>Extending Prototype with classname data helpers</h4>
<p>So, we're adding some extra data to our class-attributes. The templating engine does this in the format of "<key>_<escaped -value>".</escaped></key></p>
<div class="igBar"><span id="lhtml-20"><a href="#" onclick="javascript:showPlainTxt('html-20'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">HTML:</span>
<div id="html-20">
<div class="html">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">&lt;ul</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"myfriends"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/wolksken"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"gender_male userid_1043"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Laura Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/izewizai"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"gender_male userid_3409"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Isaï Persyn<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"/boogie"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"gender_female userid_8590"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Maarten Bogaert<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ul&gt;</span></span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>If we want to access these key-value pairs in JavaScript we go to the DOM-element, loop over it's class names, split the keys and values, and return the value for the queried key. Likewise you might want to have a class data setter method too.</p>
<p>For this I wrote two methods, getClassData(key) and setClassData(key, value), for Prototype, my weapon of choice for JavaScript development. These methods are getters and setters for those key-value pairs, and thanks to Element.addMethods, available on every DOM-element. Here's an example of it's use:</p>
<div class="igBar"><span id="ljavascript-21"><a href="#" onclick="javascript:showPlainTxt('javascript-21'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">JavaScript:</span>
<div id="javascript-21">
<div class="javascript">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">$$<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'ul.myfriends'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">first</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">observe</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'click'</span>, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>event<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> userID = event.<span style="color: #006600;">element</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">getClassData</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'userid'</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #66cc66;">&#40;</span>userID<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Here's the source code:</p>
<div class="igBar"><span id="ljavascript-22"><a href="#" onclick="javascript:showPlainTxt('javascript-22'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">JavaScript:</span>
<div id="javascript-22">
<div class="javascript">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">/**</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> * Extend all Prototype DOM-element with getClassData() and setClassData() methods</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> *</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> * @author Jurriaan Persyn - http://www.jurriaanpersyn.com</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> * @version 0.1</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> */</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Element.<span style="color: #006600;">addMethods</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900; font-style: italic;">/**</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * Returns a string stored in the classnames of a DOM-element in the form of &quot;$key$glue$data&quot;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * </span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param DOM-element &nbsp; element id or reference to a DOM-element</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param string key the key of the classname</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param&nbsp; &nbsp; string glue optional, default &quot;_&quot;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @return mixed_var null or string</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; */</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; getClassData: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>element, key, glue<span style="color: #66cc66;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; element = $<span style="color: #66cc66;">&#40;</span>element<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>!glue<span style="color: #66cc66;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; glue = <span style="color: #3366CC;">"_"</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; key = key + glue;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> data = <span style="color: #003366; font-weight: bold;">null</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; element.<span style="color: #006600;">classNames</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">each</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>className<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>className.<span style="color: #006600;">substr</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;color:#800000;">0</span>, key.<span style="color: #006600;">length</span><span style="color: #66cc66;">&#41;</span> === key<span style="color: #66cc66;">&#41;</span> </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = className.<span style="color: #006600;">replace</span><span style="color: #66cc66;">&#40;</span>key, <span style="color: #3366CC;">""</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = decodeURIComponent<span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> data;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900; font-style: italic;">/**</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * Stores a string in the classnames of a DOM-element in the form of &quot;$key$glue$data&quot;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * </span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param DOM-element element id or reference to a DOM-element</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param string key the key of the classname</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param string data a string with some data</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param&nbsp; &nbsp; string glue optional, default &quot;_&quot;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; * @param element Returns the element itself to allow chaining</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">&nbsp; &nbsp;&nbsp; */</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; setClassData: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>element, key, data, glue<span style="color: #66cc66;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>!glue<span style="color: #66cc66;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; glue = <span style="color: #3366CC;">"_"</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; element = $<span style="color: #66cc66;">&#40;</span>element<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> previousData = element.<span style="color: #006600;">getClassData</span><span style="color: #66cc66;">&#40;</span>key<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>previousData<span style="color: #66cc66;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; previousData = encodeURIComponent<span style="color: #66cc66;">&#40;</span>previousData<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element.<span style="color: #006600;">removeClassName</span><span style="color: #66cc66;">&#40;</span>key + glue + previousData<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; data = encodeURIComponent<span style="color: #66cc66;">&#40;</span>data<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; element.<span style="color: #006600;">addClassName</span><span style="color: #66cc66;">&#40;</span>key + glue + data<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> element;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span>,</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; _eoo: <span style="color: #003366; font-weight: bold;">true</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Here's a seperate file with the script: <a href='http://www.jurriaanpersyn.com/wp-content/uploads/2009/01/classdata-extensions-01.js'>classdata-extensions-01.js</a>.</p>
<p>The getClassData will always return values as strings. You could build in some type-hinting methods, but you'd have to implement that same protocol in your templating engine too then, so I decided to leave it out here. The data value is now being url-escaped to add it to the classes, but of course there's some limitations there too.</p>
<p>Here's to hoping these 2 methods might provide you some use ...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2009/01/21/accessing-data-saved-in-the-class-property-of-dom-elements-with-prototype/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>(delayed) BarCamp Gent 2008 Afterthoughts</title>
		<link>http://www.jurriaanpersyn.com/archives/2008/04/14/delayed-barcamp-gent-2008-afterthoughts/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2008/04/14/delayed-barcamp-gent-2008-afterthoughts/#comments</comments>
		<pubDate>Mon, 14 Apr 2008 19:54:16 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/archives/2008/04/14/delayed-barcamp-gent-2008-afterthoughts/</guid>
		<description><![CDATA[Barcamp Gent has been more more than 2 weeks now, but I still felt the need to give some credit to those who did great, interesting, good and/or remarkable presentations. One of the first talks I attended was the one by Werner Raemakers demoing Channel.TV and talking about the efforts VRT and BBC are making [...]]]></description>
			<content:encoded><![CDATA[<p>Barcamp Gent has been more more than 2 weeks now, but I still felt the need to give some credit to those who did great, interesting, good and/or remarkable presentations. </p>
<p>One of the first talks I attended was the one by <a href="http://www.werner.be/">Werner Raemakers</a> demoing <a href="http://www.werner.be/articles/2008/03/30/barcamp-ghent-2008-channl-tv-demo/">Channel.TV</a> and talking about the efforts VRT and BBC are making to get their video recordings digitally distributed. It was cool to see how they're experimenting with Apple TV and own linux based set top boxes.</p>
<p><a href="http://blog.elisehuard.be/">Elise Houard</a> later on did an introduction on <strong><a href="http://www.slideshare.net/ehuard/oauth">OAuth</a></strong> <em>(waf? o-af? open-waf? ... What a nightmare to pronounce this correctly)</em>, the open protocol for secure API authentication between web and desktop applications. (You've seen a protocol similar to OAuth, if you've used any application using the Flickr API before.) I fully support this standard, 'cause I'm sure it's more secure and correct than eg. most screen-scraping-based contact-importers used mostly, and it's good to have a standard for API providers, because they're all dealing with the issue of authorization.<br />
I'm still waiting to see some more sites support this standard, though, and I'm also keen to know in which way implementing <a href="http://oauth.net/">the OAuth protocol</a> affects the user experience, because I assume navigating away from a site could potentially scare a user maybe even more then asking for a password. I do see the advantages in allowing for partial access (in features - read and/or write - and in time - eg. limited for a week), but I think for most users it comes down to: "do I trust this site or not?", and if they do, will make OAuth or asking for a password of another site really make any difference?<br />
Must add I've been impressed by the recent implementations of 'check who of your <em>whatever-online-addresbook-service</em> are on here too' by Flickr and Dopplr recently.</p>
<p>Later that day <a href="http://www.krisbuytaert.be/blog/">Kris Buytaert</a> ranted about the fact (!) the web 2.0 services of today still don't work together the way they could, and should. Why can't all the services aggregate all the information one publishes on all the different sites, and eg. show me the restaurant tips from <a href="http://www.notsoso.com/">NotSoSo</a> created by my <a href="http://nl.netlog.com/oemebamo/myfriends">best Netlog friends</a> for the trip next week I've been planning using <a href="http://www.dopplr.com/traveller/oemebamo">Dopplr</a>? Should be possible ... Anyways, <a href="http://www.netlog.com/?all=1">we've</a> all definitely got some <a href="http://en.netlog.com/go/developer/documentation">work to do</a> to make this possible. The discussion took an interesting direction when <a href="http://pascal.vanhecke.info/">Pascal Van Hecke</a> spoke about initiatives in further decentralising your online presence, kind of returning to the subjects related to OpenID and OAuth.</p>
<p><a href="http://www.frank.be">Frank Louwers</a> shared his enthousiasm for the Baobab Health project, running in Malawi. In his <strong><a href="http://www.slideshare.net/frank_be/africa-on-rails">Africa On Rails</a></strong> talk he spoke about how a small team of developers is using Ruby On Rails to create kiosks that help suggesting the amount of drugs for HIV positive patients. This way not only the 160 doctors of Malawi can help out the 1 000 000 people suffering of AIDS. Their main concerns are power &#038; budget, but in an interview with one of the developers it was interesting to see how they appreciated and disliked the same things in Ruby as local Ruby developers, albeit in totally different circumstances. Definitely check out <a href="http://www.baobabhealth.org/">baobabhealth.org</a>.</p>
<p>My last session for the day was another demo, given by <a href="http://www.barclaey.com/">Bart Claeys</a>. He and a friend did a quick tour through the most important features of <strong><a href="http://www.adobe.com/products/photoshoplightroom/">Adobe Lightroom</a></strong>. I hope a demo of Apple's <a href="http://www.apple.com/aperture/">Aperture</a> is up next, so I can decide where to start managing the photos of the newly bought DSLR (Wooha!).</p>
<p>I left with a whole bunch of ideas, new people to follow on Twitter and lots of inspiration. Thumbs up for <a href="http://n00.be/">Thomas Bouve</a>, he organised a great BarCamp edition (for the very first time in my hometown, yeey!). </p>
<p>More info and linkage at: <a href="http://barcampgent.wikispaces.com/">http://barcampgent.wikispaces.com/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2008/04/14/delayed-barcamp-gent-2008-afterthoughts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Get Your Frontend Sorted</title>
		<link>http://www.jurriaanpersyn.com/archives/2008/04/03/get-your-frontend-sorted/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2008/04/03/get-your-frontend-sorted/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 09:28:27 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/archives/2008/04/03/get-your-frontend-sorted/</guid>
		<description><![CDATA[After a hectic weekend (and an even more hectic start of the week, thus the delay), here's the slides, video and some thoughts for the presentation I did with Lennart Schoors at last saturday's BarCamp Gent. It's a bunch of thoughts, experiences and stuff we learnt while working on the frontend for Netlog. While that [...]]]></description>
			<content:encoded><![CDATA[<p>After a hectic weekend (and an <a href="http://nl.netlog.com/go/news#news_100">even</a> <a href="http://nl.netlog.com/toon/photo/photoid=23290052#photos">more</a> <a href="http://corporate.netlog.com/blog/2008/04/netlog-back-online/">hectic</a> <a href="http://nl.netlog.com/oemebamo/photo/photoid=23296980#photos">start</a> <a href="http://nl.netlog.com/Dieter_be/photo/photoid=23396287#photos">of</a> <a href="http://twitter.com/oemebamo/statuses/781665259">the</a> <a href="http://twitter.com/oemebamo/statuses/780417110">week</a>, thus the delay), here's the slides, video and some thoughts for the presentation I did with <a href="http://www.lensco.be">Lennart Schoors</a> at last saturday's BarCamp Gent. It's a bunch of thoughts, experiences and stuff we learnt while working on the frontend for Netlog. While that frontend's far from being a finished and fully optimized product, we think there's somehow a few tips we could share;</p>
<div style="text-align: center;" id="__ss_326799"><object style="margin:0px" width="710" height="568"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=get-your-frontend-sorted-barcamp-gent-2008-1206802590372925-5"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=get-your-frontend-sorted-barcamp-gent-2008-1206802590372925-5" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="710" height="568"></embed></object></div>
<p>Lots of thoughts were crammed in this 20 minute session, so I hope we didn't overwhelm too much ... Credit where credit is due, so a shout out to Lennart, to the <a href="http://developer.yahoo.com/performance/">Yahoo Performance team</a> and <a href="http://stevesouders.com/">Steve Souders</a> for stressing the importance of frontend performance, to <a href="http://www.getfirebug.com/">Firebug</a> &#038; <a href="http://developer.yahoo.com/yslow/">YSlow!</a> for being indispensible tools, and to our colleagues for making <a href="http://corporate.netlog.com">Netlog</a> an inspiring to work for. </p>
<p>There's a <a href="http://video.google.com/videoplay?docid=-7726783618355799565&#038;pr=goog-sl">video recording of the presentation</a> too, thanks to <a href="http://lvb.net/">Luc Van Braekel</a>. <em>I wouldn't watch it, though.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2008/04/03/get-your-frontend-sorted/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>@media ajax 2007, london (day two)</title>
		<link>http://www.jurriaanpersyn.com/archives/2007/11/21/media-ajax-2007-london-day-two/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2007/11/21/media-ajax-2007-london-day-two/#comments</comments>
		<pubDate>Wed, 21 Nov 2007 20:04:35 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/archives/2007/11/21/media-ajax-2007-london-day-two/</guid>
		<description><![CDATA[Phew! Back home from the 5 day London trip now ... What can I say? Damn what a city! Gent feels like no-man's-land now. Day two of the @media ajax conference was definitely as interesting and inspiring as day one. It was much more on a technical level with some really neat talks by Dan [...]]]></description>
			<content:encoded><![CDATA[<p>Phew! Back home from the 5 day London trip now ... What can I say? Damn what a city! Gent feels like no-man's-land now.</p>
<p>Day two of the <a href="http://vivabit.com/atmediaAjax/">@media ajax conference</a> was definitely as interesting and inspiring as <a href="http://www.jurriaanpersyn.com/archives/2007/11/20/media-ajax-2007-london/">day one</a>. It was much more on a technical level with some really neat talks by <a href="http://www.danwebb.net/">Dan Webb</a>, <a href="http://alex.dojotoolkit.org/">Alex Russell</a> (Dojo), <a href="http://ejohn.org/">John Resig</a> (jQuery Demo) and <a href="http://www.crockford.com/">Douglas Crockford</a> (JSLint), a hardcore session by <a href="http://en.wikipedia.org/wiki/Brendan_Eich">Brendan Eich</a> and an entertaining panel to finish the two days of pure javascript shizzle. The conference being so specialised (in topics as well as in audience), definitely made for an interesting two days without too much useless introductary mumbo jumbo. </p>
<p>Meanwhile I've found these resources: <a href="http://www.slideshare.net/tag/atmediaajax">the first slides popping up at slideshare</a> and <a href="http://lectale.blogspot.com/">some thoughts by <em>James</em></a> on the individual sessions. Apart from that not much popping up at the <a href="http://technorati.com/search/atmedia">Technorati-pages</a> yet. Here's <a href="http://nl.netlog.com/oemebamo/photo/setid=196012">some of my own pictures from London</a>, with a photo or two from the conference.  As said in my previous post on day one, I hope to be sharing my notes and thoughts with you soon ... </p>
<p>A big thank you to <a href="http://corporate.netlog.com">Netlog</a> for getting me at this conference. Up to me to share the knowledge now, :).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2007/11/21/media-ajax-2007-london-day-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unserializing stored $_SESSION data in PHP</title>
		<link>http://www.jurriaanpersyn.com/archives/2006/12/23/unserializing-stored-_session-data-in-php/</link>
		<comments>http://www.jurriaanpersyn.com/archives/2006/12/23/unserializing-stored-_session-data-in-php/#comments</comments>
		<pubDate>Sat, 23 Dec 2006 17:02:35 +0000</pubDate>
		<dc:creator>oemebamo</dc:creator>
				<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://www.jurriaanpersyn.com/archives/2006/12/23/unserializing-stored-_session-data-in-php/</guid>
		<description><![CDATA[While improving the way we handle and store sessions for the *.facebox.com websites we needed a way to access, read, change and store saved php-sessions (we keep them in a memory cache). Apparently stored session are not simple serialized strings of the $_SESSION-object *. Well, almost, but not exactly. So we wrote our own ... [...]]]></description>
			<content:encoded><![CDATA[<p>While improving the way we handle and store sessions for the <a href="http://www.facebox.com/?all=1">*.facebox.com</a> websites we needed a way to access, read, change and store saved php-sessions (we keep them in a memory cache). Apparently stored session are not simple serialized strings of the $_SESSION-object <a href="#why">*</a>. Well, almost, but not exactly. So we wrote our own ... <em>Or at least:</em> Had to write our own.</p>
<p>The following function unserializes encrypted session data and returns an object representing the $_SESSION object. A serialized $_SESSION object differs from a normal serialize () in that each key of the $_SESSION-object/array is seperated by | from it's (usual php-)serialized value.</p>
<div class="igBar"><span id="lphp-24"><a href="#" onclick="javascript:showPlainTxt('php-24'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">PHP:</span>
<div id="php-24">
<div class="php">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;">/**</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;"> * This function unserializes a stored session. This serialisation is slightly different then the </span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;"> * php-serializer (each key of $_SESSION is seperated by a |).</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;"> *</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;"> * @param&nbsp; string&nbsp; &nbsp; $serialized_string&nbsp; a serialized representation of a session object</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;"> * @return mixed_var&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;an unserialized object</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000;"> */</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#000000; font-weight:bold;">function</span> <a href="http://www.php.net/unserialize"><span style="color:#000066;">unserialize</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#0000FF;">$object</span> = <a href="http://www.php.net/array"><span style="color:#000066;">array</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span>&nbsp; = <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#CC66CC;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#0000FF;">$open</span>&nbsp; &nbsp; = <span style="color:#CC66CC;color:#800000;">0</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#0000FF;">$openAcc</span> = <span style="color:#CC66CC;color:#800000;">0</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#0000FF;">$key</span>&nbsp; &nbsp; &nbsp;= <span style="color:#FF0000;">''</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#616100;">for</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$i</span> = <span style="color:#CC66CC;color:#800000;">1</span>, <span style="color:#0000FF;">$count</span> = <a href="http://www.php.net/strlen"><span style="color:#000066;">strlen</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#41;</span>; <span style="color:#0000FF;">$i</span> &lt;<span style="color:#0000FF;">$count</span>; <span style="color:#0000FF;">$i</span>++<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$curChar</span> = <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span><span style="color:#006600; font-weight:bold;">&#93;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$curChar</span> == <span style="color:#FF0000;">'|'</span> &amp;&amp; <span style="color:#0000FF;">$open</span> == <span style="color:#CC66CC;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$key</span> = <span style="color:#0000FF;">$buffer</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span> = <span style="color:#FF0000;">''</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">continue</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$curChar</span> == <span style="color:#FF0000;">'{'</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>-<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#FF0000;">':'</span> &amp;&amp; <span style="color:#0000FF;">$open</span> == <span style="color:#CC66CC;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$openAcc</span> ++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$curChar</span> == <span style="color:#FF0000;">'}'</span> &amp;&amp; <span style="color:#0000FF;">$open</span> == <span style="color:#CC66CC;color:#800000;">0</span> &amp;&amp; <span style="color:#0000FF;">$openAcc</span>&gt; <span style="color:#CC66CC;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$openAcc</span> --;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$openAcc</span> == <span style="color:#CC66CC;color:#800000;">0</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>-<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#FF0000;">'{'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$object</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$key</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <a href="http://www.php.net/array"><span style="color:#000066;">array</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span> = <span style="color:#FF0000;">''</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">continue</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$openAcc</span> == <span style="color:#CC66CC;color:#800000;">0</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>-<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#FF0000;">';'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$object</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$key</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <a href="http://www.php.net/unserialize"><span style="color:#000066;">unserialize</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$buffer</span> . <span style="color:#0000FF;">$curChar</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span> = <span style="color:#FF0000;">''</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">continue</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$openAcc</span> == <span style="color:#CC66CC;color:#800000;">0</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>-<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#FF0000;">'}'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$object</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$key</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <a href="http://www.php.net/unserialize"><span style="color:#000066;">unserialize</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$buffer</span> . <span style="color:#0000FF;">$curChar</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span> = <span style="color:#FF0000;">''</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">continue</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$curChar</span> == <span style="color:#FF0000;">'&quot;'</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>-<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#FF0000;">':'</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>+<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> != <span style="color:#FF0000;">';'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$open</span>++;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$curChar</span> == <span style="color:#FF0000;">'&quot;'</span> &amp;&amp; <span style="color:#0000FF;">$serialized_string</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$i</span>+<span style="color:#CC66CC;color:#800000;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> == <span style="color:#FF0000;">';'</span> <span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$open</span>--;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">elseif</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$curChar</span> == <span style="color:#FF0000;">';'</span> &amp;&amp; <span style="color:#0000FF;">$open</span> == <span style="color:#CC66CC;color:#800000;">0</span> &amp;&amp; <span style="color:#0000FF;">$openAcc</span> == <span style="color:#CC66CC;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$object</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#0000FF;">$key</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <a href="http://www.php.net/unserialize"><span style="color:#000066;">unserialize</span></a> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$buffer</span> . <span style="color:#0000FF;">$curChar</span><span style="color:#006600; font-weight:bold;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span> = <span style="color:#FF0000;">''</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#616100;">continue</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF;">$buffer</span> .= <span style="color:#0000FF;">$curChar</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#616100;">return</span> <span style="color:#0000FF;">$object</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#006600; font-weight:bold;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>The function we wrote should do the same as other attempts at writing such a function; as you can find <a href="http://nl2.php.net/manual/nl/function.session-decode.php#56106">here</a>. But which one is the most efficient?<br />
It is different from <a href="http://nl2.php.net/manual/nl/function.session-decode.php#55307">these</a> or <a href="http://nl2.php.net/manual/nl/function.session-decode.php#52869">these</a> other attempts in that it can handle ';' or '|' in values (php serializing doesn't escape those characters).</p>
<p>We opted not to use <strong>session_decode ()</strong> and <strong>session_encode ()</strong> for temporary overwriting of the $_SESSION object (like <a href="http://nl2.php.net/manual/nl/function.session-decode.php#61177">this</a> solution), because of security reasons.</p>
<p>Still this feels like it's more of a work-around because we're mimicking existing functionality. Who guarantees our function does exactly the same as the way php serializes the sessions internally? All seems to be going fine though, we haven't seen any problems with the sessions related to this function on our sites yet, and if you look at the amount of members we serve on the Facebox sites it feels like a pretty stable and robust solution.</p>
<p>Should add that credit for this algorithm goes out to <a href="http://www.incrowd.be/team.html">Toon Coppens</a>.</p>
<p><a name="tip"></a><strong>*</strong> <em>Does anyone know why?</em> I will have to remember to ask the mySQL consultant <a href="http://kris.koehntopp.de/">Kristian Köhntopp</a>, that'll be helping us out with mySQL soon. I'm told he's one of the peeps who introduced the sessions-concept in php3. Look forward to learning from him ...</p>
<p><strong>Update</strong> (2007-01-07): Fixed a bug in handling empty arrays.<br />
<strong>Update 2</strong> (2007-01-09): Fixed a bug in handling nested arrays.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jurriaanpersyn.com/archives/2006/12/23/unserializing-stored-_session-data-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.426 seconds -->

