PHPでは、バイナリ形式のログファイルにデータを書き込むことで、ストレージスペースを効果的に削減し、読み取りパフォーマンスを向上させることができます。 fwrite()と組み合わせたpack()関数は、これを達成するための重要なツールです。この記事では、例を使用して、これら2つの関数を使用して構造化されたデータをバイナリログファイルに書き込み、関連する技術の詳細を説明する方法を説明します。
従来のテキストログと比較して、バイナリログの利点は次のとおりです。
よりコンパクト:byteアラインメントを使用してデータを保存してディスクスペースを保存します。
より効率的:高い並行性シナリオに適した速い読み取り速度と解析速度。
より安全:ログ構造を手動で変更するのは簡単ではありません。
もちろん、不利な点は読みやすさが悪いため、内部またはパフォーマンスの最適化の一部としてのみ使用することをお勧めします。
Pack()は、PHP変数をバイナリ文字列にパッケージ化するために使用されます。その基本的な構文は次のとおりです。
string pack(string $format, mixed ...$values)
$フォーマットはフォーマット文字列であり、次のような各値をパッケージ化する方法を定義します。
L :署名されていない長い整数(4バイト、機械のエンディアンネス)
N :署名されていない長い整数(4バイト、ビッグエンディアンバイト順序)
A :nul fill文字列
F :単一の精度の浮動小数点数(4バイト)
例として、ユーザーアクセスログを記録しましょう。各レコードには次のフィールドが含まれています。
ユーザーID(4バイト符号なし整数)
タイムスタンプ(4バイト符号なし整数)
ページURLの長さ(2バイト符号なし整数)
PageURL(可変長文字列)
<?php
function write_log($user_id, $timestamp, $url) {
$fp = fopen("access.log", "ab"); // バイナリの付録でログファイルを開きます
if (!$fp) {
die("ログファイルを開くことができません");
}
$url = parse_url($url, PHP_URL_PATH); // パスパーツのみが記録されます,機密パラメーターを含むログを避けてください
$url_length = strlen($url);
if ($url_length > 65535) {
$url = substr($url, 0, 65535); // 最大のストレージのみができます2バイトの長さURL
$url_length = 65535;
}
// パッケージ固定長データ:ユーザーID + タイムスタンプ + URL長さ
$header = pack("L L n", $user_id, $timestamp, $url_length);
// ログファイルに書き込みます
fwrite($fp, $header);
fwrite($fp, $url);
fclose($fp);
}
// サンプルコール
write_log(123456, time(), "https://m66.net/user/profile?id=987");
?>
上記のコードは次のとおりです。
pack( "ll n"、...)を使用して、ユーザーID、タイムスタンプ、およびURLの長さをバイナリ形式にエンコードします。
FWRITE()を使用して、それぞれヘッダーとURLボディを書き込みます。
各レコードは明確でコンパクトな形式であり、その後のクイックリードまたは分析に使用できます。
執筆後、これらのバイナリログは、次の方法を使用して読み取り、デコードできます。
<?php
function read_logs($filename) {
$fp = fopen($filename, "rb");
while (!feof($fp)) {
$header = fread($fp, 10); // 4バイトユーザーID + 4バイトタイムスタンプ + 2バイトURL長さ
if (strlen($header) < 10) break;
$data = unpack("Luser_id/Ltimestamp/nurl_len", $header);
$url = fread($fp, $data['url_len']);
echo "ユーザーID: {$data['user_id']}, 時間: " . date('Y-m-d H:i:s', $data['timestamp']) . ", URL: $url\n";
}
fclose($fp);
}
// サンプルコール
read_logs("access.log");
?>
pack()とfwrite()を介して、構造化されたデータをバイナリログファイルに効率的に書き込むことができます。これは、多数の頻繁にアクセスされるログ情報を記録するのに適しています。バイナリログは直接表示するのは簡単ではありませんが、システムのパフォーマンスと保守性を向上させるために、バッチで読み取って分析できます。
実際のアプリケーションでは、この方法は、ユーザーの動作軌跡の記録、インターフェイスコールログ、パフォーマンス分析データなど、学習する価値のあるログ処理方法などの複数のシナリオに拡張することもできます。