この記事では、サーバーの負荷を軽減するために、PHP が shmop 関数を使用して共有メモリを作成する方法を主に紹介します。これには、特定の参考値があります。ここで共有します。必要な友人はそれを参照してください。
前回の記事 このブログ【共有メモリの概念とメリット・デメリットを理解する】で共有メモリの概念について説明しました。単純に共有メモリを使用してみましょう (実際には、redis などの他のツールを使用することもできます)
PHP にはメモリ共有用の 2 セットのインターフェイスがあります。 1 つは shm で、実際には変数共有であり、オブジェクト変数を格納する前にシリアル化します。使用すると非常に便利ですが、効率を優先するメモリアクセス操作ではシリアル化されたストレージは意味がありません。もう 1 つは shmop で、Linux と Windows に共通ですが、shm よりも機能が弱く、Linux では shm* 系の関数を呼び出すことで直接実装されますが、Windows ではシステムをカプセル化することで実装されます。関数が同じ呼び出しを行いました。ここで最初に使用するのはシュモップです。
##共有メモリ セグメントを作成するには、関数 shmop を使用し、拡張機能を有効にする必要があります。[共有メモリを実装するために PHP の shmop 拡張機能を有効にする]を参照してください。shmop メイン関数
shmop_open (共有メモリ ブロックを作成または開く)、shmop_write (共有メモリ ブロックにデータを書き込む)、shmop_read (共有メモリ ブロックからデータを読み取る)、shmop_size (共有メモリ ブロックのサイズを取得)、shmop_close (共有メモリ ブロックを閉じる)、shmop_delete (共有メモリ ブロックを削除)<?php //创建一块共享内存 $shm_key = 0x4337b101; $shm_id = @shmop_open($shm_key, 'c', 0644, 1024); //读取并写入数据 $data = shmop_read($shm_id, 0, 1024); shmop_write($shm_id, json_encode($data), 0); $size = shmop_size($shm_id); //获取内存中实际数据占用大小 //关闭内存块,并不会删除共享内存,只是清除 PHP 的资源 shmop_close($shm_id);
shmop_open (メモリ セグメントの作成) #この関数で最初に現れるのはシステムIDパラメータです。これは、システム内の共有メモリセグメントを識別する番号です。 2 番目のパラメータはアクセス モードで、fopen 関数のアクセス モードとよく似ています。メモリ セグメントには 4 つの異なるモードでアクセスできます。
モード "a" では、読み取り専用メモリ セグメントにアクセスできます。
モード "w" では、読み取り専用メモリ セグメントにアクセスできます。読み取り専用メモリ セグメント 読み取りと書き込みのためのメモリ セグメント、読み取りと書き込み モード "c"、新しいメモリ セグメントを作成します。メモリ セグメントがすでに存在する場合は、読み取りと書き込みのためにそれを開こうとします
モード"n" の場合、新しいメモリを作成します。同じキーを持つセグメントがすでに存在する場合、作成は失敗します。これは、共有メモリを安全に使用するためです。
3 番目のパラメータはメモリ セグメントのアクセス許可です。ここには 8 進数値を指定する必要があります。
4 番目のパラメータは、メモリ セグメント サイズをバイト単位で指定します。使用される共有メモリセグメントは固定長であるため、保存時および読み取り時にデータの長さを計算する必要があり、そうでないと書き込みに失敗したり、NULL 値が読み取られる可能性があります。 。
この関数は、他の関数がこの共有メモリ セグメントを操作するために使用できる ID 番号を返すことに注意してください。この ID は、パラメータとして渡されるシステム ID とは異なり、共有メモリのアクセス ID です。この 2 つを混同しないように注意してください。失敗すると、shmop_open は FALSE を返します。メモリ ブロックを作成するときは、キー パラメータに変数ではなく定数を使用することをお勧めします。そうしないと、メモリ リークが発生する可能性があります。
shmop_write (メモリ セグメントへのデータの書き込み)この関数は fwrite 関数に似ており、次の 2 つのパラメータがあります: オープン ストリーム リソース (fopen によって返される)そして書き込みたいデータ。 shmop_write 関数もこのタスクを実行します。
最初のパラメータは shmop_open によって返される ID で、操作している共有メモリ ブロックを識別します。 2 番目のパラメータは保存したいデータで、最後の 3 番目のパラメータは書き込みを開始する位置です。デフォルトでは、書き込みを開始する場所を示すために常に 0 を使用します。この関数は失敗すると FALSE を返し、成功すると書き込まれたバイト数を返すことに注意してください。
shmop_read(メモリ セグメントからのデータの読み取り)共有メモリ セグメントからのデータの読み取りは非常に簡単です。必要なのは、開いているメモリ セグメントと shmop_read 関数だけです。この関数はいくつかのパラメータを受け取り、fread のように動作します。
ここのパラメータに注意してください。 shmop_read 関数は shmop_open によって返される ID を受け入れますが、これはすでにわかっていますが、他の 2 つのパラメーターも受け入れます。 2 番目の引数は、読み取りたいメモリ セグメント内の位置で、3 番目の引数は読み取りたいバイト数です。 2 番目のパラメータは常にデータの始まりを示す 0 にすることができますが、3 番目のパラメータは読み込むバイト数がわからないため、問題が発生する可能性があります。
これは fread 関数で行うことと非常に似ており、オープン ストリーム リソース (fopen によって返される) とストリームから読み込むバイト数という 2 つのパラメーターを受け取ります。ファイルを完全に読み取るには、filesize 関数 (ファイル内のバイト数を返す) を使用します。
shmop_size (メモリ セグメント データの実際のサイズを返します)たとえば、長さ 100 バイトのメモリ空間をオープンしましたが、実際の長さは保存されているデータが 90 のみの場合、shmop_size を使用して返される値は 90 です。
shmop_delete (メモリ セグメントの削除)该函数仅接受一个参数:我们希望删除的共享内存 ID,这不会实际删除该内存段。它将该内存段标记为删除,因为共享内存段在有其他进程正在使用它时无法被删除。shmop_delete 函数将该内存段标记为删除,阻止任何其他进程打开它。要删除它,我们需要关闭该内存段。在创建内存块时建议key参数用常量而不用变量,否则很有可能造成内存泄露。 shmop_close(关闭内存段) 我们在对内存段进行读取和写入,但完成操作后,我们必须从它解除,这非常类似于处理文件时的 fclose 函数。打开包含一个文件的流并在其中读取或写入数据后,我们必须关闭它,否则将发生锁定。 简单测试结果查看 我是在LNMP环境下操作的,如果你也和我一样,在执行完简单的操作之后,可以使用linux命令查看一下地址和占用大小 命令说明 key :共享内存的唯一的key值,共享内存通过该key来判断你读取的是哪一块内存。 项目实际应用小案例# ipcs -m
[root@bogon ~]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 0 gdm 600 393216 2 dest
0x00000000 32769 gdm 600 393216 2 dest
0x4337b101 884750 nobody 644 1024 0
shmid:当使用key来获取内存时,你获得的是这个id的值。它作为你操作内存块的标识。
owner:创建该共享内存块的用户
perms:该共享内存的读写权限,8禁止,可以是777,与文件的读写权限一致。
bytes:该内存块的大小
nattch:连接该内存块的进程数
status:当前状态,如:dest,即将删除等。<?php
/**
* 将领技能
*/
class Generalskill_model extends CI_Model {
private $_memory_key = 0x4337b001; //共享内存地址key
private $_memory_size = 1048576; //开辟共享内存大小 //最好根据实际数据长度大小定义。
public function __construct() {
parent::__construct();
}
public function get_skill_list() {
$data = [];
$shmid = @shmop_open($this->_memory_key, 'a', 0644, $this->_memory_size);
if ($shmid === FALSE) {
$shmid = @shmop_open($this->_memory_key, 'c', 0644, $this->_memory_size);
$data = $this->return_skill_list();
shmop_write($shmid, json_encode($data), 0);
@shmop_close($shmid);
return $data;
}
$data = json_decode(preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', trim(shmop_read($shmid, 0, $this->_memory_size))), true);
@shmop_close($shmid);
return $data;
}
public function return_skill_list() { //这里是一个超大的数组,其实就是把这个数组json化,然后存入共享内存段。 其实可以用redis等其他缓存...这里我就是为了不用redis等其他nosql才用的shmop
return array (
1 =>
array ('id' => '1','animation' => '13','skill_type' => '1','power_type' => '1','site' => '1','type' => '1','paramete' => '0','paramete2' => '0','paramete3' => '0','chance' => '0','ratio' => '1',
),
2 =>
array ('id' => '2','animation' => '3','skill_type' => '2','power_type' => '1','site' => '1','type' => '1','paramete' => '0','paramete2' => '0','paramete3' => '0','chance' => '0','ratio' => '2',
),..........................................
当然你要考虑的是,如果数据更新的话,那么内存段也要删除,并且更新数据......................通过shmop_delete可以删除 。这就需要你们自己根据项目应用来考虑了
还有就是我这里只是为了简单的读,并没有出现复杂的读写,否则可能会出现进程互斥等意想不到的冲突~如果复杂,那么就可以考虑信号量了~
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上がPHP は単純に shmop 関数を使用して共有メモリを作成し、サーバーの負荷を軽減します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。