<?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>Richard Jones, Esq. &#187; memcached</title>
	<atom:link href="http://www.metabrew.com/article/tag/memcached/feed" rel="self" type="application/rss+xml" />
	<link>http://www.metabrew.com</link>
	<description>Erlang, PHP, C, C++, Java, PostgreSQL, MySQL, Hadoop, Linux, awk, bash, sed, grep, screen, vim, irc, ssh etc...</description>
	<lastBuildDate>Sun, 20 Dec 2009 18:59:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Erlang libketama driver &#8211; Consistent Hashing</title>
		<link>http://www.metabrew.com/article/erlang-libketama-driver-consistent-hashing/</link>
		<comments>http://www.metabrew.com/article/erlang-libketama-driver-consistent-hashing/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 13:41:54 +0000</pubDate>
		<dc:creator>RJ</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[driver]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[hashing]]></category>
		<category><![CDATA[ketama]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://www.metabrew.com/?p=36</guid>
		<description><![CDATA[All the data I need from memcached is assigned to servers using a consistent hashing mechanism, implemented as libketama &#8211; a shared library written in C. We use a php extension to wrap this, and also have a pure java implementation. Rather than port the algorithm to Erlang, I wrote a an Erlang driver. There [...]]]></description>
			<content:encoded><![CDATA[<p>All the data I need from memcached is assigned to servers using a consistent hashing mechanism, <a href="http://www.last.fm/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients">implemented as libketama</a> &#8211; a shared library written in C. We use a php extension to wrap this, and also have a pure java implementation. Rather than port the algorithm to Erlang, I wrote a an Erlang driver.</p>
<p>There are 3 things covered here:</p>
<ul>
<li>A small driver program written in C (using libketama)</li>
<li>Some basic testing from the shell using Perl and xxd</li>
<li>The Erlang gen_server that calls it</li>
</ul>
<h2>C driver program</h2>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="coMULTI">/* &nbsp;Expects a one-byte length header, followed by a key (&lt;255bytes)</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &nbsp;Returns an ip:port string with 1 byte len header</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*/</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co2">#include &lt;ketama.h&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;stdio.h&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;stdlib.h&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;unistd.h&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#include &lt;string.h&gt;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">typedef</span> <span class="kw4">unsigned</span> <span class="kw4">char</span> byte;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">int</span> read_exact<span class="br0">&#40;</span>byte *buf, <span class="kw4">int</span> len<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw4">int</span> i, got = <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">do</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>i=read<span class="br0">&#40;</span><span class="nu0">0</span>,buf+got, len-got<span class="br0">&#41;</span><span class="br0">&#41;</span>&lt;=<span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">return</span> i;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; got += i;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">while</span><span class="br0">&#40;</span>got&lt;len<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">return</span> len;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">int</span> main<span class="br0">&#40;</span><span class="kw4">int</span> argc, <span class="kw4">char</span> **argv<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>argc==<span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;Usage: %s &lt;ketama.servers file&gt;<span class="es0">\n</span>&quot;</span>, *argv<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">1</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; ketama_continuum c;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; ketama_roll<span class="br0">&#40;</span> &amp;c, *++argv <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; mcs *m;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; byte len;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; byte buffer<span class="br0">&#91;</span><span class="nu0">256</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span> <span class="nu0">1</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span> <span class="nu0">1</span> != read_exact<span class="br0">&#40;</span>&amp;len, <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>len &gt;= <span class="nu0">255</span> <span class="br0">&#41;</span> <span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; read_exact<span class="br0">&#40;</span><span class="br0">&#40;</span>byte *<span class="br0">&#41;</span>&amp;buffer, <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>len<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; buffer<span class="br0">&#91;</span>len<span class="br0">&#93;</span> = <span class="st0">&#8216;<span class="es0">\0</span>&#8216;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; m = ketama_get_server<span class="br0">&#40;</span> <span class="br0">&#40;</span><span class="kw4">char</span> *<span class="br0">&#41;</span> &amp;buffer, c <span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; sprintf<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">char</span> *<span class="br0">&#41;</span>&amp;buffer, <span class="st0">&quot;%s&quot;</span>,m-&gt;ip<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> respleni = strlen<span class="br0">&#40;</span>m-&gt;ip<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">char</span> l = <span class="br0">&#40;</span>0xff &amp; respleni<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; write<span class="br0">&#40;</span><span class="nu0">1</span>, &amp;l, <span class="nu0">1</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; write<span class="br0">&#40;</span><span class="nu0">1</span>, <span class="br0">&#40;</span><span class="kw4">char</span>*<span class="br0">&#41;</span>&amp;buffer, respleni<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><br/></p>
<h2>Testing the driver with Perl and xxd</h2>
<p>Before writing the Erlang bit, it&#8217;d be nice to know the driver program does what we expect.  Will send the driver a 1-byte length header followed by the key, and expect a 1-byte length header and the value as a response. Say we&#8217;re hashing a memcached key &#8216;user:123&#8242; to a server, we can do what the Erlang port does with a bit of perl, and the &#8216;xxd&#8217; command to see output in binary.</p>
<p><code>perl -e '$key="user:123"; $len=pack("C",length($key)); print $len; print $key;' | xxd -b</code></p>
<pre>0000000: 00001000 01110101 01110011 01100101 01110010 00111010  .user:
0000006: 00110001 00110010 00110011                             123</pre>
<p>Note the first byte (00001000) printed before the key is the length of the key, 8. Now let&#8217;s send this to the driver program and check the response (provide a valid ketama.servers file):</p>
<p><code>perl -e '$key="user:123"; $len=pack("C",length($key)); print $len; print $key;' | ./ketama_erlang_driver /var/ketama.servers | xxd -b</code></p>
<pre>0000000: 00010000 00110001 00110000 00101110 00110000 00101110  .10.0.
0000006: 00110001 00101110 00110001 00110001 00111000 00111010  1.118:
000000c: 00110001 00110001 00110010 00110001 00110001           11211</pre>
<p>The first byte of the response (00010000) is 16, which is the length of the server address returned by the driver, &#8220;10.0.1.118:11211&#8243; &#8211; It does what we expect, onwards&#8230;</p>
<h2>The Erlang bit</h2>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">-<span class="kw2">module</span><span class="br0">&#40;</span>ketama<span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">-<span class="kw2">behaviour</span><span class="br0">&#40;</span>gen_server<span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">-<span class="kw2">export</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="kw3">start_link</span>/<span class="nu0">0</span>, <span class="kw3">start_link</span>/<span class="nu0">1</span>, <span class="kw3">start_link</span>/<span class="nu0">2</span>, getserver/<span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">-<span class="kw2">export</span><span class="br0">&#40;</span><span class="br0">&#91;</span>init/<span class="nu0">1</span>, handle_call/<span class="nu0">3</span>, handle_cast/<span class="nu0">2</span>, handle_info/<span class="nu0">2</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp;terminate/<span class="nu0">2</span>, code_change/<span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">-record<span class="br0">&#40;</span>state, <span class="br0">&#123;</span>port<span class="br0">&#125;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">start_link</span><span class="br0">&#40;</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw3">start_link</span><span class="br0">&#40;</span><span class="st0">&quot;/web/site/GLOBAL/ketama.servers&quot;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">start_link</span><span class="br0">&#40;</span><span class="re0">ServersFile</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw3">start_link</span><span class="br0">&#40;</span><span class="re0">ServersFile</span>, <span class="st0">&quot;/usr/bin/ketama_erlang_driver&quot;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw3">start_link</span><span class="br0">&#40;</span><span class="re0">ServersFile</span>, <span class="re0">BinPath</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="me1">gen_server</span>:<span class="kw3">start_link</span><span class="br0">&#40;</span><span class="br0">&#123;</span>local, ?<span class="re0">MODULE</span><span class="br0">&#125;</span>, ?<span class="re0">MODULE</span>, <span class="br0">&#91;</span><span class="re0">ServersFile</span>, <span class="re0">BinPath</span><span class="br0">&#93;</span>, <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">getserver<span class="br0">&#40;</span><span class="re0">Key</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="me1">gen_server</span>:<span class="kw3">call</span><span class="br0">&#40;</span>?<span class="re0">MODULE</span>, <span class="br0">&#123;</span>getserver, <span class="re0">Key</span><span class="br0">&#125;</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">%%</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">init<span class="br0">&#40;</span><span class="br0">&#91;</span><span class="re0">ServersFile</span>, <span class="re0">BinPath</span><span class="br0">&#93;</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">Exe</span> = <span class="re0">BinPath</span> ++ <span class="st0">&quot; &quot;</span> ++ <span class="re0">ServersFile</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="re0">Port</span> = open_port<span class="br0">&#40;</span><span class="br0">&#123;</span>spawn, <span class="re0">Exe</span><span class="br0">&#125;</span>, <span class="br0">&#91;</span>binary, <span class="br0">&#123;</span>packet, <span class="nu0">1</span><span class="br0">&#125;</span>, use_stdio<span class="br0">&#93;</span><span class="br0">&#41;</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span>ok, #state<span class="br0">&#123;</span>port=<span class="re0">Port</span><span class="br0">&#125;</span><span class="br0">&#125;</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">handle_call<span class="br0">&#40;</span><span class="br0">&#123;</span>getserver, <span class="re0">Key</span><span class="br0">&#125;</span>, _<span class="re0">From</span>, #state<span class="br0">&#123;</span>port=<span class="re0">Port</span><span class="br0">&#125;</span> = <span class="re0">State</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">Port</span> ! <span class="br0">&#123;</span>self<span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="br0">&#123;</span>command, <span class="re0">Key</span><span class="br0">&#125;</span><span class="br0">&#125;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">receive</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><span class="re0">Port</span>, <span class="br0">&#123;</span>data, <span class="re0">Data</span><span class="br0">&#125;</span><span class="br0">&#125;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>reply, <span class="re0">Data</span>, <span class="re0">State</span><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">after</span> <span class="nu0">1000</span> -&gt; <span class="co1">% if it takes this long, you have serious issues.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>stop, ketama_port_timeout, <span class="re0">State</span><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">end</span>.</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">handle_cast<span class="br0">&#40;</span>_<span class="re0">Msg</span>, <span class="re0">State</span><span class="br0">&#41;</span> -&gt; &nbsp; &nbsp;<span class="br0">&#123;</span>noreply, <span class="re0">State</span><span class="br0">&#125;</span>.</div>
</li>
<li class="li1">
<div class="de1">handle_info<span class="br0">&#40;</span><span class="br0">&#123;</span><span class="st0">&#8216;EXIT&#8217;</span>, <span class="re0">Port</span>, <span class="re0">Reason</span><span class="br0">&#125;</span>, #state<span class="br0">&#123;</span>port = <span class="re0">Port</span><span class="br0">&#125;</span> = <span class="re0">State</span><span class="br0">&#41;</span> -&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span>stop, <span class="br0">&#123;</span>port_terminated, <span class="re0">Reason</span><span class="br0">&#125;</span>, <span class="re0">State</span><span class="br0">&#125;</span>.</div>
</li>
<li class="li2">
<div class="de2">terminate<span class="br0">&#40;</span><span class="br0">&#123;</span>port_terminated, _<span class="re0">Reason</span><span class="br0">&#125;</span>, _<span class="re0">State</span><span class="br0">&#41;</span> -&gt; &nbsp; &nbsp;<span class="me1">ok</span>;</div>
</li>
<li class="li1">
<div class="de1">terminate<span class="br0">&#40;</span>_<span class="re0">Reason</span>, #state<span class="br0">&#123;</span>port = <span class="re0">Port</span><span class="br0">&#125;</span> = _<span class="re0">State</span><span class="br0">&#41;</span> -&gt; &nbsp; &nbsp; <span class="me1">port_close</span><span class="br0">&#40;</span><span class="re0">Port</span><span class="br0">&#41;</span>.</div>
</li>
<li class="li1">
<div class="de1">code_change<span class="br0">&#40;</span>_<span class="re0">OldVsn</span>, <span class="re0">State</span>, _<span class="re0">Extra</span><span class="br0">&#41;</span> -&gt; &nbsp; &nbsp; <span class="br0">&#123;</span>ok, <span class="re0">State</span><span class="br0">&#125;</span>.</div>
</li>
</ol>
</div>
<p><br/><br />
This code can be found in the erlang directory of the ketama source in svn:<br />
<code>svn://svn.audioscrobbler.net/misc/ketama/</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabrew.com/article/erlang-libketama-driver-consistent-hashing//feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
