<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: memcached PHP semaphore &amp; cache expiration handling</title>
	<atom:link href="http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/</link>
	<description>Wonder what’s on my mind? Now you know.</description>
	<lastBuildDate>Tue, 03 Aug 2010 17:32:39 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: Wide-Eyed Amazement / Modern Memcached Client</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-1222</link>
		<dc:creator>Wide-Eyed Amazement / Modern Memcached Client</dc:creator>
		<pubDate>Thu, 22 Oct 2009 07:56:59 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-1222</guid>
		<description>[...] endemic to concurrent systems. There are lots of solutions to this, most of which involve mutual exclusions. The problem with that, though, is that locking involves some small amount of overhead [...]</description>
		<content:encoded><![CDATA[<p>[...] endemic to concurrent systems. There are lots of solutions to this, most of which involve mutual exclusions. The problem with that, though, is that locking involves some small amount of overhead [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: <fb:name linked="false" useyou="false" uid="582491693">Mike Tougeron</fb:name></title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-1221</link>
		<dc:creator><fb:name linked="false" useyou="false" uid="582491693">Mike Tougeron</fb:name></dc:creator>
		<pubDate>Mon, 31 Aug 2009 17:12:25 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-1221</guid>
		<description>@Michael Greiling - Yes, that&#039;s the route I ended up going in production as well.  This entry has *long* been do for an update.  :)</description>
		<content:encoded><![CDATA[<p>@Michael Greiling &#8211; Yes, that&#8217;s the route I ended up going in production as well.  This entry has *long* been do for an update.  <img src='http://www.grepmymind.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: <fb:name linked="false" useyou="false" uid="54300824">Michael Greiling</fb:name></title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-1220</link>
		<dc:creator><fb:name linked="false" useyou="false" uid="54300824">Michael Greiling</fb:name></dc:creator>
		<pubDate>Thu, 02 Jul 2009 05:45:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-1220</guid>
		<description>I know this is an old post, but I just ran across it while looking for my own solution within memcache and I thought I&#039;d share my findings.  I found the following to work slightly better than mightye&#039;s solution in a previous comment:

[CODE]

function get_lock( $key_name )
{
while ( !$cache-&gt;add( $key_name, 1, false, 30 ) ) { usleep(100); }
}

function release_lock( $key_name )
{
$cache-&gt;delete( $key_name );
}

get_lock(&#039;lock_A&#039;);
// do stuff
release_lock(&#039;lock_A&#039;);

[/CODE]

The difference here is that unlike increment(), the key does not need to exist in the memcache prior to obtaining a lock, and add() is atomic as well.  (it will never return &#039;true&#039; to more than one process -- as opposed to set() for example)

One pitfall though which I didn&#039;t realize right away is that unlike a traditional blocking semaphore, the processes waiting to run will not necessarily complete in the order in which they started.  They don&#039;t line up in a queue to complete on a first-come-first-server basis, instead the next process to obtain the lock happens to be the first one to attempt an add() command after the lock is released which is completely random.</description>
		<content:encoded><![CDATA[<p>I know this is an old post, but I just ran across it while looking for my own solution within memcache and I thought I&#8217;d share my findings.  I found the following to work slightly better than mightye&#8217;s solution in a previous comment:</p>
<p>[CODE]</p>
<p>function get_lock( $key_name )<br />
{<br />
while ( !$cache-&gt;add( $key_name, 1, false, 30 ) ) { usleep(100); }<br />
}</p>
<p>function release_lock( $key_name )<br />
{<br />
$cache-&gt;delete( $key_name );<br />
}</p>
<p>get_lock(&#8216;lock_A&#8217;);<br />
// do stuff<br />
release_lock(&#8216;lock_A&#8217;);</p>
<p>[/CODE]</p>
<p>The difference here is that unlike increment(), the key does not need to exist in the memcache prior to obtaining a lock, and add() is atomic as well.  (it will never return &#8216;true&#8217; to more than one process &#8212; as opposed to set() for example)</p>
<p>One pitfall though which I didn&#8217;t realize right away is that unlike a traditional blocking semaphore, the processes waiting to run will not necessarily complete in the order in which they started.  They don&#8217;t line up in a queue to complete on a first-come-first-server basis, instead the next process to obtain the lock happens to be the first one to attempt an add() command after the lock is released which is completely random.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: The Woodwork &#187; Blog Archive &#187; Keeping memcache consistent</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-50</link>
		<dc:creator>The Woodwork &#187; Blog Archive &#187; Keeping memcache consistent</dc:creator>
		<pubDate>Tue, 03 Feb 2009 22:18:23 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-50</guid>
		<description>[...] problem with it was that it is buggy. It used a nonce/semaphore to look a lot like this example. Only written if someone who just learned object-oriented program wrote it and then the locking [...]</description>
		<content:encoded><![CDATA[<p>[...] problem with it was that it is buggy. It used a nonce/semaphore to look a lot like this example. Only written if someone who just learned object-oriented program wrote it and then the locking [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Michael Tougeron</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-24</link>
		<dc:creator>Michael Tougeron</dc:creator>
		<pubDate>Fri, 05 Dec 2008 20:31:55 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-24</guid>
		<description>That could work as well.  With the environment I work in (GameSpot.com) it is still possible for race conditions with your example.  However, for me anyway, it doesn&#039;t matter.  I&#039;d rather have 2 people (or even 1,000) people hit the database than all 100,000 hitting the db.  :)</description>
		<content:encoded><![CDATA[<p>That could work as well.  With the environment I work in (GameSpot.com) it is still possible for race conditions with your example.  However, for me anyway, it doesn&#8217;t matter.  I&#8217;d rather have 2 people (or even 1,000) people hit the database than all 100,000 hitting the db.  <img src='http://www.grepmymind.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: mightye</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-23</link>
		<dc:creator>mightye</dc:creator>
		<pubDate>Fri, 05 Dec 2008 19:19:50 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-23</guid>
		<description>Looks like these solutions are prone to a race condition Michael.

For example, in the second one, users A and B hit this function very nearly simultaneously.  A executes -&gt;get($cache_id), then B does.  A tests timestamp and determines it is stale, then B does the same thing.  A tests the lock and it doesn&#039;t exist.  B tests the lock and it doesn&#039;t exist for him either.  A sets the lock.  B sets the lock.  

Now both users will do this work at the same time, and if it&#039;s really critical that the work not be done more than once (IE, perhaps it can lead to a deadlock or some other system utilization or data integrity issue), you can have some problems here.

I might suggest using something like (for your first example):
while ($cache-&gt;increment($lock_name) &gt; 1) {
    $cache-&gt;decrement($lock_name);
    usleep(100);
}
Or adapting the same idea to your second example:
if ($cacheIsStale &amp;&amp; $cache-&gt;increment($lockName) == 1) {
    // refresh cache
}
$cache-&gt;decrement($lockName);

Increment and decrement should be atomic operations, so there should be no concern about both users calling -&gt;increment() nearly simultaneously only to discover that they both get back the same value.  Though this may not be guaranteed in a multi-memcached-server setup; at least in such a scenario the window size for the race condition is dramatically smaller - and it&#039;s as good as it gets given that memcached doesn&#039;t natively offer true semaphores.</description>
		<content:encoded><![CDATA[<p>Looks like these solutions are prone to a race condition Michael.</p>
<p>For example, in the second one, users A and B hit this function very nearly simultaneously.  A executes -&gt;get($cache_id), then B does.  A tests timestamp and determines it is stale, then B does the same thing.  A tests the lock and it doesn&#8217;t exist.  B tests the lock and it doesn&#8217;t exist for him either.  A sets the lock.  B sets the lock.  </p>
<p>Now both users will do this work at the same time, and if it&#8217;s really critical that the work not be done more than once (IE, perhaps it can lead to a deadlock or some other system utilization or data integrity issue), you can have some problems here.</p>
<p>I might suggest using something like (for your first example):<br />
while ($cache-&gt;increment($lock_name) &gt; 1) {<br />
    $cache-&gt;decrement($lock_name);<br />
    usleep(100);<br />
}<br />
Or adapting the same idea to your second example:<br />
if ($cacheIsStale &amp;&amp; $cache-&gt;increment($lockName) == 1) {<br />
    // refresh cache<br />
}<br />
$cache-&gt;decrement($lockName);</p>
<p>Increment and decrement should be atomic operations, so there should be no concern about both users calling -&gt;increment() nearly simultaneously only to discover that they both get back the same value.  Though this may not be guaranteed in a multi-memcached-server setup; at least in such a scenario the window size for the race condition is dramatically smaller &#8211; and it&#8217;s as good as it gets given that memcached doesn&#8217;t natively offer true semaphores.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: tyleradam</title>
		<link>http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/comment-page-1/#comment-6</link>
		<dc:creator>tyleradam</dc:creator>
		<pubDate>Wed, 19 Mar 2008 03:09:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.grepmymind.com/2008/01/11/memcached-php-semaphore-cache-expiration-handling/#comment-6</guid>
		<description>Good stuff!!</description>
		<content:encoded><![CDATA[<p>Good stuff!!</p>
]]></content:encoded>
	</item>
</channel>
</rss>

