PhpRedis
GitHub概要
スター10,157
ウォッチ451
フォーク2,150
作成日:2011年3月15日
言語:C
ライセンス:Other
トピックス
clusterkeydbphpredisredis-clustervalkey
スター履歴
データ取得日時: 2025/10/22 08:07
キャッシュライブラリ
PhpRedis
概要
PhpRedisは、PHP用のRedis拡張モジュールです。C言語で実装されたネイティブ拡張として、Redisサーバーとの高性能な通信を提供します。単一のRedisインスタンスから、RedisCluster、RedisSentinelを使った高可用性構成まで幅広くサポートし、キャッシュ、セッション管理、リアルタイムデータ処理に活用されます。
詳細
PhpRedisは、Redisの豊富な機能をPHPから効率的に利用するためのC拡張です。Pure PHPライブラリ(Predis等)と比較して大幅な性能向上を実現し、プロダクション環境での大規模運用に最適化されています。
主要な技術的特徴:
- ネイティブC実装: PHP Pure実装比で大幅な性能向上
- フル機能対応: Redis 7.x の最新機能まで包括的サポート
- クラスター対応: RedisClusterによる水平スケーリング
- 高可用性: RedisSentinelによる自動フェイルオーバー
- 配列サポート: RedisArrayによる自動シャーディング
- セッション統合: PHPセッションハンドラーとしての利用
技術アーキテクチャ:
- 接続管理: 永続化接続、接続プール、タイムアウト制御
- シリアライゼーション: PHP、igbinary、msgpack対応
- 圧縮: LZF、ZSTD、LZ4による帯域幅削減
- SSL/TLS: 暗号化通信のサポート
メリット・デメリット
メリット
- 最高性能: C拡張による最適化されたRedis通信
- 完全機能: Redis全機能への包括的アクセス
- 本格運用対応: クラスター、センチネル、配列機能
- セッション統合: PHPセッションストレージとしての利用
- 豊富な設定: 接続、シリアライゼーション、圧縮オプション
- 実績: 多くの大規模Webサービスでの実績
- アクティブ開発: 継続的なアップデートと最新Redis対応
デメリット
- インストール要件: C拡張のコンパイル・インストール必要
- 環境依存: サーバー環境でのモジュール有効化が必要
- Redis必須: Redisサーバーへの依存
- 学習コスト: Redis知識と設定ノウハウが必要
- デバッグ難易度: C拡張レベルの問題は調査困難
- バージョン管理: PHP・Redis・PhpRedisの3層バージョン管理
参考ページ
書き方の例
基本的なRedis接続と操作
<?php
// Redis接続
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 認証が必要な場合
// $redis->auth('your_password');
// 基本的なキー・バリュー操作
$redis->set('user:1000', 'John Doe');
$redis->expire('user:1000', 3600); // 1時間で期限切れ
$username = $redis->get('user:1000');
echo "ユーザー名: " . $username . "\n";
// 複数キーの一括操作
$redis->mset([
'product:1' => 'Laptop',
'product:2' => 'Mouse',
'product:3' => 'Keyboard'
]);
$products = $redis->mget(['product:1', 'product:2', 'product:3']);
print_r($products);
// リストデータ構造
$redis->lpush('notifications', 'New message from admin');
$redis->lpush('notifications', 'Your order has been shipped');
$notifications = $redis->lrange('notifications', 0, -1);
print_r($notifications);
?>
PHPセッションストレージとしての利用
<?php
// セッション設定(php.ini または実行時設定)
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379?auth=password&database=1');
// セッション開始
session_start();
// 通常のセッション操作
$_SESSION['user_id'] = 12345;
$_SESSION['username'] = 'john_doe';
$_SESSION['last_login'] = time();
// セッションデータの表示
echo "ユーザーID: " . $_SESSION['user_id'] . "\n";
echo "ユーザー名: " . $_SESSION['username'] . "\n";
// セッション破棄
// session_destroy();
?>
RedisClusterの利用
<?php
// RedisCluster接続
$cluster = new RedisCluster(null, [
'host1:7000',
'host2:7001',
'host3:7002'
], 1.5, 1.5, true, 'cluster_password');
// クラスター情報確認
$masters = $cluster->_masters();
echo "マスターノード数: " . count($masters) . "\n";
// データ分散保存
for ($i = 0; $i < 100; $i++) {
$cluster->set("key:$i", "value:$i");
}
// ハッシュタグによる同一ノード配置
$cluster->set('{user:1000}:profile', json_encode(['name' => 'John', 'age' => 30]));
$cluster->set('{user:1000}:settings', json_encode(['theme' => 'dark']));
// トランザクション(同一ノード内)
$cluster->multi();
$cluster->set('{transaction}:key1', 'value1');
$cluster->set('{transaction}:key2', 'value2');
$result = $cluster->exec();
print_r($result);
?>
RedisSentinelによる高可用性
<?php
// Sentinel接続
$sentinel = new RedisSentinel([
'host' => '127.0.0.1',
'port' => 26379,
'connectTimeout' => 2.5,
'auth' => 'sentinel_password'
]);
// マスター情報取得
$masters = $sentinel->masters();
foreach ($masters as $master) {
echo "マスター名: " . $master['name'] . "\n";
echo "IPアドレス: " . $master['ip'] . ":" . $master['port'] . "\n";
echo "状態: " . $master['flags'] . "\n";
}
// 現在のマスターアドレス取得
$masterAddr = $sentinel->getMasterAddrByName('mymaster');
if ($masterAddr) {
$redis = new Redis();
$redis->connect($masterAddr[0], $masterAddr[1]);
// マスターへの書き込み
$redis->set('counter', 1);
echo "マスターに書き込み完了\n";
}
// スレーブ情報取得
$slaves = $sentinel->slaves('mymaster');
echo "スレーブ数: " . count($slaves) . "\n";
?>
RedisArrayによる自動シャーディング
<?php
// HashRing設定(redis.ini)
/*
redis.arrays.names = "user_cache"
redis.arrays.hosts = "user_cache[]=host1:6379&user_cache[]=host2:6379&user_cache[]=host3:6379"
redis.arrays.functions = "user_cache=user_hash_function"
redis.arrays.index = "user_cache=1"
redis.arrays.auth = "user_cache=password"
*/
// カスタムハッシュ関数
function user_hash_function($key) {
// ユーザーIDに基づくハッシュ
if (preg_match('/user:(\d+)/', $key, $matches)) {
return $matches[1]; // ユーザーIDでシャーディング
}
return $key;
}
// RedisArray利用
$redisArray = new RedisArray(['host1:6379', 'host2:6379', 'host3:6379'], [
'function' => 'user_hash_function',
'consistent' => true, // 一貫性ハッシュ
'algorithm' => 'crc32'
]);
// データ分散保存
$redisArray->set('user:1000:profile', json_encode(['name' => 'Alice']));
$redisArray->set('user:2000:profile', json_encode(['name' => 'Bob']));
$redisArray->set('user:3000:profile', json_encode(['name' => 'Charlie']));
// どのノードに配置されたかを確認
$target = $redisArray->_target('user:1000:profile');
echo "user:1000のデータ配置先: " . $target . "\n";
// 同一ユーザーのデータを同じノードに配置
$host = $redisArray->_target('user:1000:profile');
$redisArray->multi($host)
->set('user:1000:settings', json_encode(['theme' => 'light']))
->sadd('user:1000:friends', '2000', '3000')
->exec();
?>
高度なデータ構造とパフォーマンス最適化
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// パイプライン処理による高速化
$pipe = $redis->multi(Redis::PIPELINE);
for ($i = 0; $i < 1000; $i++) {
$pipe->set("batch:$i", "value:$i");
$pipe->expire("batch:$i", 3600);
}
$results = $pipe->exec();
echo "パイプライン実行結果: " . count($results) . "件処理\n";
// Lua スクリプト実行
$luaScript = '
local key = KEYS[1]
local increment = ARGV[1]
local current = redis.call("GET", key)
if current == false then
current = 0
end
local new_value = current + increment
redis.call("SET", key, new_value)
return new_value
';
$result = $redis->eval($luaScript, ['counter:atomic', '5'], 1);
echo "アトミックカウンター結果: " . $result . "\n";
// ハッシュデータ構造
$redis->hset('user:profile:1000', 'name', 'John Doe');
$redis->hset('user:profile:1000', 'email', '[email protected]');
$redis->hset('user:profile:1000', 'age', 30);
$profile = $redis->hgetall('user:profile:1000');
print_r($profile);
// ソート済みセット(ランキング)
$redis->zadd('leaderboard', 1500, 'player1');
$redis->zadd('leaderboard', 2000, 'player2');
$redis->zadd('leaderboard', 1800, 'player3');
// 上位ランキング取得
$topPlayers = $redis->zrevrange('leaderboard', 0, 2, true);
foreach ($topPlayers as $player => $score) {
echo "プレイヤー: $player, スコア: $score\n";
}
?>
設定とモニタリング
<?php
$redis = new Redis();
// 接続設定
$redis->connect('127.0.0.1', 6379, 2.5); // 2.5秒タイムアウト
// または永続化接続
// $redis->pconnect('127.0.0.1', 6379, 2.5, 'persistent_id');
// オプション設定
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_JSON);
$redis->setOption(Redis::OPT_COMPRESSION, Redis::COMPRESSION_LZ4);
// サーバー情報取得
$info = $redis->info();
echo "Redis バージョン: " . $info['redis_version'] . "\n";
echo "使用メモリ: " . $info['used_memory_human'] . "\n";
echo "接続クライアント数: " . $info['connected_clients'] . "\n";
// 統計情報
$stats = $redis->info('stats');
echo "総接続数: " . $stats['total_connections_received'] . "\n";
echo "総コマンド数: " . $stats['total_commands_processed'] . "\n";
// スロー クエリ確認
$slowlog = $redis->slowlog('get', 10);
foreach ($slowlog as $entry) {
echo "スロークエリ: " . implode(' ', $entry[3]) . " (実行時間: " . $entry[2] . "μs)\n";
}
// 設定確認・変更
$maxMemory = $redis->config('get', 'maxmemory');
echo "最大メモリ設定: " . $maxMemory['maxmemory'] . "\n";
// 実行時設定変更
// $redis->config('set', 'maxmemory', '1gb');
?>