PHP共有メモリの使用シナリオと注意点

 ダダロードチーフ 360クラウドコンピューティング 

画像

ヒロインの宣言:


分散、CAP理論、高可用性、結果整合性、強力な一貫性、因果的一貫性、さまざまな場所での複数のアクティビティ...クラウドとクラウドは多くのことを聞いています。今回のGGの開発により、単一マシンの共有メモリ使用シナリオがもたらされ、分析されます。 、食欲をリフレッシュ!そこに木があります!

PS:豊富な第一線の技術と多様な表現形式はすべて「HULK第一線の技術トーク」にあります、注意してください


使用するシーン   モニタリングの概要

現在使用されているシーンは、特定のマシンのエラーを要約して警告することです。同じアラームを1分以内に1つにマージし、共有メモリを使用して一時的に保存するため、非常に実用的で効率的です。


 PHPセッション

スタンドアロンサービスであり、セッションが有効になっている場合は、セッションをストレージ用の共有メモリに置き換えることができます。これにより、ファイルよりもはるかに高速になります。ここでは、スタンドアロンサーバーであることも強調されています。これはが最大の弱点ですが、機能しているだけで、memcacheほど便利ではありません。


共有メモリとは


共有メモリは、同じマシン上の異なるプロセス(アプリケーション)間でデータを交換する方法です。プロセスは、他のプロセスがアクセスできるメモリセグメントを作成し、それに対応するアクセス許可を付与できます。各メモリセグメントには一意のIDがあり、通常はshmidと呼ばれます。このIDは、読み取り、書き込み、削除など、他のプロセスがこのメモリを操作できる物理メモリ領域を指します。


共有メモリの使用は、主にメモリセグメントの作成後にカーネルがデータの転送に関与しないため、プロセス間でデータを交換するための高速な方法です。この方法は、プロセス間通信(IPC)と呼ばれることがよくあります。他のIPCメソッドには、パイプ、メッセージキュー、RPC、およびソケットが含まれます。


 PHPで共有メモリを使用するいくつかの一般的な方法

APCは、PHPオペコードをキャッシュしてアプリケーションのパフォーマンスを向上させ、同じPHP-FPMプロセスプール内のプロセス間でデータを共有できます。一般的な機能は次のとおりです。

apc_store、apc_fetch、apc_add、apc_delete、apc_inc apc_dec、apc_cas、apc_clear_cache、apc_sma_info


Shmop Unixシステムの共有メモリ使用インターフェースの一般的な機能:

shmop_open、shmop_close、shmop_read、shmop_write、shmop_delete


ipcs-mローカル共有メモリのステータスと統計を表示します。

ipcrm -mshmidまたはipcrm-M shmkeyは、共有メモリ内のデータをクリアします。


SystemV Shmの一般的な機能:

ftok、shm_attach、shm_detach、shm_put_var、shm_get_var、shm_remove_var。


共有メモリを使用するには、原子性とロック、並列処理、および操作の相互排除を考慮する必要があります。
semセマフォ関連関数:sem_get、sem_remove、sem_acquire、sem_release

PHPによって提供されるIPCメカニズム。
のみによってバイト操作可能メモリ共有--enable-SHMOP、--enable-SYSVSEM
セマフォ
--enable-SYSVSHM共有メモリ、SHMOPとの差が、異なる操作機能とサポートのキーと値の操作を提供することです
--enable- sysvmsgメッセージキュー


この記事について


PHP shmopを使用して共有メモリセグメントを作成および操作し、それらを使用して他のアプリケーションで使用できるデータを格納する方法。


 1.メモリセグメントを作成します

共有メモリ機能はファイル操作機能に似ていますが、ストリームを処理する必要はなく、共有メモリアクセスIDを処理します。最初の例はshmop_open関数です。これを使用すると、既存のメモリセグメントを開いたり、新しいメモリセグメントを作成したりできます。この関数は、ファイル操作用にストリームを開き、開いたストリームの読み取りまたは書き込みを希望する他の関数のリソースを返す、従来のfopen関数と非常によく似ています。shmop_openの使用法を見てみましょう。

<?php 

$ key = ftok(__ FILE __、 'h'); 
$ mode = 'c'; 
$ permits = 0644; 
$ size = 1024; 

$ shmid = shmop_open($ key、$ mode、$ permits、$ size); 

?>


最初のパラメーター($ key):

システムがIPC通信(メッセージキュー、セマフォ、共有メモリ)を確立するときは、キー値を指定する必要があります。通常、キー値はftok関数を介して取得されます。** keyは、共有メモリセグメントを論理的に表す識別子です。異なるプロセスは、同じキー値を選択する限り、同じストレージセグメントを共有できます。


2番目のパラメーター($ mode):

アクセスモードは、fopenのアクセスモードに似ています。
読み取り専用メモリセグメント
モード「w」にアクセスできるモード「a」には、読み取り/書き込みメモリセグメント
モードにアクセスできるモードがあります。新しいメモリセグメントを作成する「c」、またはメモリセグメントがすでに存在する場合は、読み取りおよび書き込み
モード「n」で開こうとすると、新しいメモリセグメントが作成されます。メモリセグメントがすでに存在する場合は、失敗します。 falseを返し、警告が表示されます:共有メモリセグメントを接続または作成できません


3番目のパラメーター($ permits):

メモリセグメントの権限。ここでは8進数の値を指定する必要があります。これは、UNIXオペレーティングシステムのファイルとディレクトリの操作権限に似ています。


4番目のパラメーター($ size):

バイト単位のメモリセグメントのサイズ。メモリセグメントに書き込む前に、適切なバイト数を割り当てる必要があります。


戻り結果:

この関数はID番号を返し、他の関数はID番号を使用して共有メモリセグメントを操作できます。このIDは、システムIDとは異なる共有メモリアクセスIDであり、パラメータとして渡されます。2つを混同しないように注意してください。失敗した場合、shmop_openはFALSEを返します。


shmop_openが成功したら、ipcs -mを使用して、新しく作成されたメモリセグメントを表示します。要求されたメモリセグメントには厳密な権限があることに注意してください。たとえば、rootユーザーに申請した場合、通常のユーザーにはアクセス権がありません。

 
  

[[test @ test]〜/ temp \] $ ipcs -m ------共有メモリセグメント-------- key shmid owner perms bytes nattch status 0x00924660 0 root 666 8104 0x00000000 294915 root 666 787528456 1 dest 0x68410e9f 753668 test 644 1024 0


 2.メモリセグメントにデータを書き込みます

shmop_write関数を使用して、共有メモリブロックにデータを書き込みます。この関数の使用法は非常に簡単で、以下に示すように3つのパラメーターのみを受け入れます。

 
  

<?php
//ここで、shmidは前のコードによって返されたshmidを引き続き使用できます
$ shmid = shmop_open(ftok(__ FILE __、 'h)、' c '、0644、1024); shmop_write($ shmid、 "Hello World!" 、0);?>


この関数はfwrite関数に似ています。ここには3つのパラメーターがあります。

最初のパラメーター($ shmid):shmop_openによって返されるIDであり、操作している共有メモリー・ブロックを識別します。

2番目のパラメーター($ data):保存するデータです。
3番目のパラメーター($ offset):書き込みを開始する場所です。デフォルトでは、書き込みを開始する場所を示すために常に0を使用します。

返回结果:此函数在失败时会返回 FALSE,在成功时会返回写入的字节数。


 3. 从内存段读取数据

从共享内存段读取数据很简单。您只需要一个打开的内存段和 shmop_read 函数,它接受三个参数,如下所示:

<?php
$shmid = shmop_open(ftok(\__FILE_\_,'h), 'c', 0644, 1024);
shmop_write($shmid, "Hello World\!", 0);
var_dump(shmop_read($shmid, 0, 11));
?>

第一个参数($shmid):是 shmop_open 返回的 ID,它识别您操作的共享内存块。
第二个参数($start):是您希望从内存段读取的位置,这个参数可以始终为0, 表示数据的开头
第三个参数($count):是您希望读取的字节数。一般情况下我们用shmop_size($shmid),以便完整的读取它。


 4. 删除内存段

shmop_delete 该函数只接收一个参数,如下所示:

<?php
$shmid = shmop_open(ftok(\__FILE_\_,'h), 'c', 0644, 1024);
shmop_delete($shmid);
?>

其实这个函数不会实际删除该内存段。它将该内存段标记为删除状态,因为共享内存段在有其他进程正在使用它时无法被删除。shmop_delete 函数将该内存段标记为删除,阻止任何其他进程打开它。要删除它,我们需要关闭该内存段。


 5. 关闭内存段

打开一个共享内存段会 “附加” 到它。附加该内存段之后,我们可在其中进行读取和写入,但完成操作后,我们必须从它解除。

 
  

<?php $shmid = shmop_open(ftok(\__FILE_\_,'h), 'c', 0644, 1024); shmop_write($shmid, "Hello World\!", 0); shmop_delete($shmid); shmop_close($shmid); ?>


 共享内存的原子操作 - 信号控制

针对共享内存的写操作本身不是原子性的,那么当我们大量并发进行读写的时候,怎么保证原子性呢,这里要引入信号量进行控制。


PHP 也提供了内置扩展 sysvsem ,其实我们在看sysvsem 提供的一系列sem_*的方法的时候,就会想到,这和上面提到的shmop_*有什么区别呢,我们来看官房文档中的这一个解释:PHP already had a shared memory extension (sysvshm) written by Christian Cartus <[email protected]>, unfortunately this extension was designed with PHP only in mind and offers high level features which are extremely bothersome for basic SHM we had in mind.
也就是说:sysvshm 扩展提供的方法在存储之前对用户的数据进行serialize处理,这里就导致这个存储的数据是无法与其它语言共享的,这一系列方法是php only的方法。


引入信号控制之后的示例:

<?php
$key = ftok(_FILE_, 'h')
$mode = "c";&nbsp;
$permissions = 0755;&nbsp;
$size = 1024; // 内存段的大小,单位是字节$key = ftok(\__FILE_\_, 'h');
$semid = sem_get($key);
# 请求信号控制权if (sem_acquire($semid)) {
$shmid = shmop_open($key, 'c', 0644, 1024);
# 读取并写入数据
shmop_write($shmid, '13800138000', 0);

# 关闭内存块
shmop_close($shmid);
# 释放信号
sem_release($semid);
}


共享内存的操作是非常快的,在本地想要模拟实现写入冲突是非常困难的,但是本地想模拟实现写入冲突实际上是非常难的(考虑到计算机的执行速度)。在本地测试中,使用 for 循环操作时如果不使用shmop_close 关闭资源会出现无法打开共享内存的错误警告。这应该是因为正在共享内存被上一次操作占用中还没有释放导致。


共享内存,memcache,文件的读写速度对比。

以下是同时读写1k的数据读写100000次的时间对比:

  读(s) 写(s)
memcache 7.8 8.11
文件 2.6 3.2
shm 0.1 0.07 


共享内存的使用场景,想了很久,结合自己曾经做过的项目,发现能用到共享内存的地方比较少。


おすすめ

転載: blog.51cto.com/15127564/2668209