The Many Challenges of Object Caching in WordPress

The Many Challenges of Object Caching in WordPress

It's no secret that WordPress can be slow and tough to scale. A key ingredient to scaling WordPress is setting up object caching. Object caching reduces the number of heavy database calls that WordPress needs to satisfy web requests. My talk will discuss the many details of how WordPress loads a third-party object cache, the API that developers can use, and design patterns for effective object caching. Finally, I will share my personal experiences in using object caching to help scale enterprise-level WordPress installations.

980df66b142b2a067b3f8b67b04352de?s=128

Zack Tollman

November 18, 2015
Tweet

Transcript

  1. The Many Challenges of Object Caching in WordPress Zack Tollman

    @tollmanz
  2. I know what you are thinking

  3. “There are two hard things in computer science: cache invalidation,

    and naming things”
  4. Cache Rules Everything Around Me

  5. WordPress can get slow

  6. Database queries

  7. API requests

  8. Long running routines

  9. Once is usually enough

  10. Object caching can improve performance

  11. http://www.fs.usda.gov/

  12. Making data easier to access on subsequent requests

  13. 1. Caching primer 2. Caching patterns

  14. wp-content/object-cache.php

  15. wp_cache_init();

  16. function wp_cache_init() { global $wp_object_cache; $wp_object_cache = new WP_Object_Cache(); }

  17. Persistence

  18. APC https://wordpress.org/plugins/apc/

  19. Memcached https://github.com/tollmanz/ wordpress-pecl-memcached-object-cache https://wordpress.org/plugins/memcached/

  20. “There are two hard things in computer science: cache invalidation,

    and naming things”
  21. Redis https://github.com/ericmann/Redis-Object-Cache/

  22. wp_cache_set($key, $value, $prefix, $ttl)

  23. wp_cache_get($key, $prefix)

  24. Grokking the WordPress Object Cache https://www.tollmanz.com/grokking-the-wp-object-cache/

  25. None
  26. Caching patterns

  27. On demand

  28. None
  29. $related = wp_cache_get( get_the_ID(), ‘related’); if ( false === $related

    ) { $related = generate_related( get_the_ID() ); wp_cache_set( get_the_ID(), $value, ‘related’, 86400 ); } foreach ( $related as $related_post ) { // Display the related post }
  30. Stampeding herd Easy to implement

  31. On event

  32. None
  33. add_action( ‘save_post’, function($post_id) { $value = generate_related( $post_id ); wp_cache_set(

    $post_id, $value, ‘related’ ); } );
  34. $related = wp_cache_get( get_the_ID(), ‘related’ ); if ( empty( $related

    ) ) { $related = get_default_related(); } foreach ( $related as $related_post ) { // Display the related post }
  35. No stampeding herd Must be able to listen to event

  36. On interval

  37. None
  38. add_action( ‘init’, function() { wp_schedule_event( time(), 'hourly', ‘update_tweets’ ); }

    ); function update_tweets() { $tweets = generate_tweets(); if ( empty( $tweets ) ) { $tweets = ‘none-available’; } wp_cache_set( ‘tweets’, $tweets ); }
  39. $tweets = wp_cache_get( ‘tweets’ ); if ( empty( $tweets )

    || ‘none- available’ === $tweets) { $tweets = get_default_tweets(); } foreach ( $tweets as $tweets ) { // Get your social on }
  40. No stampeding herd Doesn’t need an event Relies on WP

    Cron
  41. Stale while revalidate https://tools.ietf.org/html/rfc5861

  42. Use stale data while generating new data

  43. None
  44. $related = wp_cache_get( get_the_ID(), ‘related’ ); if ( false ===

    $value ) { queue_related( get_the_ID() ); $related = wp_cache_get( get_the_ID(), ‘related-stale’ ); } foreach ( $related as $related_post ) { // Display the related post }
  45. function queue_related( $post_id ) { $lock = wp_cache_get( $post_id, ‘related-

    lock’ ); if ( $lock ) { return; } else { wp_cache_set( $post_id, 1, ‘related-lock’ ); } $related = generate_related( $post_id ); wp_cache_set($post_id, $related, ‘related’, 300); wp_cache_set($post_id, $related, ‘related- stale’); wp_cache_delete( $post_id, ‘related-lock’ ); }
  46. TLC Transients https://github.com/markjaquith/WP-TLC-Transients

  47. $related = tlc_transient( ‘related-’ . $post_id ) ->updates_with( ‘queue_related’, [

    $post_id ] ) ->expires_in( 300 ) ->get(); foreach ( $related as $related_post ) { // Display the post } ———————————————— function queue_related( $post_id ) { return generate_related( $post_id ); }
  48. No stampeding herd Easy to implement with library

  49. Tips for the Cacher

  50. Avoid front-end caching

  51. Always set TTL

  52. Group level purges don’t exist https://www.tollmanz.com/invalidation-schemes/

  53. Invalidation first design

  54. #31245 sucks, a lot https://core.trac.wordpress.org/ticket/31245

  55. None
  56. https://speakerdeck.com/tollmanz @tollmanz