Cache miss stampedes [patch]

BUSTARRET, Jean-francois jfbustarret at wat.tv
Thu Jul 26 12:25:19 UTC 2007


> > -----Message d'origine-----
> > De : dormando [mailto:dormando at rydia.net]
> > > You would not need tuning, and the rate of incoming
> > requests is not a
> > > problem IMHO.
> > > 
> > > - If the rate is very low, one can expect that there won't be any 
> > > stampede (unless the regeneration code is veeeeeeery slow,
> > but this a
> > > code tuning problem, and not a caching one)
> > > - If the rate is moderate, it works fine
> > > - If the rate is very high, I still prefer to 1% of requests 
> > > regenerating the key instead of 100% one minute later...
> > 
> > Or do you mean it simply returns a cache miss randomly? I 
> guess that'd 
> > work.
> 
> Yep ! 1% of cache requests will return a cache miss, 99% will 
> return a cache hit with the data.

Here is a patch against 1.2.2 (no comments, no doc yet), in case someone
wants to give it a try.

Usage : add -e duration to the commandline

The chance of returning a cache miss grow with time, starting at
it->exptime - duration (0%) and ending at it->exptime (100%).

diff -rup memcached-1.2.2/items.c memcached-1.2.2-randomexp/items.c
--- memcached-1.2.2/items.c     2007-05-03 00:58:51.000000000 +0200
+++ memcached-1.2.2-randomexp/items.c  2007-07-26 14:09:57.000000000
+0200
@@ -387,6 +387,13 @@ item *do_item_get_notedeleted(const char
         do_item_unlink(it);           // MTSAFE - cache_lock held
         it = 0;
     }
+    if (it != NULL && settings.random_exp_time > 0 && it->exptime != 0
&& it->exptime <= current_time + settings.random_exp_time) {
+        int threshold = (current_time - it->exptime +
settings.random_exp_time);
+        threshold = RAND_MAX / settings.random_exp_time /
settings.random_exp_time * threshold * threshold;
+        if (rand() <= threshold) {
+                it = 0;
+        }
+    }

     if (it != NULL) {
         it->refcount++;
diff -rup memcached-1.2.2/memcached.c
memcached-1.2.2-randomexp/memcached.c
--- memcached-1.2.2/memcached.c 2007-05-03 00:58:51.000000000 +0200
+++ memcached-1.2.2-randomexp/memcached.c    2007-07-26
14:08:29.000000000 +0200
@@ -185,6 +185,7 @@ static void settings_init(void) {
 #endif
     settings.prefix_delimiter = ':';
     settings.detail_enabled = 0;
+    settings.random_exp_time = 0;
 }

 /* returns true if a deleted item's delete-locked-time is over, and it
@@ -2475,7 +2476,7 @@ int main (int argc, char **argv) {
     setbuf(stderr, NULL);

     /* process arguments */
-    while ((c = getopt(argc, argv,
"bp:s:U:m:Mc:khirvdl:u:P:f:s:n:t:D:")) != -1) {
+    while ((c = getopt(argc, argv,
"bp:s:U:m:Mc:khirvdl:u:P:f:s:n:t:D:e:")) != -1) {
         switch (c) {
         case 'U':
             settings.udpport = atoi(optarg);
@@ -2559,6 +2560,10 @@ int main (int argc, char **argv) {
             settings.prefix_delimiter = optarg[0];
             settings.detail_enabled = 1;
             break;
+        case 'e':
+            settings.random_exp_time = atoi(optarg);
+            srand(time(0));
+            break;
         default:
             fprintf(stderr, "Illegal argument \"%c\"\n", c);
             return 1;
diff -rup memcached-1.2.2/memcached.h
memcached-1.2.2-randomexp/memcached.h
--- memcached-1.2.2/memcached.h 2007-05-03 00:58:51.000000000 +0200
+++ memcached-1.2.2-randomexp/memcached.h    2007-07-26
13:30:54.000000000 +0200
@@ -79,6 +79,7 @@ struct settings {
     int num_threads;        /* number of libevent threads to run */
     char prefix_delimiter;  /* character that marks a key prefix (for
stats) */
     int detail_enabled;     /* nonzero if we're collecting detailed
stats */
+    int random_exp_time;
 };

 extern struct stats stats;


More information about the memcached mailing list