Skip to content

APCキャッシュ

APC

Alternative PHP Cache

Alternative PHP Cache (APC) は、PHP の実行コードをキャッシュする仕組みで、 フリーかつオープンに使用できます。
PHP の中間コードのキャッシュ・最適化を行うための、 フリーでオープンかつ堅牢なフレームワークを提供するということを目標としています。
 ( PHP: 導入 - Manual )

http://php.net/manual/ja/book.apc.php

apc_cache_info

APC のデータから、キャッシュされた情報を取得する
http://php.net/manual/ja/function.apc-cache-info.php

キャッシュについて

超絶参考サイト様:
https://qiita.com/dorarep/items/e29053138c1504f004f1

キャッシュ先

<APC Cache>

  • 通信が発生しないため専用のCacheサーバをたてるより高速。
  • 帯域を制限しないため巨大なデータにも対応させやすい。
  • キャッシュを消すタイミングをコントロールできないため、基本的にexpire_timeで処理することとなる。
  • 基本静的なデータ(マスタデータなど)のキャッシュに向いている。
  • Webサーバのメモリサイズに依存しており分散させることができないため、あまり乗せすぎるとメモリを使い切ってしまう。

<Memcached>

  • 全Webサーバで同一のデータを扱うことができるため、キャッシュの更新・削除までコントロールができる。
  • 負荷分散させられる。

<PHP Cache>

  • PHP内で静的変数などにキャッシュする。
  • Updateのタイミングで更新しないと誤ったデータが取得されてしまうため、キャッシュする箇所は共有しないと障害を生みやすい。
  • キャッシュは必ずFrameworkのここのレイヤーで行うなど、ルール付けをしたほうが良い。
    • 基本的にはDBアクセスを削減するのが目的なので、DBアクセスに近い深いレイヤーで行ったほうが資源を有効活用しやすい。
    • 処理自体が重たいようなときに浅いところでキャッシュすることもあるが、
      浅いと複数のキャッシュ同士の関係性が難しくコントロールしづらい。

キャッシュ単位

クエリキャッシュ

  • クエリに対して1対1で紐づける。
    • 大文字・小文字の違いやWHERE句の並びの違いも吸収せず、ノーロジックでクエリ自体をキーとすることが多い。
    • 同一の問い合わせは同一のクエリになるように注意する。
  • 基本ノーロジックで入れられるため、UPDATE時の更新・削除等のコントロールがしづらい。
    • マスターデータに向いている。
  • 全く違うクエリが頻繁に使用されるようなテーブルに関しては効きづらい。
    • mgetで複数取ってくるような場合、完全に同一になりづらいためキャッシュがほぼ効かない。
    • あえて範囲を広めに取ってPHP側で絞り込んだり、細かいクエリをループすることでキャッシュを使い回すなどの手段も考える。

全てキャッシュ

  • テーブルのデータを全てキャッシュする。
  • アイテムマスタなど過去のデータも含めまんべんなくreadが走るようなマスタデータに向いている。
  • 運用の長期化に合わせて無限に肥大していくため、データの総量に注意する。
    • Memcachedだと帯域を使いすぎてしまうおそれがあるため、apcのほうが良い。
    • 何個かに分割して入れるなどの回避手段もある。
  • イベントマスタなど基本過去のデータにアクセスが行かないようなものに関しては全てキャッシュするメリットは薄い。

ROWキャッシュ

  • PrimaryKeyなどに対して1対1でキャッシュする。
    • mgetはgetをループすることで行う。
    • cacheから取得⇒なかったものだけDBから取る⇒cacheに入れる、と若干ロジックが複雑になる。
  • PrimaryKeyでのアクセスが基本のデータに向いている。
    • ユーザデータなど
  • mgetでの無駄が発生しづらく、更新・削除クエリでのコントロールもしやすい。
  • 様々なクエリが投げられるようなケースには向かない。

その他

  • WHERE句をキーにしてキャッシュするケースが多い。(WHERE user_id = X AND event_id = YだったらkeyはTABLENAME_X_Yなど)

注意すること

  • DBとの同一性の担保を意識する。
    • エラーハンドリングをしっかり。
    • master-slave遅延して古いデータをキャッシュしちゃうのはあるある。
  • 手当たり次第入れるとあまり使用されないキャッシュも生まれてしまうため、使用頻度とクエリの重さと相談。
    • 例えば1時間に1回飛ぶクエリを5分間キャッシュしても意味がない。
  • 同一のキャッシュをできるだけ使い回せるような設計を意識する。
  • UPDATE/DELETE時にキャッシュも更新/削除を行う。
  • コード全体のありとあらゆるところでキャッシュされてしまうとコントロールしづらいため、プロダクトでのルールを設けてしっかり管理する。
    • 2重でキャッシュしちゃってるのもあるある
    • 長期化したプロダクトだとキャッシュが意図しない動きをしてたっていうのは割と障害の原因になりやすい
    • デバッグしてて関数が意図通りの挙動をしないと思ったらキャッシュしてましたーとか