|Pathologically Eclectic Rubbish Lister|
Re: PerlMonks Caching (race)by tye (Sage)
|on Apr 21, 2010 at 07:11 UTC||Need Help??|
Yeah, memcached would very likely provide a noticeable speed boost and reduce memory usage if its use were properly implemented here. It wouldn't eliminate the per-process node cache, just make it faster and smaller. And I probably wouldn't eliminate the version table...
I'm sad to see that memcached has still not provided a way to avoid the race condition that I pointed out several years ago (and that is quite simple to avoid). And you avoid it by having a version number (usually one that is sequenced when you route your updates through the database).
memcached provides ways to avoid other race conditions by supporting increment/decrement, append/prepend, and 'cas' operations (which I believe are all new since I looked at it last).
But the original race condition still exists. Imagine one web server gets bogged down and the following sequence of events happen between web server X and web server Y:
X: request arrives when Bob downvotes Alice's node, N
Alice can refresh and refresh and she still won't see her update. When Carl looks at N, he also gets shown the rude version. Carl is offended by Alice's extreme rudeness and finally downvotes her node, putting N5 into the DB and memcached (N5 includes Alice's update and both decrements to the reputation).
In response to Carl's downvote, he is shown N5 and realizes Alice's rudeness was just a typo.
Meanwhile, Alice has written a PMD node wondering how her update could be ignored like that. This makes her look foolish because her update is plainly visible now (even though it wasn't visible for a long time after she made it).
Why do the memcached developers hate Alice so much?
Yes, there are several other race conditions in this scenario. I've talked about them several times before and even described how I mitigate them. Note that the first block of steps for Y are just part of a single web request and so can happen very quickly so X need only be slightly bogged down to make this possible.
Some observers may have noticed that some of the steps described are not actually how PerlMonks currently works (in particular, "rep=rep-1" and the redirect). The deviations from current reality just make the race consequences different, not less of a problem. For example, Alice might see her update yet nobody else does but later she refreshes and her update is gone, only to reappear much later when somebody votes on her node.
This added race condition might not be enough to prevent memcached from being used at PerlMonks, but it certainly doesn't help motivate adoption of it. The real blocker will likely be the difficulty in getting major updates deployed (my node cache re-write still isn't deployed, darnit!).
Thanks for the recommendation!
Oh, the way to avoid the race is to allow a memcached 'set' operation to include a "version string". A 'set' operation using a version string lt the current version string (using Perl's concept of lt) just gets ignored as a stale update. If you want to use numeric versions for memcached objects, then just be sure to zero-pad them to an appropriate, fixed length.