<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>domas mituzas &#187; memcached</title>
	<atom:link href="http://dom.as/tag/memcached/feed/" rel="self" type="application/rss+xml" />
	<link>http://dom.as</link>
	<description></description>
	<lastBuildDate>Thu, 02 Feb 2012 21:29:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='dom.as' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/6e344c6e0cd7462eb056f8b98eb2cbcd?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>domas mituzas &#187; memcached</title>
		<link>http://dom.as</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://dom.as/osd.xml" title="domas mituzas" />
	<atom:link rel='hub' href='http://dom.as/?pushpress=hub'/>
		<item>
		<title>Memcached for small objects</title>
		<link>http://dom.as/2008/12/25/memcached-for-small-objects/</link>
		<comments>http://dom.as/2008/12/25/memcached-for-small-objects/#comments</comments>
		<pubDate>Thu, 25 Dec 2008 14:06:00 +0000</pubDate>
		<dc:creator>Domas Mituzas</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[memory]]></category>

		<guid isPermaLink="false">http://dammit.lt/?p=296</guid>
		<description><![CDATA[Memcached quite often ends up as a store for very small objects (small key and some integer value), though it isn&#8217;t really designed to do this kind of work by default. Current memory management is based on slabs (200 of &#8230; <a href="http://dom.as/2008/12/25/memcached-for-small-objects/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dom.as&amp;blog=190075&amp;post=296&amp;subd=domasmituzas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Memcached quite often ends up as a store for very small objects (small key and some integer value), though it isn&#8217;t really designed to do this kind of work by default. Current memory management is based on slabs (200 of them), where objects are grouped by similar size &#8211; though actual sizes are pre-defined at startup based on few configuration parameters.</p>
<p>By default memcached would have slabs based on assumption, that smallest object size will have 48 bytes of data (thats without item header), and will increase the slab sizes in +25% steps:</p>
<pre>
slab class   1: chunk size    104 perslab 10082
slab class   2: chunk size    136 perslab  7710
slab class   3: chunk size    176 perslab  5957
slab class   4: chunk size    224 perslab  4681
...
</pre>
<p>So, in this case, it allocates at least 104 bytes per object, and next steps are way behind. Fortunately, there&#8217;re some quick steps to have better efficiency:<span id="more-296"></span></p>
<h3>Configuration!</h3>
<p>There&#8217;re two parameters for this:</p>
<ul>
<li>-n &#8211; minimum space allocated for key+value+flags, defaults at 48</li>
<li>-f &#8211; chunk growth factor, default 1.25</li>
</ul>
<p>With these settings memcached will define just 38 slabs, ranging from 104 to 458992 byte sized chunks. Even in case of mixed workloads one can use <code>-n 5 -f 1.05</code> &#8211; this will define ~170 slabs, where low values will increase in 8-byte chunks, and smallest slabs would look like this:</p>
<pre>
slab class   1: chunk size     64 perslab 16384
slab class   2: chunk size     72 perslab 14563
slab class   3: chunk size     80 perslab 13107
...
</pre>
<p>It would get way higher memory efficiency for larger objects too (6k steps at 100k object sizes, rather than 30k steps with default configuration). Of course, more slabs means that there&#8217;re more eviction queues, and in case distribution of object sizes changes, it would have more memory fragmentation, though thats nothing a restart can&#8217;t resolve ;-)</p>
<h3>Internal storage</h3>
<p>Every data item has a header, which includes pointers to other item structures, and additional metadata. One of obvious things that will be fixed in later releases is the CAS (compare-and-swap) metadata (8 bytes per object), which is stored for every object &#8211; though very rarely used by users (one needs to use special breed commands). In future versions this might get resolved, and a very dirty hack would be changing cas_id to be uint8_t in memcached.h (heeeee!).</p>
<p>There&#8217;re also multiple pointers inside the header &#8211; and on 64 bit systems they take 64 bits &#8211; though in theory chunks inside memory pages (slabs can have multiple memory pages assigned) can be addressed with 16-bit pointers. Of course, the easy workaround here is simply compiling memcached as 32-bit binary &#8211; though then it won&#8217;t be able to address more than ~3GB per-instance (and running multiple memcached instances is straightforward).</p>
<p>There&#8217;s another internal CPU-vs-memory optimization, where objects internally end up aligned at 8-byte boundaries. Hacking CHUNK_ALIGN_BYTES at slabs.c (I set it to 2) allows us to have chunk sizes increased in much smaller steps.</p>
<h3>Data!</h3>
<p>Have small keys. Have small data. Compression at application will reduce network i/o, less roundtrips and system calls, and better memory efficiency in the end. Pack integers inside keys into base250 or so (skip whitespace), store binary data.</p>
<p>It is usually way less cycles to have more efficient storage, compared to additional cycles when a cache miss happens :)</p>
<h3>Testing &amp; summary</h3>
<p>I tried to simulate the most edge case out of all edge cases &#8211; integer key and one byte data objects being inserted into 64M memcached instance.</p>
<ul>
<li>I could fit in 645k objects inside regular memcached, 932k after factor changes.</li>
<li>Simple 32-bit build fit in 763k objects, 1164k after factor changes, 1180k after alignment change</li>
<li>After removing CAS support, it fit 1378k, 1461k after reducing key with base250</li>
</ul>
<p>So, I could have such slab size distribution (it facilitates objects up to 45k in size):</p>
<pre>
slab class   1: chunk size     33 perslab 31775
slab class   2: chunk size     34 perslab 30840
slab class   3: chunk size     35 perslab 29959
slab class   4: chunk size     36 perslab 29127
...
</pre>
<h3>MySQL!</h3>
<p>64M-sized MEMORY table will be able to store 2087k (INT,TINYINT) entries. When people aim for no-eviction storage, MySQL can be way more efficient.</p>
<p>Interesting though, the PK will take as much space as data itself (what simply asks PK to be held together with data, like InnoDB does (it will actually fit 2500k entries in 64M).  With custom MySQL engines this shouldn&#8217;t be too difficult for those who really hit the edge cases, right? :)</p>
<p>Oh well, last I&#8217;ve heard, memcached is going to have storage engine support too, I wonder how fun will be hacking those (someone ages ago plugged BDB into memcached and called it Tugela.. ;)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/domasmituzas.wordpress.com/296/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/domasmituzas.wordpress.com/296/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/domasmituzas.wordpress.com/296/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/domasmituzas.wordpress.com/296/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/domasmituzas.wordpress.com/296/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/domasmituzas.wordpress.com/296/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/domasmituzas.wordpress.com/296/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/domasmituzas.wordpress.com/296/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dom.as&amp;blog=190075&amp;post=296&amp;subd=domasmituzas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://dom.as/2008/12/25/memcached-for-small-objects/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/c660a6eb3a4005232acb111303bef12c?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">domasmituzas</media:title>
		</media:content>
	</item>
		<item>
		<title>Replication will live!</title>
		<link>http://dom.as/2008/04/12/replication-will-live/</link>
		<comments>http://dom.as/2008/04/12/replication-will-live/#comments</comments>
		<pubDate>Sat, 12 Apr 2008 06:30:46 +0000</pubDate>
		<dc:creator>Domas Mituzas</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[replication]]></category>

		<guid isPermaLink="false">http://dammit.lt/?p=101</guid>
		<description><![CDATA[Brian exposed some of his internal letters about death of replication (caused by memcached). Back when he wrote this, I responded back a bit too. Now as quite a few people really want to burry replication, let me point out &#8230; <a href="http://dom.as/2008/04/12/replication-will-live/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dom.as&amp;blog=190075&amp;post=101&amp;subd=domasmituzas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Brian <a href='http://krow.livejournal.com/590912.html'>exposed</a> some of his internal letters about death of replication (caused by memcached). Back when he wrote this, I responded back a bit too. Now as quite a few people really want to burry replication, let me point out some of reasoning why it will live.<br />
<span id="more-101"></span><br />
First of all, both MySQL and memcached are slow (however you look at it, they&#8217;re both fast) &#8211; in proper gigabit environment both respond in a millisecond or so (well, MySQL is closed to 1.5ms). The major task becomes putting as much of work done in that round trip as possible.</p>
<p>Replication lag? The major problem with it was fixed by Google patches back in 4.0, finally hitting stock MySQL in 5.1. Now replication thread doesn&#8217;t get queued due to concurrency, and always enters the execution. Use binary log position serialization for reading users, and they will never notice replication lag.</p>
<p>More servers? Also more performance. Putting everything to memcached? Lots of stuff still has to be written to database. Once it is in database anyway, one can query it from database too. In low hitrate situations using memcached will be 3x slower, than just fetching data from database (get/get/set vs get). I&#8217;ve seen lots of code that was enthusiastic to use memcached, but authors didn&#8217;t actually try to profile what are the hit ratios.</p>
<p>Major problem with memcached is that it is a hash table. All it supports in data retrieval is asking for a key and getting a value. Which works great in situations where one just has a key and gets a value. Now if 50 keys are needed, memcached will need 50 lookups, quite often &#8211; routed to 50 different servers. Thats single database B-Tree read. How does one fetch all keys from 1 to 10000 with memcached? Thats right &#8211; ask for all of them. Of course, it is easy to resolve some of inefficiency by having separate memcached clusters for different tasks, appending information to multiple tracking objects, but thats where the ease of distribution starts fading, and development and administration needs surface.</p>
<p>memcached APIs now start supporting replication too &#8211; but flapping hosts can get environment out of sync quite fast then (host disappears, failover host starts getting traffic, host comes back with stale data&#8230;). Solution &#8211; object generation management, reading from multiple hosts, etc. &#8211; here again, solving simple problem already needs quite some complexity.</p>
<p>Add the ACID properties of databases, which quite often make whole development much easier &#8211; what ends up quite difficult to achieve in completely distributed &#8216;get/set&#8217; environment.</p>
<p>And by the way &#8211; memcached can be outgunned. Hot objects can be cached directly on local application server stores, like APC object cache, file system, etc. New application servers nowadays have lots of memory.. :) Need global state? Just broadcast it to all.</p>
<p>There&#8217;re much more what replicated databases can provide &#8211; more complex views, all indexed and snappy, single line change doesn&#8217;t need invalidation of hundreds or thousands of objects around, and it all comes to interactivity and serving user&#8217;s needs better. Single line change immediately visible to all the users around.</p>
<p>Brian suggests using job queue systems and pushing <i>everything</i> to memcached &#8211; which makes it a dump of stuff instead of a cache. Putting more information that might be needed ends up with unnecessary evictions, which decrease efficiency of system too. Building those objects needs reading from database (or other persistent store), and eventually they end up in database too. Surprise &#8211; they can be served from database as well! :)</p>
<p>Anyway, memcaching ideas are moving forward, so does database replication. There is lots of room for replication to evolve yet &#8211; making it more async, parallel, relaxed. Whole MySQL protocol might be better &#8211; now it is all synchronous and boring.</p>
<p>Though replication has the storage overhead &#8211; more copies are usually saved &#8211; it also allows utilizing those copies in different way, different indexing schemes, though still maintaining same image of data on different nodes. Even better, such application-specific &#8216;roles&#8217; of slaves can migrate from one node to other, heating up different segments of data.</p>
<p>The role of database replication will still remain core for scaling out reads for various workflows. Database allows incremental changes to infinite datasets required by various applications. Replication just multiples system capacity for presenting those datasets. Thats good. If it was up to me, I&#8217;d let it live.</p>
<p><i>P.S. Our current memcached cluster has 80 nodes, each providing 2gb of storage. When used properly, memcached is great tool too. :)</i></p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/domasmituzas.wordpress.com/101/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/domasmituzas.wordpress.com/101/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/domasmituzas.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/domasmituzas.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/domasmituzas.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/domasmituzas.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/domasmituzas.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/domasmituzas.wordpress.com/101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/domasmituzas.wordpress.com/101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/domasmituzas.wordpress.com/101/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=dom.as&amp;blog=190075&amp;post=101&amp;subd=domasmituzas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://dom.as/2008/04/12/replication-will-live/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/c660a6eb3a4005232acb111303bef12c?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">domasmituzas</media:title>
		</media:content>
	</item>
	</channel>
</rss>
