初めまして、adwaysの孟です。
今日紹介したいのは、自分がプライベートで研究したちょっと面白い裏技です。
mysql普段の使い方みんな知ってますので、パスします~
今日の話題:mysqlとキャッシュサーバの連動
cronかscriptで定期的にmysqlからpullしてキャッシュをウォーミングアップするパターンですね、(ほかもいろんなパターンあると思いますが。。。
アプリケーション側でトリガーするパターンだと、キャッシュへの更新タイミング一番早いですが、
アプリのロジックにキャッシュ更新ルールも一緒に書かないといけないです。
キャッシュの更新や削除など考える要素増えるので、プロジェクトの複雑度上がり、メンテナンスが面倒になります。
シンプルisベストですからね。
スクリプトからキャッシュサーバへのウォーミングアップするパターンもよく使われてるんです、
ウォーミングアップscriptの数が限られてるので、メンテしやすいがメリットです!
DBからデータ一括pullしてキャッシュへごにょごにょ更新するなんか便利ですね。
けど、欠点もいくつかあります。
① script動くタイミングが一定してますので、サーバの負荷が呼吸のように波が出てきます。
② mysqlからpullしないとデータ更新されないので、データ量多いDBからすると、キャッシュサーバへの更新遅延が発生しやすくなります。
③ scriptがcronで動くかwhile(1)で動くか、scriptの実行管理がしなければいけません。面倒~
メンテナンスもしやすい、効率もいい、管理も手間かからない案世の中ないの?
あります!
「mysqlのテーブルtriggerから直接キャッシュサーバへ更新すればいい」
mysqlのデータ更新された瞬間、キャッシュサーバへの更新も完了、これより早い方法がない。
キャッシュ更新ルール全部mysql中で管理できるので、メンテナンスしやすい、管理も便利ですね。
実際どこで使ったら便利か、例を用意しました。
※ user_{ユーザID}_{属性} の形式でkeyを組み合わせて、値を書きます
※ memc_set(key,val,second)でも使えます。second秒後無効になります。 例2:ユーザAとユーザB友達になりました。memcachedへ更新する。
select memc_set(concat("user_",NEW.id,"_",NEW.friend_id), 1);
※ user_{ユーザID}_{ユーザID} の形式で、キャッシュサーバにリレーションを作ります
select memc_del(concat("user_",NEW.id,"_hoge");
※ use_{ユーザID}_hogeというキーを削除します。
例4:ユーザの友達リストを表示しながら、このユーザの友達の友達数も一緒に取ります。
select *, (memc_get(concat("user_",friend_id,"_friendnum"))) as friendnum from user_friend
※ use_{ユーザID}_friendnumをselect中でfunctionとして取得します。
memcachedから事前に用意した友達数を読み取れるので、subqueryごとcountより当然速いですね!
こんな感じで使えます。
どうですか?
普段の3階層構造を一気に2階層まで減らしました。(DB->APP->CACHE => DB->CACHE)
最新状態のデータを取りたい場合、DBの代わりにmemcachedからでも安心して取れるようになったので、dbのselect requestが減り、ロックの発生率も当然減ります。
データがinsertや削除された同時に関連するmemcachedデータカウントアップやダウンができますので嬉しいです。(select countが重いですからね)
極端の性能を追求してる方、是非この方法を使ってみてください~
ただ、注意しなければならないこともあります。memcached壊れた時、リカバリー用のscriptで再度memcachedへのウォーミングアップする必要があります。まぁ、キャッシューサーバ使うことなら必須項目ですね。
最新状態のデータを取りたい場合、DBの代わりにmemcachedからでも安心して取れるようになったので、dbのselect requestが減り、ロックの発生率も当然減ります。
データがinsertや削除された同時に関連するmemcachedデータカウントアップやダウンができますので嬉しいです。(select countが重いですからね)
極端の性能を追求してる方、是非この方法を使ってみてください~
ただ、注意しなければならないこともあります。memcached壊れた時、リカバリー用のscriptで再度memcachedへのウォーミングアップする必要があります。まぁ、キャッシューサーバ使うことなら必須項目ですね。
memc_set,memc_get,memc_delのmysql functionのソースも用意しました。興味ある方是非開発環境で試してみてください。(memcachedサーバのIP直接ソースに書いてます、環境に合わせて調整してください)
推奨環境:centos 5/6(64bit), mysql 5.1以上、gcc, libmemcached, mysql-devel
ソースダウンロード:
※ build.sh (コンパイル用shell
※ memc_set.c
※ memc_get.c
※ memc_del.c
(※自分のプライベート研究なので、本番への導入ご検討してる方は自己責任になります、ご注意してください)。
ソースダウンロード:
※ build.sh (コンパイル用shell
※ memc_set.c
※ memc_get.c
※ memc_del.c
(※自分のプライベート研究なので、本番への導入ご検討してる方は自己責任になります、ご注意してください)。
次回の場合、nginxの裏技も紹介したいと思います~
以上!