おぼえがき
おぼえがき
redisクラスタxマスタースレーブ構成でリアルタイムアクセス解析
redis cluster を マスタースレーブ構成でレプリケーション張って、php-redisを利用した、リアルタイムアクセス解析を作ってみた。

■構成
サーバー全部で6台
3台でクラスタ構成その下にスレーブをぶら下げる
■永続性
まだ、怖いから1日に1回データをフラッシュさせる
■データ構成
データ型 sorted set
キー access_monitor:id:${ユーザーID}
スコア unixtime
バリュー アクセスされたURL\x09リファラ\x09アクセスしてきたID\x09unixtime(タブ区切り)
スコアに、unixtimeを入れることにより、最新のアクセス順みたいな感じでデータが取れる
■インストール
redis 3.01
php-redisは、クラスタ構成 に対応していないから(2015/06/16現在)、ここから、もってきてクラスタ構成用の、RedisClusterが動くように無理やりやる
他にも、jemalloc-devel(3.6.0.1)も入れた
■クラスタを作る
sudo ./redis-trib.rb create --replicas 1 IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート
※redis-trib.rbは、redis本家のソースコードの中に入ってる。
初めは、sudo gem install redisしてあげる必要がある。
□クラスタが上手く作れないその1
こんなエラーが出たときは、
client.rb:113:in `call': ERR Slot 16011 is already busy (Redis::CommandError)
redis-cli -c
>select 0
>flushdb
>flushall
をやると、クラスタ作れる。
ただし、対象クラスタ全部やったほうが良い
□クラスタが作れないその2
クラスタを作るとき、nodes.confを作ると思うけど、再構築する際は、こいつの中身消したほうが良い
他にも、
17067: * Increased maximum number of open files to 10032 (it was originally set to 1024).
17067: * Node configuration loaded, I'm xxxxxe94c3dc311e558e3015ff1e51fe362c530d
17067: # Creating Server TCP listening socket *:16379: bind: Address already in use
とか、出たけど
全体の流れとして、
slect 0
flusdb
flushall
とかで、データ全部消して、
/etc/init.d/redis restart
:>nodes.conf (ファイルの中身消す)
で、
sudo ./redis-trib.rb create --replicas 1 IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート
こんな感じで作れるはず
■redis.conf
こんな感じにした(自信なし)
=====
daemonize no
pidfile /var/run/redis.pid
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 60
loglevel notice
logfile /var/log/redis/redis.log
databases 16
### SNAPSHOTTING
save ""
dir /var/lib/redis/
####REPLICATION
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync yes
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
### SECURITY
### LIMITS
maxclients 10000
maxmemory 1g
maxmemory-policy volatile-ttl
maxmemory-samples 5
###APPEND ONLY MODE
appendonly no
appendfsync no
no-appendfsync-on-rewrite no
###LUA SCRIPTING
lua-time-limit 5000
###REDIS CLUSTER
cluster-enabled yes
cluster-config-file /etc/redis/nodes.conf
cluster-node-timeout 5000
###SLOW LOG
slowlog-log-slower-than 10000
slowlog-max-len 128
####LATENCY MONITOR
latency-monitor-threshold 0
###EVENT NOTIFICATION
notify-keyspace-events ""
### ADVANCED CONFIG
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
#client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync no
=====
■php-redisを利用してみる
define('REDIS_CONNECT_PORT' , 'srv101:6379,srv102:6379,srv103:6379,srv104:6379,srv105:6379,srv106:6379');
#アクセス情報をredisクラスタに格納
$port=explode( ',' , REDIS_CONNECT_PORT );
$redis_obj = new RedisCluster('cluster', $port);
$redis_obj->zadd(${KEY}, $unixtime_now, $value);
#最新のアクセス順で取得(スコアも一緒に取得)
$redis_obj->zrangebyscore(${KEY}, $unixtime_from, $unixtime_to, array('withscores' => TRUE));
■tips
・php-redis入れたら、apacheリスタート
・データの一括投入(クラスタ構成だと、一部しかはいらないよ)
perl -pe "s/\n/\r\n/g" ファイル | redis-cli --pipe -c
上記コマンド、ファイルの中身
set key_1 val1
set key_2 val2
・フェイルオーバー
マスターのクラスタの一台が死んだ場合、対応しているスレーブが自動でマスターに昇格。
死んだマスターを復活させたら、今度は、スレーブとして起動するようになる(すごいね)
・クラスタの構成確認
cluster nodes
・メモリ使用量の確認
infoで、used_memoryを確認
・日本語入れてみる
redis-cli -c
127.0.0.1:6383> get title
"\xa4\xa4\xa4\xa4\xa4\xa4"
ってなかんじで、日本語が文字化けてしまう
redis-cli -c --raw
127.0.0.1:6383> get title
いいい
ちゃんと出る
・hash型にデータの一括投入
$filed_values = array(
'id' => ${id},
'title' => ${title}
);
$redis_obj->hmset(${KEY}, $filed_values);
■アクセス解析に使った他のredisの型
zincrby(${KEY} . YYYYMMDDHH, 1, "/ページのurl");
これで、○時のアクセスランキング作れちゃう
以上、redis cluster x m-s構成でphp-redisを利用した、リアルタイムアクセス解析を作ってみる。でした。おしまい

■構成
サーバー全部で6台
3台でクラスタ構成その下にスレーブをぶら下げる
■永続性
まだ、怖いから1日に1回データをフラッシュさせる
■データ構成
データ型 sorted set
キー access_monitor:id:${ユーザーID}
スコア unixtime
バリュー アクセスされたURL\x09リファラ\x09アクセスしてきたID\x09unixtime(タブ区切り)
スコアに、unixtimeを入れることにより、最新のアクセス順みたいな感じでデータが取れる
■インストール
redis 3.01
php-redisは、クラスタ構成 に対応していないから(2015/06/16現在)、ここから、もってきてクラスタ構成用の、RedisClusterが動くように無理やりやる
他にも、jemalloc-devel(3.6.0.1)も入れた
■クラスタを作る
sudo ./redis-trib.rb create --replicas 1 IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート
※redis-trib.rbは、redis本家のソースコードの中に入ってる。
初めは、sudo gem install redisしてあげる必要がある。
□クラスタが上手く作れないその1
こんなエラーが出たときは、
client.rb:113:in `call': ERR Slot 16011 is already busy (Redis::CommandError)
redis-cli -c
>select 0
>flushdb
>flushall
をやると、クラスタ作れる。
ただし、対象クラスタ全部やったほうが良い
□クラスタが作れないその2
クラスタを作るとき、nodes.confを作ると思うけど、再構築する際は、こいつの中身消したほうが良い
他にも、
17067: * Increased maximum number of open files to 10032 (it was originally set to 1024).
17067: * Node configuration loaded, I'm xxxxxe94c3dc311e558e3015ff1e51fe362c530d
17067: # Creating Server TCP listening socket *:16379: bind: Address already in use
とか、出たけど
全体の流れとして、
slect 0
flusdb
flushall
とかで、データ全部消して、
/etc/init.d/redis restart
:>nodes.conf (ファイルの中身消す)
で、
sudo ./redis-trib.rb create --replicas 1 IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート IPアドレス:ポート
こんな感じで作れるはず
■redis.conf
こんな感じにした(自信なし)
=====
daemonize no
pidfile /var/run/redis.pid
port 6379
tcp-backlog 511
timeout 300
tcp-keepalive 60
loglevel notice
logfile /var/log/redis/redis.log
databases 16
### SNAPSHOTTING
save ""
dir /var/lib/redis/
####REPLICATION
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync yes
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
### SECURITY
### LIMITS
maxclients 10000
maxmemory 1g
maxmemory-policy volatile-ttl
maxmemory-samples 5
###APPEND ONLY MODE
appendonly no
appendfsync no
no-appendfsync-on-rewrite no
###LUA SCRIPTING
lua-time-limit 5000
###REDIS CLUSTER
cluster-enabled yes
cluster-config-file /etc/redis/nodes.conf
cluster-node-timeout 5000
###SLOW LOG
slowlog-log-slower-than 10000
slowlog-max-len 128
####LATENCY MONITOR
latency-monitor-threshold 0
###EVENT NOTIFICATION
notify-keyspace-events ""
### ADVANCED CONFIG
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
#client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync no
=====
■php-redisを利用してみる
define('REDIS_CONNECT_PORT' , 'srv101:6379,srv102:6379,srv103:6379,srv104:6379,srv105:6379,srv106:6379');
#アクセス情報をredisクラスタに格納
$port=explode( ',' , REDIS_CONNECT_PORT );
$redis_obj = new RedisCluster('cluster', $port);
$redis_obj->zadd(${KEY}, $unixtime_now, $value);
#最新のアクセス順で取得(スコアも一緒に取得)
$redis_obj->zrangebyscore(${KEY}, $unixtime_from, $unixtime_to, array('withscores' => TRUE));
■tips
・php-redis入れたら、apacheリスタート
・データの一括投入(クラスタ構成だと、一部しかはいらないよ)
perl -pe "s/\n/\r\n/g" ファイル | redis-cli --pipe -c
上記コマンド、ファイルの中身
set key_1 val1
set key_2 val2
・フェイルオーバー
マスターのクラスタの一台が死んだ場合、対応しているスレーブが自動でマスターに昇格。
死んだマスターを復活させたら、今度は、スレーブとして起動するようになる(すごいね)
・クラスタの構成確認
cluster nodes
・メモリ使用量の確認
infoで、used_memoryを確認
・日本語入れてみる
redis-cli -c
127.0.0.1:6383> get title
"\xa4\xa4\xa4\xa4\xa4\xa4"
ってなかんじで、日本語が文字化けてしまう
redis-cli -c --raw
127.0.0.1:6383> get title
いいい
ちゃんと出る
・hash型にデータの一括投入
$filed_values = array(
'id' => ${id},
'title' => ${title}
);
$redis_obj->hmset(${KEY}, $filed_values);
■アクセス解析に使った他のredisの型
zincrby(${KEY} . YYYYMMDDHH, 1, "/ページのurl");
これで、○時のアクセスランキング作れちゃう
以上、redis cluster x m-s構成でphp-redisを利用した、リアルタイムアクセス解析を作ってみる。でした。おしまい
コメント ( 0 )
fuelphpでバッチ処理(oil refineを利用する)
oil refineをちゃんと見る
バッチ処理を動かすときは、oil refineを利用するんだが、
ちょいとハマったところもあるので、まとめておく
バッチ処理は、全て、fuel/app/tasks/ここのディレクトリ
配下に配下に置くようになっている。
これを実行するには、oil refine hoge
runメソッドが実行される
これを実行するには、oil refine hoge:sample
runメソッドではなく、オリジナルのメソッドが実行される
これを実行するには、oil refine hoge AAA BBB
これで、runメソッドに引数を渡すことができる
そんざいする、タスクをタスクを確認する
Available tasks:
php oil refine install
php oil refine migrate:help
php oil refine session
php oil refine session:create
php oil refine session:remove
php oil refine session:clear
php oil refine session:help
php oil refine fromdb
php oil refine fromdb:help
php oil refine fromdb:scaffold
php oil refine fromdb:model
php oil refine hoge <------ お!入っている
php oil refine hoge:sample <------ お!入っている
php oil refine robots
php oil refine robots:protect
modelとかパッケージがなぜか呼べなかったが、
\モデル名
\Email::forge()
ってやればちゃんと呼ぶことができた。
ちなみに、oilコマンドでタスクの生成ができる(これ、ヘルプ oil g help に載ってない気がする)
oil g task test
ってやったら、tasks/配下にtest.phpとrunメソッドのスケルトンが生成されて
oil g task test2 subtest
ってやったら、tasks/配下にtest2.phpとrunメソッドとsubtestのスケルトンが生成される
おしまい。

バッチ処理を動かすときは、oil refineを利用するんだが、
ちょいとハマったところもあるので、まとめておく
バッチ処理は、全て、fuel/app/tasks/ここのディレクトリ
配下に配下に置くようになっている。
2 namespace Fuel\Tasks;
3 class Hoge
4 {
5 public static function run()
6 {
7 echo "hoge";
8 }
9 }
これを実行するには、oil refine hoge
runメソッドが実行される
2 namespace Fuel\Tasks;
3 class Hoge
4 {
5 public static function run()
6 {
7 echo "hoge";
8 }
9 public static function sample()
10 {
11 echo "this is sample";
12 }
13 }
これを実行するには、oil refine hoge:sample
runメソッドではなく、オリジナルのメソッドが実行される
2 namespace Fuel\Tasks;
3 class Hoge
4 {
5 public static function run($a,$b)
6 {
7 echo $a;
8 echo $b;
9 echo "hoge";
10 }
11 public static function sample()
12 {
13 echo "this is sample";
14 }
15 }
これを実行するには、oil refine hoge AAA BBB
これで、runメソッドに引数を渡すことができる
そんざいする、タスクをタスクを確認する
Available tasks:
php oil refine install
php oil refine migrate:help
php oil refine session
php oil refine session:create
php oil refine session:remove
php oil refine session:clear
php oil refine session:help
php oil refine fromdb
php oil refine fromdb:help
php oil refine fromdb:scaffold
php oil refine fromdb:model
php oil refine hoge <------ お!入っている
php oil refine hoge:sample <------ お!入っている
php oil refine robots
php oil refine robots:protect
modelとかパッケージがなぜか呼べなかったが、
\モデル名
\Email::forge()
ってやればちゃんと呼ぶことができた。
ちなみに、oilコマンドでタスクの生成ができる(これ、ヘルプ oil g help に載ってない気がする)
oil g task test
ってやったら、tasks/配下にtest.phpとrunメソッドのスケルトンが生成されて
oil g task test2 subtest
ってやったら、tasks/配下にtest2.phpとrunメソッドとsubtestのスケルトンが生成される
おしまい。
コメント ( 0 )
fuelphp最小構成

最低限必要なファイルは何なんだろうか。
コアクラス追っかけてみた。
結果は・・・
./app/bootstrap.php
./app/classes/controller/welcome.php
./app/config/config.php
./app/config/crypt.php
./app/config/routes.php
./app/logs/
./app/views/welcome/index.php
./core/base.php
./core/bootstrap.php
./core/classes/arr.php
./core/classes/asset.php
./core/classes/asset/instance.php
./core/classes/autoloader.php
./core/classes/config/file.php
./core/classes/config/ini.php
./core/classes/config/interface.php
./core/classes/config/json.php
./core/classes/config/php.php
./core/classes/config/yml.php
./core/classes/config.php
./core/classes/controller.php
./core/classes/cookie.php
./core/classes/event.php
./core/classes/event/instance.php
./core/classes/finder.php
./core/classes/fuel.php
./core/classes/inflector.php
./core/classes/input.php
./core/classes/module.php
./core/classes/profiler.php
./core/classes/route.php
./core/classes/request.php
./core/classes/response.php
./core/classes/router.php
./core/classes/security.php
./core/classes/uri.php
./core/classes/view.php
./core/config/asset.php
./core/vendor/phpquickprofiler/console.php
./core/vendor/phpquickprofiler/display.php
./core/vendor/phpquickprofiler/phpquickprofiler.php
./packages/log/
これらのファイルを通って、呼ばれて、welcome画面が表示される
基本的には、index.phpで
$response = Request::forge()->execute()->response();
ってやって、
$response->send();
で表示されるだけ。
なんか、何でこのクラスが必要なんだところもあるが、
もうちょい追っかければ分かると思う
コメント ( 0 )
fuelphpとビルトインウェブサーバー

FuelPHPをビルドインウェブサーバー(PHP5.4以上)で動かそうとしたら、
この辺をみて、mod_rewrite的なものを実装する必要があったけど、
fuelphp1.6-develop眺めてると、
fuelphpをビルドインウェブサーバーで動かすことができそうな予感。
やってみる。
1.6-developのoilパッケージをダウンロードしてくる
今、自分の環境はFuelPHPの1.5を使っている。
XXX/fuel/packages/oil
このoilディレクトリの1.6のoilに入れ替える。
(オリジナルをmvして、githubのやつをDLしてoilに置き換えただけ)
じゃぁー実際動かしてみる
$ls
CHANGELOG.md CONTRIBUTING.md README.md TESTING.md build.xml
docs fuel/ oil public/
$oil help
Usage:
php oil [cell|console|generate|package|refine|help|server|test]
お!serverオプションがある
じゃぁ、起動してみる
$oil server
1
Listening on http://localhost:8000
Document root is public/
Press Ctrl-C to quit.
これで、ビルドインウェブサーバーが立ち上がった。
実際アクセスしてみる
wget http://localhost:8000/hello/hoge
うごいたうごいた。
oil/server.phpみると、まぁ、ただのラッパーだな
コメント ( 0 )
fuelphpでAssetsを利用して画面特有のcss,jsなどを呼び込む

テンプレートのベースである、templateファイルにpjaxのライブラリのパスを
書いてしまうと、使ってない画面までこのライブラリが呼ばれて無駄。
かと言って、個別テンプレートでそのライブラリを呼ぶのもいけてない。
assetsを利用してこの問題が解決できる。
■コントローラー
class Controller_Welcome extends Controller_Template
{
public function action_index()
{
Asset::css(array('bootstrap.min.css', 'bootstrap-responsive.min.css','bootswatch.css'), array(), 'add_css', false);
$this->template->content = View::forge('welcome/index');
}
※ここで、'add_css'っていうグループを登録しておく
■テンプレート
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<?php echo Asset::css('全てのテンプレートで呼ぶ.css'); ?>
<?php echo Asset::js('全てのテンプレートで呼ぶ.js'); ?>
<!-- 画面固有のCSS -->
<?php echo Asset::render('add_css');?>
これで、コントローラー側で、add_cssグループに、CSSファイルがアサイン
されているときだけ、画面固有のCSSが表示されるようになる。
ちなみに、
<?php echo Asset::render('add_css',true);?>
ってやると、外部ファイルを呼ぶのではなくて、外部ファイルがここに
展開される
なるほどね
コメント ( 0 )
« 前ページ |