Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

WordPress のキャッシュ機構

4.455 visualizaciones

Publicado el

* キャッシュの概要
* WordPressに備わっているキャッシュの仕組みの紹介
* WordPress Object Cache
* Transients API

Publicado en: Tecnología
  • Sé el primero en comentar

WordPress のキャッシュ機構

  1. 1. WordPressのキャッシュ機構
  2. 2. • キャッシュの概要 • WordPressに備わっているキャッシュの仕組みの紹介 • WordPress Object Cache
 https://codex.wordpress.org/Class_Reference/WP_Object_Cache • Transients API
 https://wpdocs.osdn.jp/Transients_API • ※ WordPress コアのコードを例示している箇所はすべ てバージョン 4.4.2 からの引用
  3. 3. キャッシュとは
  4. 4. cache = 隠し場所、隠す (単語のもともとの意味)
  5. 5. 一度使ったデータを取り出しやすいところに置いておき 次からより素早く使えるようにする仕組み
  6. 6. データを要求する側 応答する側
  7. 7. データを要求する側 応答する側キャッシュ
  8. 8. データを要求する側 応答する側キャッシュ
  9. 9. • キャッシュ機構はデータを要求する側と応答する側の間に 立ち、応答結果のコピーを保存 • 要求に応じて、該当するコピーがあればコピーを返す(キャッ シュヒット) • コピーが無ければ応答側にデータを要求してその応答結果 を返す(キャッシュミス) • 本来、キャッシュの存在は意識されないもの
 (キャッシュの有無にかかわらず、システムは同じように動作することが求められる。 キャッシュの仕組みを使う側からはその存在は意識されないが、実はそこにあり、こっ そりデータが保存されるイメージ。だから「隠し場所」)
  10. 10. Webサイトにおけるキャッシュ
  11. 11. ユーザー エージェント DBサーバCDN Web/アプリケー ションサーバ リバースプロキシ (キャッシュサーバ) その他 データストア等
  12. 12. ユーザー エージェント DBサーバCDN Web/アプリケー ションサーバ リバースプロキシ (キャッシュサーバ) その他 データストア等
  13. 13. キャッシュの効用
  14. 14. ユーザー エージェント DBサーバCDN Web/アプリケー ションサーバ リバースプロキシ (キャッシュサーバ) その他 データストア等
  15. 15. HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 キャッシュなし ※上記のイメージは、以下のページの「動的なサイトがリクエストを受け取って処理する仕組み」の画像の一部抜粋を元に作成 http://takahashifumiki.com/web/programing/2426/
  16. 16. HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 キャッシュなし HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 出力キャッシュ (ページキャッシュ) ※上記のイメージは、以下のページの「動的なサイトがリクエストを受け取って処理する仕組み」の画像の一部抜粋を元に作成 http://takahashifumiki.com/web/programing/2426/
  17. 17. HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 キャッシュなし HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 出力キャッシュ (ページキャッシュ) キャッシュヒットすれば この部分の処理が省略される ※上記のイメージは、以下のページの「動的なサイトがリクエストを受け取って処理する仕組み」の画像の一部抜粋を元に作成 http://takahashifumiki.com/web/programing/2426/
  18. 18. HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 キャッシュなし HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 出力キャッシュ (ページキャッシュ) HTTPリクエスト 解析 PHP MySQL PHP HTTPレスポンス 出力 データキャッシュ (MySQLの応答結果をキャッシュするケース) キャッシュヒットすれば この部分の処理が省略される ※上記のイメージは、以下のページの「動的なサイトがリクエストを受け取って処理する仕組み」の画像の一部抜粋を元に作成 http://takahashifumiki.com/web/programing/2426/
  19. 19. 多様な選択肢
  20. 20. • 何を保存するか • どこに保存するか • いつまで保存するか • どうやって更新するか • どうやって削除するか
  21. 21. • クライアントサイド • HTTPキャッシュ/プロキシキャッシュ • サーバーサイド • アプリケーション • 出力キャッシュ/データキャッシュ • ミドルウェア • リバースプロキシキャッシュ/バイトコードキャッシュ/DBキャッシュ • OS • ディスクキャッシュ
  22. 22. 画像出典:WordPressキャッシュ系プラグインの比較とサイトに適した選び方 http://tokkono.cute.coocan.jp/blog/slow/index.php/wordpress/comparison-and-selection-of-wordpress- cache-plugin/
  23. 23. キャッシュの難しさ
  24. 24. • どこがボトルネックなのか • キャッシュすべきでないものは? • 更新・削除・置き換えの方法は? • 使い方を誤ると・・・
  25. 25. ほんとうは怖いWP Super Cacheの話
 http://takahashifumiki.com/web/programing/2426/ ※WP Super Cache がよくないということではありません
  26. 26. WordPressに備わっている
 キャッシュの仕組み
  27. 27. ユーザー エージェント DBサーバCDN Web/アプリケー ションサーバ リバースプロキシ (キャッシュサーバ) その他 データストア等
  28. 28. • クライアントサイド • HTTPキャッシュ/プロキシキャッシュ • サーバーサイド • アプリケーション • 出力キャッシュ/データキャッシュ • ミドルウェア • リバースプロキシキャッシュ/バイトコードキャッシュ/DBキャッシュ • OS • ディスクキャッシュ
  29. 29. WordPress Object Cache
  30. 30. • 非永続キャッシュ • 同一プロセス内でのみ再利用可能 • ドロップインで拡張することで永続化可能
  31. 31. PHP実行プロセス DB プログラム Object Cache 投稿データを要求 キャッシュミス
 DBからデータを取得
  32. 32. PHP実行プロセス DB プログラム Object Cache 投稿データを要求 キャッシュミス
 DBからデータを取得
  33. 33. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得
  34. 34. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得
  35. 35. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得
  36. 36. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得 キャッシュデータ
  37. 37. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得 キャッシュデータ
  38. 38. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得 キャッシュデータ
  39. 39. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得 投稿データを要求 キャッシュデータ
  40. 40. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュミス
 DBからデータを取得 投稿データを要求 キャッシュデータ 投稿データを更新 キャッシュデータを削除
  41. 41. キャッシュされたデータの寿命
  42. 42. PHP実行プロセス DB プログラム 投稿データを要求 Object Cache キャッシュデータ PHP実行プロセス プロセス終了により 無くなる 投稿データを要求 キャッシュミス
 DBからデータを取得
  43. 43. 永続化
  44. 44. APCu などPHP実行プロセス DB 投稿データを要求 Object Cacheプログラム PHP実行プロセス 投稿データを要求 キャッシュミス
 DBからデータを取得 投稿データを要求 キャッシュデータ キャッシュデータ
  45. 45. • WP_Object_Cache クラスで実装 • インスタンス変数にデータを保持 • プログラムから使用するときは WP_Object_Cache に 直接アクセスせず wp_cache_* 関数を使う • 関数の一覧と基本的な使い方を Codex で確認してみ ましょう
  46. 46. 例: 投稿データ
  47. 47. get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 ); get_post( 1 );
  48. 48. get_post 関数より抜粋 function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) { if ( empty( $post ) && isset( $GLOBALS['post'] ) ) $post = $GLOBALS['post']; if ( $post instanceof WP_Post ) { $_post = $post; } elseif ( is_object( $post ) ) { if ( empty( $post->filter ) ) { $_post = sanitize_post( $post, 'raw' ); $_post = new WP_Post( $_post ); } elseif ( 'raw' == $post->filter ) { $_post = new WP_Post( $post ); } else { $_post = WP_Post::get_instance( $post->ID ); } } else { $_post = WP_Post::get_instance( $post ); }
  49. 49. get_post 関数より抜粋 function get_post( $post = null, $output = OBJECT, $filter = 'raw' ) { if ( empty( $post ) && isset( $GLOBALS['post'] ) ) $post = $GLOBALS['post']; if ( $post instanceof WP_Post ) { $_post = $post; } elseif ( is_object( $post ) ) { if ( empty( $post->filter ) ) { $_post = sanitize_post( $post, 'raw' ); $_post = new WP_Post( $_post ); } elseif ( 'raw' == $post->filter ) { $_post = new WP_Post( $post ); } else { $_post = WP_Post::get_instance( $post->ID ); } } else { $_post = WP_Post::get_instance( $post ); }
  50. 50. public static function get_instance( $post_id ) { global $wpdb; $post_id = (int) $post_id; if ( ! $post_id ) return false; $_post = wp_cache_get( $post_id, 'posts' ); if ( ! $_post ) { $_post = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $post_id ) ); if ( ! $_post ) return false; $_post = sanitize_post( $_post, 'raw' ); wp_cache_add( $_post->ID, $_post, 'posts' ); } elseif ( empty( $_post->filter ) ) { $_post = sanitize_post( $_post, 'raw' ); } return new WP_Post( $_post ); } WP_Post クラスより抜粋
  51. 51. public static function get_instance( $post_id ) { global $wpdb; $post_id = (int) $post_id; if ( ! $post_id ) return false; $_post = wp_cache_get( $post_id, 'posts' ); if ( ! $_post ) { $_post = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $post_id ) ); if ( ! $_post ) return false; $_post = sanitize_post( $_post, 'raw' ); wp_cache_add( $_post->ID, $_post, 'posts' ); } elseif ( empty( $_post->filter ) ) { $_post = sanitize_post( $_post, 'raw' ); } return new WP_Post( $_post ); } WP_Post クラスより抜粋
  52. 52. wp_insert_post 関数より整形して抜粋 if ( empty( $data['post_name'] ) && !in_array( $data[‘post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) { $data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_title'], $post_ID ), $post_ID, $data[‘post_status'], $post_type, $post_parent ); $wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where ); clean_post_cache( $post_ID ); }
  53. 53. if ( empty( $data['post_name'] ) && !in_array( $data[‘post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) { $data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_title'], $post_ID ), $post_ID, $data[‘post_status'], $post_type, $post_parent ); $wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where ); clean_post_cache( $post_ID ); } wp_insert_post 関数より整形して抜粋
  54. 54. wp_cache_delete( $post->ID, 'posts' ); wp_cache_delete( $post->ID, 'post_meta' ); clean_object_term_cache( $post->ID, $post->post_type ); wp_cache_delete( 'wp_get_archives', 'general' ); do_action( 'clean_post_cache', $post->ID, $post ); if ( 'page' == $post->post_type ) { wp_cache_delete( 'all_page_ids', 'posts' ); do_action( 'clean_page_cache', $post->ID ); } wp_cache_set( 'last_changed', microtime(), 'posts' ); clean_post_cache 関数より抜粋
  55. 55. • データベースの更新時にいったんキャッシュを破棄 • 投稿そのものの他に、タームとの関係や投稿メタデータ など付随する情報もキャッシュされていることが分かる
  56. 56. • ちなみに、get_posts / WP_Query は・・・ • 取得した投稿リストの各投稿オブジェクトがキャッシュ される • cache_results パラメータで投稿オブジェクトを キャッシュするかどうかを指定可能 • 投稿リストそのものはキャッシュされない
  57. 57. function get_books( $args = array() ) { $defaults = array( 'post_type' => 'book' ); $args = wp_parse_args( $args, $defaults ); $cache_key = md5( 'books_' . serialize( $args ) ); $books = wp_cache_get( $cache_key, 'books' ); if ( $books === false ) { $books = get_posts( $args ); wp_cache_set( $cache_key, $books, 'books', 60 * MINUTE_IN_SECONDS ); } return $books; } カスタム投稿のリストをキャッシュするユーザー定義関数のサンプル
  58. 58. function get_books( $args = array() ) { $defaults = array( 'post_type' => 'book' ); $args = wp_parse_args( $args, $defaults ); $cache_key = md5( 'books_' . serialize( $args ) ); $books = wp_cache_get( $cache_key, 'books' ); if ( $books === false ) { $books = get_posts( $args ); wp_cache_set( $cache_key, $books, 'books', 60 * MINUTE_IN_SECONDS ); } return $books; } カスタム投稿のリストをキャッシュするユーザー定義関数のサンプル
  59. 59. 例: サイトオプション
  60. 60. get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' ); get_option( 'hoge' );
  61. 61. • オートロード対象のオプションはコアの初期化処理で一括して ロードされ、オブジェクトキャッシュに保存される • wp-settings.php • wp_not_installed • is_blog_installed • wp_load_alloptions • オートロード対象ではないオプションも、一度�get_option で 取得するとキャッシュされる
  62. 62. • オプション関係のキャッシュ ( [キャッシュグループ].[キャッシュID] ) • options.alloptions
 �… オートロードされたオプションのリスト • options.notoptions
 �… 存在しないオプションのリスト • options.[オプション名]
 �… オートロード対象外の個別のオプション
  63. 63. ドロップインによる拡張
  64. 64. • memcached • Redis • APC/APCu • etc. • ※それぞれ拡張用のプラグインがあります
  65. 65. wp_start_object_cache 関数より抜粋 wp-settings.php でこの関数が呼ばれオブジェクトキャッシュが初期化される $first_init = false; if ( ! function_exists( 'wp_cache_init' ) ) { if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { require_once ( WP_CONTENT_DIR . '/object-cache.php' ); if ( function_exists( 'wp_cache_init' ) ) wp_using_ext_object_cache( true ); } $first_init = true; } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { wp_using_ext_object_cache( true ); } if ( ! wp_using_ext_object_cache() ) require_once ( ABSPATH . WPINC . '/cache.php' );
  66. 66. wp_start_object_cache 関数より抜粋 wp-settings.php でこの関数が呼ばれオブジェクトキャッシュが初期化される $first_init = false; if ( ! function_exists( 'wp_cache_init' ) ) { if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { require_once ( WP_CONTENT_DIR . '/object-cache.php' ); if ( function_exists( 'wp_cache_init' ) ) wp_using_ext_object_cache( true ); } $first_init = true; } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) { wp_using_ext_object_cache( true ); } if ( ! wp_using_ext_object_cache() ) require_once ( ABSPATH . WPINC . '/cache.php' );
  67. 67. • wp-content の下に object-cache.php という名前で ファイルを配置 • object-cache.php 内で wp_cache_* 関数を定義す る • wp_cache_* 関数の引数でキャッシュの有効期限を 指定可能 ( 有効期限が使用されるかどうかはドロップイ ンの実装による )
  68. 68. デモ
  69. 69. Transients API
  70. 70. transient = 一時の、はかない
  71. 71. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API
  72. 72. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API
  73. 73. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API
  74. 74. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API データを保存
  75. 75. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API データを保存
  76. 76. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API set_transientデータを保存
  77. 77. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API Options API set_transientデータを保存 add_option
  78. 78. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option
  79. 79. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option データを要求 データ 有効期限
  80. 80. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option データを要求 get_transient データ 有効期限
  81. 81. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option データを要求 get_transient get_option データ 有効期限
  82. 82. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option データを要求 get_transient get_option データ 有効期限
  83. 83. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option データを要求 get_transient get_option データ 有効期限
  84. 84. PHP実行プロセス DB プログラム 外部サイトから データを取得 Transients API 有効期限 Options API set_transient データ データを保存 add_option データを要求 get_transient get_option データ 有効期限
  85. 85. キャッシュされたデータが 削除されるタイミング
  86. 86. PHP実行プロセス DB プログラム Transients API Options API get_transient データ データを要求 get_option delete_option 有効期限 有効期限 (期限切れ) データ
  87. 87. • 「永続的かつ時限的なキャッシュ」 ( Codex より) • リクエスト( ≒ PHP実行プロセス ) をまたいでデータ の再利用が可能 • データに有効期限を設定可能 • データはデータベース ( wp_options テーブル ) に保 存 • Codex を見てみましょう
  88. 88. • set_transient • add_option でデータと有効期限を保存 • get_transient • 有効期限が過ぎていたら delete_option でデータを削除 • 有効期限がまだ来ていなければ、get_option でデータを 取得 • ※有効期限が過ぎていても、次の get_transient が呼ばれ るまでデータは残り続けるということ
  89. 89. 典型的なユースケース
  90. 90. • フラグメントキャッシュ • ページ断片の再利用。フッターやサイドバーの HTML をキャッシュし て複数のリクエストに対して使い回す • 重い処理、外部のWebサービス / サイトとの連携を伴う処理 • WordPress コア / プラグイン / テーマ の更新チェック • SNS の API 利用制限を回避するなど • フラッシュメッセージ • 「設定を更新しました」など、1回限りのメッセージをリクエストをまた いで表示
  91. 91. 例: コアの更新チェック
  92. 92. $url = $http_url = 'http://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $query, null, '&' ); if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) $url = set_url_scheme( $url, 'https' ); (中略) $response = wp_remote_post( $url, $options ); (中略) $updates = new stdClass(); $updates->updates = $offers; $updates->last_checked = time(); $updates->version_checked = $wp_version; if ( isset( $body['translations'] ) ) $updates->translations = $body['translations']; set_site_transient( 'update_core', $updates ); wp_version_check 関数より抜粋
  93. 93. $url = $http_url = 'http://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $query, null, '&' ); if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) $url = set_url_scheme( $url, 'https' ); (中略) $response = wp_remote_post( $url, $options ); (中略) $updates = new stdClass(); $updates->updates = $offers; $updates->last_checked = time(); $updates->version_checked = $wp_version; if ( isset( $body['translations'] ) ) $updates->translations = $body['translations']; set_site_transient( 'update_core', $updates ); wp_version_check 関数より抜粋
  94. 94. $current = get_site_transient( 'update_core' ); (中略) // Wait 60 seconds between multiple version check requests $timeout = 60; $time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked ); if ( ! $force_check && $time_not_changed ) { return; } wp_version_check 関数より抜粋
  95. 95. $current = get_site_transient( 'update_core' ); (中略) // Wait 60 seconds between multiple version check requests $timeout = 60; $time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked ); if ( ! $force_check && $time_not_changed ) { return; } wp_version_check 関数より抜粋
  96. 96. Object Cache との関係
  97. 97. • Object Cache がドロップインで拡張されている場合、 トランジェントデータの保存先として Object Cache が 使われる • トランジェントデータの読み書きは wp_cache_* 関 数に委譲 • プラグイン開発等で Transients API を使う際には、ト ランジェントデータがデータベース以外に保存されるケー スも考慮しておく
  98. 98. デモ
  99. 99. まとめ
  100. 100. • ひとくちにキャッシュといっても、その実現方法はいろい ろある • それぞれの特性を理解して、効果が見込まれる部分に 対して導入する • 「なんとなく・・・」「とりあえず・・・」で使わない
  101. 101. • WordPress に備わっているキャッシュの仕組みとして Object Cache と Transients API がある • Object Cache は単に PHP の変数でデータを管理。手 軽で高速だが、リクエストをまたいでデータを再利用す ることはできない�( ドロップインで拡張すれば可能にな る ) • Transients はサイトオプションの仕組みをうまく使うこ とで有効期限つきの永続キャッシュを実現。リクエストを またいでデータを再利用できる
  102. 102. おわり
  103. 103. Special Thanks to • 高橋文樹.com
 http://takahashifumiki.com • ゆっくりと…
 http://tokkono.cute.coocan.jp
  104. 104. ご清聴ありがとうございました WordBench新潟 2016.2.20 @katanyan

×