EDIT xdebugとnetbeansでこれをデバッグしようとしました。私がいくつかのブレークポイントを置くと、デバッグセッション中にエクスポートが機能するのは不思議です。しかし、ブレークポイントがなく、より現実的な環境であれば、輸出は機能しません。PHP Redisセッションが保存されない
コードの一部にスリープ状態を追加しようとしました。
Redisのコミットが完了する前にPHPが終了している可能性があります。多分、Redis接続は非同期的に行われていますが、私はPRedisをチェックして、デフォルトは同期接続です。
私は報告ツールを開発中です。
ここに基本的な問題があります。
レポートをセッションオブジェクトに格納しますが、セッションオブジェクト内のレポートにアクセスしようとすると、後で要求があったときにその要求が破棄されます。
これは、より詳細なバージョンです。
私はそう
$_SESSION['report_name_unixtimestamp'] = gzcompress(serialize($reportObject));
ユーザーは、いくつかの表形式でレポートを見て、彼らが望むならば、彼らはそれをエクスポートすることができますのようなセッションに「報告書」オブジェクトを格納します。レポートが変更される可能性があるので、セッションに保存するという考え方は、ユーザーがPDF、Excelなどにエクスポートすると、表示されているレポートと同じレポートが表示されます。
ユーザはエクスポートボタンをクリックし、PHP側ではセッションに入り、取得パラメータとして提供されたキーを使用してレポートを取得し(圧縮解除およびシリアル化解除)、エクスポートを作成してユーザに送信しますダウンロードのために。
これは、レディスキャッシングサーバーをセッション管理のためのツールとして導入しようとするまで、うまく機能しています。今、何が起こる
は以下の通りです:
我々はレポートを最初に実行したときには、それがキャッシュに保存されますと、輸出が正常に動作します。
同じセッションで同じユーザーアカウントを使用してレポートを再度実行します。 unixtimestampが変更されるため、$_SESSION
に2つのエントリが必要です。 ($_SESSION['report_name_oldertimetamp']
および$_SESSION['report_name_newertimestamp']
)。エクスポートボタンを再度クリックすると、ファイルが存在しないというエラーが表示されます(サーバーから送信されていないため)。
新しいバージョンのレポートについてredisサーバーをチェックすると、そこには存在しませんが、古いタイムスタンプはそのまま残ります。
これは、ファイルセッション管理では機能しましたが、Redisでは機能しませんでした。私たちは、純粋なPHPクライアントPredisと同様、PHP用のredisモジュールを試しました。
誰にもアイデアはありますか?ここで
は、いくつかの詳細は以下のとおりです。
- Redisのは、メモリが不足していません。これを何度も確認しました。
- セッションでレポートオブジェクトをシリアル化解除するには、レポートクラスを既にインクルードしておく必要があることは既にわかっています。
- レポートが実行されているリクエスト中にPHPセッションオブジェクトをチェックすると、新しいレポートが含まれますが、Redisには決して反映されません。
以下は、Predisで使用されているセーブハンドラです。 redis_session_initは、session_start()の直前に呼び出されて登録される関数です。私はどのようにredis_session_write関数が動作するかわからないので、多分誰かが私を助けることができます。
<?php
namespace RedisSession
{
$redisTargetPrefix = "PHPREDIS_SESSION:";
$unpackItems = array();
$redisServer = "tcp://cache.emcweb.com";
function redis_session_init($unpack = null, $server = null, $prefix = null)
{
global $unpackItems, $redisServer, $redisTargetPrefix;
if($unpack !== null)
{
$unpackItems = $unpack;
}
if($server !== null)
{
$redisServer = $server;
}
if($prefix !== null)
{
$redisTargetPrefix = $prefix;
}
session_set_save_handler('RedisSession\redis_session_open', 'RedisSession\redis_session_close', 'RedisSession\redis_session_read', 'RedisSession\redis_session_write', 'RedisSession\redis_session_destroy', 'RedisSession\redis_session_gc');
}
function redis_session_read($id)
{
global $redisServer, $redisTargetPrefix;
$redisConnection = new \Predis\Client($redisServer);
return base64_decode($redisConnection->get($redisTargetPrefix . $id));
}
function redis_session_write($id, $data)
{
global $unpackItems, $redisServer, $redisTargetPrefix;
$redisConnection = new \Predis\Client($redisServer);
$ttl = ini_get("session.gc_maxlifetime");
$redisConnection->pipeline(function ($r) use (&$id, &$data, &$redisTargetPrefix, &$ttl, &$unpackItems)
{
$r->setex($redisTargetPrefix . $id, $ttl, base64_encode($data));
foreach($unpackItems as $item)
{
$keyname = $redisTargetPrefix . $id . ":" . $item;
if(isset($_SESSION[ $item ]))
{
$r->setex($keyname, $ttl, $_SESSION[ $item ]);
}
else
{
$r->del($keyname);
}
}
});
}
function redis_session_destroy($id)
{
global $redisServer, $redisTargetPrefix;
$redisConnection = new \Predis\Client($redisServer);
$redisConnection->del($redisTargetPrefix . $id);
$unpacked = $redisConnection->keys($redisTargetPrefix . $id . ":*");
foreach($unpacked as $unp)
{
$redisConnection->del($unp);
}
}
// These functions are all noops for various reasons... opening has no practical meaning in
// terms of non-shared Redis connections, the same for closing. Garbage collection is handled by
// Redis anyway.
function redis_session_open($path, $name)
{
}
function redis_session_close()
{
}
function redis_session_gc($age)
{
}
}
セッション変数に別のキーを使用してください(診断用)。 md5( 'report_name_unixtimestamp')や 'timestamp-reportname'など? 背景:私は鍵が切り捨てられていると思われます。 –
@EugenRieck、この$ _SESSION [md5( 'report_name_1234')]のような意味ですか?たぶん、最初のレポートのエクスポートが機能する理由は説明されません。キーの長さは、異なるタイムスタンプと同じ名前なので、レポートでは同じです。私はそれを試してみます、ありがとう。 –
@EugenRieck、それは仕事をしなかった。私はあなたが示唆したようにmd5ハッシュを試みたが、どちらも動作していない。 –