« Xtremely Quick Development SystemComplexity: the mismatch between needs, does, and wants »


Comment from: Dan McKinley [Visitor] · http://mcfunley.com

Cromulent Simpsons reference.

12/31/07 @ 07:28
Comment from: David Avraamides [Visitor] · http://davidavraamides.net

Why not use a variant of #2 where the address registry is memcache? Just have a key 'get_items_in_cart' whose value is a pickled tuple of the specific cached instances of the function:

(get_items_in_cart::13:10:30, get_items_in_cart::5:5:20, ...)

Then when you get a cache miss, you just need to append the new key to the key list as well as cache the actual data. A cache reset just iterates through the keylist and invalidates each key, and then truncates the keylist.

12/31/07 @ 08:43
Comment from: Simon Willison [Visitor] · http://simonwillison.net/

Option 6 looks pretty good to me - I don't understand your argument against using it.

12/31/07 @ 09:43
Comment from: fumanchu [Member] Email


Thanks for mentioning that. Storing indices in memcached can work in some situations, but I rejected it as a general solution because you don't have absolute control over when it might be LRU'd out of the cache (even with no timeout). Instead, you have to trust that you've thrown enough resources into Memcached to never approach that scenario. That's why my #2 opted for a more durable store for the address registry.

12/31/07 @ 10:03
Comment from: fumanchu [Member] Email


The last line is of course just a running joke that someone somewhere in the company isn't going to like whatever decision you make. My argument should have been more fully stated. #6 makes caching more performant at the cost of making database access less so. If you cache the version number itself you might as well not use it, so you need to hit the DB every time, but you're usually in the situation of adding caching because your database is already overworked. It also means more coordination between all layers of the stack, since you have to pass the version around; this is especially true if you've physically separated the app and DAL layers, as we have.

So, in some situations I might try it, like I might try any one of them depending on the details of the operations involved.

12/31/07 @ 10:17
Comment from: fumanchu [Member] Email
  1. Put a shim in front of each memcached server that allows you to set tags for each key, and then delete all seen keys which share a given tag.
12/31/07 @ 17:31
Comment from: Alex Rickabaugh [Visitor]

the way we handle something like this is to have a group key which contains a randomly generated prefix. A lookup becomes:

prefix = cache_get('cart_' + cart_id);
fullkey = prefix + '' + limit + '' + offset;
value = cache_get(fullkey);

of course, if the group key is invalid, all of the subkeys that depend on the group key lookup are implicitly invalid, since they are effectively lost. so invalidating the entire cached cart is as simple as:

cache_del('cart_' + cart_id);

the lost subkeys will eventually expire, but in the meantime, the next time we query the cart (and find that the group key is invalid), we'll generate a new prefix (something like md5(rand()) works well) and save it to the group key.

02/22/08 @ 10:32
Comment from: fumanchu [Member] Email

Alex, that sounds like a very nice solution indeed! The only thing I might change would be, instead of calling:

cache_del('cart' + cart_id)
....time passes
prefix = cache_get('cart' + cart_id)
if prefix is None:
cache_set('cart' + cart_id, newprefix())

I would probably just call cache_set with a new prefix right away. That would cut down on stampeding and out-of-sync prefixes if multiple consumers are using the same cache farm.

02/28/08 @ 16:28
Comment from: James Arthur [Visitor] · http://www.thruflo.com

Sometimes reading to the bottom of the comment thread really pays off.

Alex's solution: so simple, so clever. Nice!

07/15/09 @ 10:18

Leave a comment

Your email address will not be revealed on this site.

Your URL will be displayed.

Please enter the phrase "I am a real human." in the textbox above.
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)