Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Re: PerlMonks Caching (race)

by tye (Sage)
on Apr 21, 2010 at 07:11 UTC ( #835973=note: print w/replies, xml ) Need Help??

in reply to PerlMonks Caching

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
X: read version 1 of N from memcached, N1
X: decrement 'reputation' field in N1, producing N2
X: flush N2 changes to DB (update ... rep=rep-1 ...)
X: re-read N from DB, yielding N2 again
X: the slowness of this web server matters at this point

Y: request arrives when Alice updates her node, N (having noticed a typo that makes her node appear extremely rude)
Y: read version 1 of N from memcached, N1
Y: apply update to node text, producing N3
Y: flush N3 changes to DB (update ... doctext='...' ...)
Y: re-read N from DB, yeilding N4 (includes both the text update and the reputation decrease)
Y: flush N to memcached, storing N4

X: flush N to memcached, storing N2 (Oops!)

Y: redirect to prevent POST being re-applied
Y: get request to show N to Alice as response to her update
Y: read N from memcached, getting N2
Y: display N2 to Alice, who wonders where her update went!

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.

- tye        

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://835973]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2023-12-08 15:36 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (36 votes). Check out past polls.