<?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>Grep My Mind &#187; semaphore</title>
	<atom:link href="http://www.grepmymind.com/tags/semaphore/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grepmymind.com</link>
	<description>Wonder what’s on my mind? Now you know.</description>
	<lastBuildDate>Thu, 11 Jun 2009 20:00:55 +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>memcached PHP semaphore &amp; cache expiration handling</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/</link>
		<comments>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 21:01:41 +0000</pubDate>
		<dc:creator>Michael Tougeron</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[semaphore]]></category>

		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/</guid>
		<description><![CDATA[There are a lot of different ways that people use memcached and PHP. The most common of which is probably your basic set and get to cache data from your database. function get_my_data1&#40;&#41; &#123; &#160; &#160; $cache_id = &#34;mykey&#34;; &#160; &#160; $data = $memcache_obj-&#62;get&#40;$cache_id&#41;; &#160; &#160; if &#40; !$data &#41; &#123; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>There are a lot of different ways that people use <a href="http://www.danga.com/memcached/">memcached</a> and <a href="http://php.net/manual/en/ref.memcache.php">PHP</a>.   The most common of which is probably your basic <a href="http://php.net/manual/en/function.Memcache-set.php">set </a> and <a href="http://php.net/manual/en/function.Memcache-get.php">get</a> to cache data from your database.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> get_my_data1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&quot;mykey&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = get_data_from_db_function<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span>, <span class="re0">$data</span>, <span class="re0">$sec_to_cache_for</span><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; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>But what if the query that&#8217;s going to hit the database is pretty intensive and you don&#8217;t want more than one user to hit the db at a time?  That&#8217;s easily handling via a <a href="http://en.wikipedia.org/wiki/Semaphore_(programming)">semaphore</a> lock.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> get_my_data2<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&quot;mykey&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// check to see if someone has already set the lock</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data_lock</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</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="re0">$data_lock</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$lock_counter</span> = <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// loop until you find that the lock has been released. &nbsp;that implies that the query has finished</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">do</span> <span class="kw1">while</span> <span class="br0">&#40;</span> <span class="re0">$data_lock</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// you may only want to wait for a specified period of time.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// one second is usually sufficient since your goal is to always have sub-second response time</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if you query takes more than 1 second, you should consider &quot;warming&quot; your cached data via a cron job</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$lock_counter</span> &gt; <span class="re0">$max_time_to_wait</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$lock_failed</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// you really want this to be a fraction of a second so the user waits as little as possible</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// for the simplicity of example, I&#8217;m using the sleep function.</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/sleep"><span class="kw3">sleep</span></a><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data_lock</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// if the loop is completed, that either means the user waited for too long</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// or that the lock has been removed. &nbsp;try to get the cached data again; it should exist now</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$data</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// set a lock for 2 seconds</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span>, <span class="kw2">true</span>, <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = get_data_from_db_function<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span>, <span class="re0">$data</span>, <span class="re0">$sec_to_cache_for</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// don&#8217;t forget to remove the lock</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><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; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>More below the break &#8211;&gt;<span id="more-11"></span></p>
<p>Another good use of the semaphore locking is to set the expire time as part of the cached data and have an extended expire time set in memcache.  This allows you to have more control over what happens when the cached data becomes stale.  You can make it so that one user repopulates the cache while other users continue to get the existing cache until the first user has finished.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> get_my_data3<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$cache_id</span> = <span class="st0">&quot;mykey&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$data</span> = <span class="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="co1">// if there is cached data and the expire timestamp has already expired or is within the next 2 minutes</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="co1">// then we want the user to freshen up the cached data</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> <span class="re0">$data</span> &amp;amp;&amp;amp; <span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#91;</span><span class="st0">&#8216;cache_expires_timestamp&#8217;</span><span class="br0">&#93;</span> &#8211; <a href="http://www.php.net/time"><span class="kw3">time</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> &lt; <span class="nu0">120</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="co1">// if the semaphore lock has already been set, just return the data like you normally would.</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="re0">$memcache_obj</span>-&gt;<span class="me1">get</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_expire_lock&#8217;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// now we want to set the lock and have the user freshen the data.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_expire_lock&#8217;</span>, <span class="kw2">true</span>, <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// by unsetting the data it will cause the data gather logic below to execute.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span> !<span class="re0">$data</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="co1">// be sure to include all of the semaphore logic from example 2</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// set the _qry_lock for 2 seconds</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span>, <span class="kw2">true</span>, <span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$raw_data</span> = get_data_from_db_function<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span><span class="br0">&#91;</span><span class="st0">&#8216;cache_expires_timestamp&#8217;</span><span class="br0">&#93;</span> = <a href="http://www.php.net/time"><span class="kw3">time</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span> + <span class="re0">$sec_to_cache_for</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span><span class="br0">&#91;</span><span class="st0">&#8216;cached_data&#8217;</span><span class="br0">&#93;</span> = <span class="re0">$raw_data</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">set</span><span class="br0">&#40;</span><span class="re0">$cache_id</span>, <span class="re0">$data</span>, <span class="re0">$sec_to_cache_for</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// remove the _qry_lock</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_qry_lock&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// remove the _expires_lock</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$memcache_obj</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$cache_id</span> . <span class="st0">&#8216;_expires_lock&#8217;</span><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; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>When you mash these functions together, you end up with a system where only one user every freshens the cache and/or hits the database with a specific query at a time.  There are a lot of other things that suddenly become available once you start thinking of memcached beyond just saving your db from hits.  You have things like session handling, smarty template caching, flags for per-server processing (e.g., clearing local file cache), and even as a temporary database.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
