WordPress.org

Make WordPress Core

Opened 5 years ago

Last modified 5 months ago

#29351 new enhancement

Add a function for stampedes transient caching

Reported by: hypertextranch Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.0
Component: Cache API Keywords:
Focuses: performance Cc:
PR Number:

Description

A common caching pattern that's used by WordPress and developers everywhere look something like this:

if ( false === ( $value = get_transient( $cache_key ) ) ) {
  // A
  // Bunch
  // Of
  // Code
  // $value = ...

  set_transient( $cache_key, $value, 300 );
}

The downside of this approach is when the cache is cold or when the cache expires there's a stampede effect as multiple requests try and refresh the cache at the same time. Instead if we had a function that allowed for soft expirations we could do something like the following:

$some_slow_func = function() {
  // A
  // Bunch
  // Of
  // Code
  // $value = ...

  return $value;
}

$value = get_set_soft_transient(
  $cache_key,
  $some_slow_func,
  300,
  'Some fake initial stale value'
);

This approach abstracts out the cache refresh logic into another function which can result in slightly cleaner code and can be used to prevent cache stampedes.

Some other optimizations / changes that we could do with this approach that's not yet implemented in the patch:

  • Run all cache refresh functions async via wp_cron so even the unlucky winner that gets to trigger the cache refresh will get stale data (fast).
  • Better locking so that only one request will refresh the cache. (Right now a couple requests could happen to refresh at the same time on a very busy site.)
  • Perhaps prevent caching of a false value or one that equates to the default passed in?
  • Use filters instead of PHP callbacks to make this more WordPress like.
  • Also build out get_set_soft_site_transient().

This is inspired by the stampedes cache @gibrown wrote for some of WordPress.com and the @mboynes talk at WordCamp Boston.

/cc @betzster

Attachments (1)

29351-initial-idea.patch (2.4 KB) - added by hypertextranch 5 years ago.
Initial idea patch

Download all attachments as: .zip

Change History (3)

@hypertextranch
5 years ago

Initial idea patch

#2 @jipmoors
5 years ago

I think the point is valid but with this patch you are polluting the transient space with meta data and not respecting existing data or the possibility that some code uses your function to set and other code uses get_transient to read the data.

Perhaps a separate meta transient would be a better option. Allowing for unmodified get_transient & set_transient functionality. This would increase cache / meta requests but I guess this functionality would only be used on large or slow data so would be worth it to provide the option to use it.

Note: See TracTickets for help on using tickets.