【php】【redis】phpredisのRedisArray
phpredisには、RedisArrayというものが実装されています。
複数のRedisインスタンスをコンストラクタに与えると、分散してデータを保持してくれるというスグレモノです。
で、下記のようなスクリプトで、ちょっと動作を確認
<?php
define('DATA_COUNT', 10000 );
define('KEY_PREFIX', 't1:');
$host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
);
$start_time = microtime( true );
$RedisArray = new RedisArray($host_array);
for( $i = 0; $i < DATA_COUNT ; $i++ ){
$ret = $RedisArray->set( KEY_PREFIX.$i, $i );
}
$end_time = microtime( true );
echo $i;
echo "\n";
echo ($end_time - $start_time);
echo "\n";
で、redis-cliで確認
redis 127.0.0.1:6379> dbsize
(integer) 4890
もう1つのインスタンスは
redis 127.0.0.1:6380> dbsize
(integer) 5110
実行時間は 0.5751秒。
ぼちぼち2つのインスタンスに分かれてデータを保存しているようです。
サーバーを増やしても古いホスト群を教えてやれば、うまく対応してくれるとのこと。
で、上記のスクリプトを動かした後に、下記のスクリプトを動かします。 サーバーを追加した後、増加するデータはどのように保存されるのか確認します。
<?php
define('START_DATA_COUNT', 10000 );
define('END_DATA_COUNT', 20000 );
define('KEY_PREFIX', 't1:');
$new_host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
'127.0.0.1:6381',
);
$previous_host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
);
$start_time = microtime( true );
$RedisArray = new RedisArray($new_host_array, array('previous' => $previous_host_array));
for( $i = START_DATA_COUNT; $i < END_DATA_COUNT ; $i++ ){
$ret = $RedisArray->set( KEY_PREFIX.$i, $i );
}
$end_time = microtime( true );
echo $i;
echo "\n";
echo ($end_time - $start_time);
echo "\n";
dbsizeは
redis 127.0.0.1:6379> dbsize
(integer) 8230
そして、
redis 127.0.0.1:6380> dbsize
(integer) 8446
追加したインスタンスは
redis 127.0.0.1:6381> dbsize
(integer) 3324
実行時間は、0.5686秒。2インスタンスの場合と、大差なしです。 データも新しいインスタンスにも分散しているようです。
じゃあ、もう1インスタンス増やしたらどうなるんでしょう?
<?php
define('START_DATA_COUNT', 20000 );
define('END_DATA_COUNT', 30000 );
define('KEY_PREFIX', 't1:');
$new_host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
'127.0.0.1:6381',
'127.0.0.1:6382',
);
$previous_host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
'127.0.0.1:6381',
);
$start_time = microtime( true );
$RedisArray = new RedisArray($new_host_array, array('previous' => $previous_host_array));
for( $i = START_DATA_COUNT; $i < END_DATA_COUNT ; $i++ ){
$ret = $RedisArray->set( KEY_PREFIX.$i, $i );
}
$end_time = microtime( true );
echo $i;
echo "\n";
echo ($end_time - $start_time);
echo "\n";
dbsizeは、
redis 127.0.0.1:6379> dbsize
(integer) 10730
dbsizeその2
redis 127.0.0.1:6380> dbsize
(integer) 10946
dbsizeその3
redis 127.0.0.1:6381> dbsize
(integer) 5824
新しいインスタンスは
redis 127.0.0.1:6382> dbsize
(integer) 2500
で、処理時間は、0.5833秒。大差なし。
このままでは古いサーバーにデータが溜まっていくので、データを再分配しないとダメかもです。 そこで使用するのが、_rehashというメソッドです。
<?
$new_host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
'127.0.0.1:6381',
'127.0.0.1:6382',
);
$previous_host_array = array(
'127.0.0.1:6379',
'127.0.0.1:6380',
'127.0.0.1:6381',
);
$start_time = microtime( true );
$RedisArray = new RedisArray($new_host_array, array('previous' => $previous_host_array));
$RedisArray->_rehash();
$end_time = microtime( true );
echo ($end_time - $start_time);
echo "\n";
処理時間は、6.652秒でした。 さすがに時間がかかります…
で、結果は
redis 127.0.0.1:6379> dbsize
(integer) 7446
redis 127.0.0.1:6380> dbsize
(integer) 7445
redis 127.0.0.1:6381> dbsize
(integer) 7555
redis 127.0.0.1:6382> dbsize
(integer) 7556
なるほど。データが再分配されています。
結果的に、増え続けるRedisデータについて、RedisArrayを利用してサーバー追加すれば対応可能な印象です。
ただ、どこかのタイミングで_rehashする必要があるかもしれません。
クラスタのような冗長性はReisArray単独では難しいかもですが、各インスタンスにSlaveサーバーを付けて、フェイルオーバー出来るようにすれば良いかもですね。
RedisArrayには他にもいくつか特徴があるので、RedisArrayをご確認下さい!