インターネットで検索すると、2つの方法がありますが、どちらもあまり良くありません。1つは単純にプロセスIDのタイムスタンプを使用するか、プロセスIDの乱数を使用して近似的な一意のIDを生成する方法です。簡単ですが、私はそうではありません。これは「完璧」を追求する意欲があり、さらに、このプロセスは Apache2 以降も長期間続くため、生成された ID の衝突の可能性は依然として比較的高いです。2 番目のアイデアは、Mysql の自動インクリメント フィールドを使用することです。効率が低いことは言うまでもなく、私の設計にはデータベースがまったくありません。
増分 ID の取得は次のプロセスです。
1. グローバル ストレージから ID を読み取ります。
2. ID に 1 を追加します。
3. ID を複数のグローバル ストレージ
に保存します。 ID の一意性を確保するには、上記の 3 つのステップをプロセスまたはスレッド プログラム内の単一ステップのアトミック操作として使用する必要があります。
これは Java で解決するのが簡単です。これは、ほとんどの Java プログラムが Java プロセス内の変数を共有でき、スレッド操作の同期を制御するためにスレッド ロックを簡単に追加できるためです。 PHP では、グローバル ID をセッション内に、または最悪の場合はファイル内に保存することは問題ありませんが、プロセス間の同期が問題になります。
実際、プロセスのスケジューリングと管理はオペレーティング システムのカーネルが実装する必要がある機能です。今回紹介するセマフォ (セマフォとも呼ばれます) は、Unix/Linux 上のプロセスの同期を解決するテクノロジです。
信号機はもともと鉄道の管理機構として使用されていましたが、現在私たちが目にするほとんどの鉄道は並行複線ですが、一部の区間は山や地形の影響を受け、単線のみを確保する必要があります。これらの区間を同時に走行できる列車は 1 つだけです。初期の鉄道は信号機によって管理されており、列車が通過しないときは信号機が停止し、列車が通過するときに信号機が使用されるようになりました。列車が出発する場合、出口信号機が空になった場合にのみ、この区間に入ることができます。別の列車が入線すると、信号機は再び混雑します...鉄道の安全でスムーズな運行を確保します。
鉄道行政がセマフォを制御するのと同じように、Unix システムはセマフォの状態を管理および制御します。したがって、セマフォはプロセス間の同期を制御するだけではなく、カーネルによって管理されるとも言えます。スレッド間の同期も同様です。
セマフォはシステムプロセス間通信技術 (IPC) に属します。今日は、PHP の観点からセマフォの使用のみを紹介します。IPC の技術的な詳細については、Stevens の権威ある書籍「UNIX Network Programming Volume 2」を参照してください。プロセス間通信」。
最初に最終的なコードを見てください:
コードをコピーします コードは次のとおりです:
// ------------------------------------------- ----- -
// シリアル番号 ID をインクリメントします (1~1000000000)
//
// ID は共有メモリに保存され、セマフォを通じて同期されます
// -- - --------------------------------------
$ IPC_KEY = 0x1234; //System V IPC KEY
$SEQ_KEY = "SEQ"; //シリアル番号 ID を共有メモリに保存する KEY
//「1234」セマフォを使用して既存のキーを作成するKEY
$sem_id = sem_get($IPC_KEY);
//既存の共有メモリを KEY
$shm_id = shm_attach($IPC_KEY, 64) として作成または関連付けます。セマフォを占有します。これはロックに相当します。このコードを同時に実行できるのは 1 つのプロセスだけです。
sem_acquire($sem_id)
//共有メモリからシリアル番号 ID を取得します。
$id = @shm_get_var($shm_id, $SEQ_KEY);
if ($id == NULL || $id >= 1000000000)
{
$id = 1;
else
{
$id ;
}
//" " の後の ID を共有メモリに書き込みます
shm_put_var($shm_id, $SEQ_KEY, $id);セマフォ、ロック解除と同等
sem_release($sem_id);
//共有メモリの関連付けを閉じる
shm_detach($shm_id);
echo "シリアル ID: {$id} "; ?>
行 009 は 16 進整数 KEY を定義します。PHP では、KEY は指定されたリソース (メッセージ キュー、セマフォ、共有メモリ) に関連付けられる必要があります。
行 010 は、共有メモリに増分 ID を格納する KEY を定義します。これは、PHP による System V 共有メモリのアイドル使用です。変数は、ハッシュテーブルと同様の KEY-VALUE メソッドに格納する必要があります。上記のコードでは、共有メモリは ID のストレージ コンテナとして使用されています。これは、セッションやファイルなどの他のメカニズムで置き換えることもできます。この記事では、共有メモリについての知識を後で説明します。前に勧めた本を忘れないでください)。
013行目、1234をキーとしたセマフォをシステム内で取得し、システム内に存在しない場合は作成します。
行 015 は、行 13 と同様に、システム内に 1234 をキーとして共有メモリを取得します。2 番目のパラメータ 64 は、64 バイト サイズの共有メモリを作成することを意味します。 。
018~034行目、同期コード領域、プロセスまたはスレッドがsem_acquire関数を実行してセマフォを占有するとき、およびsem_release関数を呼び出してセマフォを解放するプロセス中に、他のプロセスまたはスレッドはsem_acquireの実行時にブロックします。行 021 では、共有メモリから ID を取得します。関数 shm_get_var には、エラー メッセージを隠すために「@」が付加されています (初めて実行するときは、共有メモリに KEY として「SEQ」を持つデータは存在しません)。警告メッセージがページに印刷されます)。
他の文は非常に簡単なので説明する必要はありません。
プログラムがコンパイルされた後、この PHP ページにアクセスすると、数値が段階的に出力されます。
システム コマンド ipcs を使用して、プログラムで作成されたセマフォと共有メモリを表示できます。
$ ipcs
------ 共有メモリ セグメント --------
key shmid owner perms bytes nattch status
0x00001234 1212443 www-data 666 64 0
------ セマフォ配列 --------
key semid owner perms nsems
0x00001234 163841 www - データ 666 3
------ メッセージ キュー --------
key msqid owner perms used-bytesmessages
最初の 2 つの段落はそれぞれ共有メモリとセマフォで、0x00001234 は作成されたキー。
コマンド ipcrm を使用して削除することもできます:
$ ipcrm -M 0x00001234 #共有メモリの削除
$ ipcrm -S 0x00001234 #セマフォの削除
----------- -- --------------------------------
PHP マニュアルには IPC に関する情報がほとんどありません。 Stevens が 10 年以上前に徹底的に説明した内容が、PHP でパッケージ化されていると想像してみてください。
本文では ID によるセマフォの使用についてのみ説明しています。自動インクリメント ID を生成する簡単な方法がある場合は、お知らせください。
友人の中には、セマフォの実行効率を知りたい人もいるかもしれません。これを古い流行語で要約します。「非常に高速です」。