99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

 PHP 共享內(nèi)存使用場景及注意點

發(fā)布時間:2016-11-16 16:23  回復(fù):0  查看:2331   最后回復(fù):2016-11-16 16:23  

本文和大家分享的是PHP開發(fā)單機共享內(nèi)存的使用場景和分析,希望對大家有幫助,一起來看看吧。

 

  使用場景

 

  監(jiān)控匯總

 

  目前正在用的一個場景,針對某一臺機器上的錯誤進行匯總并報警,我們把一分鐘之內(nèi)的相同報警合并成一條,用共享內(nèi)存來暫存,非常實用且高效。

 

  PHP SESSION

 

  如果你是單機的服務(wù),且又啟用了session,那么可以把session換成共享內(nèi)存的來存儲,會比文件要快上不少,這里還要強調(diào)是單機,這是最大的軟肋,但就功能上來講沒有memcache方便。

 

  什么是共享內(nèi)存

 

  共享內(nèi)存是一種在同一臺機器的不同進程(應(yīng)用程序)之間交換數(shù)據(jù)的方式。一個進程可創(chuàng)建一個可供其他進程訪問的內(nèi)存段,并賦予它相應(yīng)的權(quán)限。每個內(nèi)存段擁有一個惟一的ID,我們通常稱之為shmid,這個ID指向一個物理內(nèi)存區(qū)域,其他進程可通過此ID來操作這塊內(nèi)存包擴讀取、寫入以及刪除。

 

  共享內(nèi)存的使用是一種在進程之間交換數(shù)據(jù)的快速方法,主要因為在創(chuàng)建內(nèi)存段之后傳遞數(shù)據(jù),不會涉及內(nèi)核。這種方法常常稱為進程間通信 (IPC)。其他 IPC 方法包括管道、消息隊列、RPC 和套接字。

 

  PHP 中幾種常見的共享內(nèi)存使用方式

 

  APC 可以緩存 PHP 的 opcode 提高應(yīng)用的性能,可以在同個 PHP-FPM 進程池的進程間共享數(shù)據(jù),常用功能如下:

 

  apc_store,apc_fetch,apc_add,apc_deleteapc_inc apc_dec,apc_cas,apc_clear_cache,apc_sma_info

 

  Shmop Unix 系統(tǒng)共享內(nèi)存使用接口常用功能:

 

  shmop_open,shmop_close,shmop_read,shmop_write,shmop_delete

 

  ipcs -m  查看本機共享內(nèi)存的狀態(tài)和統(tǒng)計。

 

  ipcrm -m shmid 或 ipcrm -M shmkey 清除共享內(nèi)存中的數(shù)據(jù)。

 

  SystemV Shm常用功能:

 

  ftok, shm_attach, shm_detach, shm_put_var, shm_get_var, shm_remove_var。

 

  使用共享內(nèi)存需要考慮操作的原子性和鎖、并行和互斥。

 

  sem 信號量相關(guān)函數(shù):sem_get,sem_remove,sem_acquire,sem_release

 

  PHP 提供的 IPC 機制。

 

  --enable-shmop 共享內(nèi)存,只能按字節(jié)操作

 

  --enable-sysvsem 信號量

 

  --enable-sysvshm 共享內(nèi)存,和 shmop 的差別是提供的操作函數(shù)不同,支持 key、value操作

 

  --enable-sysvmsg 消息隊列

 

  本文主講

 

  如何使用  PHP shmop 創(chuàng)建和操作共享內(nèi)存段,使用它們存儲可供其他應(yīng)用程序使用的數(shù)據(jù)。

 

  1. 創(chuàng)建內(nèi)存段

 

  共享內(nèi)存函數(shù)類似于文件操作函數(shù),但無需處理一個流,您將處理一個共享內(nèi)存訪問 ID。第一個示例就是 shmop_open 函數(shù),它允許您打開一個現(xiàn)有的內(nèi)存段或創(chuàng)建一個新內(nèi)存段。此函數(shù)非常類似于經(jīng)典的 fopen 函數(shù),后者打開用于文件操作的流,返回一個資源供其他希望讀取或?qū)懭朐摯蜷_的流的函數(shù)使用。讓我們看看 shmop_open的用法:

 

  <?php $key = ftok(__FILE__, 'h'); $mode = 'c'; $permissions = 0644; $size = 1024; $shmid = shmop_open($key, $mode, $permissions, $size); ?>

 

  第一個參數(shù)($key):

 

  系統(tǒng)建立IPC通訊 (消息隊列、信號量和共享內(nèi)存) 時必須指定一個key值。通常情況下,該key值通過ftok函數(shù)得到, * *key是一個我們邏輯上表示共享內(nèi)存段的標識。不同進程只要選擇同一個Key值就可以共享同一段存儲段。

 

  第二個參數(shù)($mode):

 

  訪問模式,它類似于fopen的訪問模式,有以下幾種

 

  模式 “a”,它允許您訪問只讀內(nèi)存段

 

  模式 “w”,它允許您訪問可讀寫的內(nèi)存段

 

  模式 “c”,它創(chuàng)建一個新內(nèi)存段,或者如果該內(nèi)存段已存在,嘗試打開它進行讀寫

 

  模式 “n”,它創(chuàng)建一個新內(nèi)存段,如果該內(nèi)存段已存在,則會失敗,返回 false,并伴隨有warning: unable to attach or create shared memory segment

 

  第三個參數(shù)($permissions):

 

  內(nèi)存段的權(quán)限。您必須在這里提供一個八進制值,它類似于UNIX操作系統(tǒng)文件和目錄的操作權(quán)限。

 

  第四個參數(shù)($size):

 

  內(nèi)存段大小,以字節(jié)為單位。在寫入一個內(nèi)存段之前,您必須在它之上分配適當?shù)淖止?jié)數(shù)。

 

  返回結(jié)果:

 

  此函數(shù)返回一個 ID 編號,其他函數(shù)可使用該 ID 編號操作該共享內(nèi)存段。這個 ID 是共享內(nèi)存訪問 ID,與系統(tǒng) ID 不同,它以參數(shù)的形式傳遞。請注意不要混淆這兩者。如果失敗,shmop_open 將返回 FALSE。

 

  shmop_open成功后,使用ipcs -m, 可以查看到剛剛創(chuàng)建的內(nèi)存段,注意 申請的內(nèi)存段有嚴格的權(quán)限,比如用root用戶申請的,普通用戶就無權(quán)訪問

 

  [[test@test]~/temp\\]$ ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00924660 0 root 666 8 104 0x00000000 294915 root 666 787528456 1 dest 0x68410e9f 753668 test 644 1024 0

 

  2. 向內(nèi)存段寫入數(shù)據(jù)

 

  使用 shmop_write 函數(shù)向共享內(nèi)存塊寫入數(shù)據(jù)。此函數(shù)的使用很簡單,它僅接受 個參數(shù),如下所示。

 

  <?php

 

  //這里shmid可以延用上一段代碼返回的shmid

 

  $shmid = shmop_open(ftok(__FILE__,'h), 'c', 0644, 1024); shmop_write($shmid, "Hello World!", 0); ?>

 

  這個函數(shù)類似于 fwrite 函數(shù), 在這里有三個參數(shù)。

 

  第一個參數(shù)($shmid):是 shmop_open 返回的 ID,它識別您操作的共享內(nèi)存塊。

 

  第二個參數(shù)($data):是您希望存儲的數(shù)據(jù)。

 

  第三個參數(shù)($offset):是您希望開始寫入的位置。默認情況下,我們始終使用 來表示開始寫入的位置。

 

  返回結(jié)果:此函數(shù)在失敗時會返回 FALSE,在成功時會返回寫入的字節(jié)數(shù)。

 

  3. 從內(nèi)存段讀取數(shù)據(jù)

 

  從共享內(nèi)存段讀取數(shù)據(jù)很簡單。您只需要一個打開的內(nèi)存段和 shmop_read 函數(shù),它接受三個參數(shù),如下所示:

 

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

 

  第一個參數(shù)($shmid):是 shmop_open 返回的 ID,它識別您操作的共享內(nèi)存塊。

 

  第二個參數(shù)($start):是您希望從內(nèi)存段讀取的位置,這個參數(shù)可以始終為0, 表示數(shù)據(jù)的開頭

 

  第三個參數(shù)($count):是您希望讀取的字節(jié)數(shù)。一般情況下我們用shmop_size($shmid),以便完整的讀取它。

 

  4. 刪除內(nèi)存段

 

  shmop_delete 該函數(shù)只接收一個參數(shù),如下所示:

 

  <?php

 

  $shmid = shmop_open(ftok(\\__FILE_\\_,'h), 'c', 0644, 1024);

 

  shmop_delete($shmid);

 

  ?>

 

  其實這個函數(shù)不會實際刪除該內(nèi)存段。它將該內(nèi)存段標記為刪除狀態(tài),因為共享內(nèi)存段在有其他進程正在使用它時無法被刪除。shmop_delete 函數(shù)將該內(nèi)存段標記為刪除,阻止任何其他進程打開它。要刪除它,我們需要關(guān)閉該內(nèi)存段。

 

  5. 關(guān)閉內(nèi)存段

 

  打開一個共享內(nèi)存段會 “附加” 到它。附加該內(nèi)存段之后,我們可在其中進行讀取和寫入,但完成操作后,我們必須從它解除。

 

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

 

  共享內(nèi)存的原子操作 - 信號控制

 

  針對共享內(nèi)存的寫操作本身不是原子性的,那么當我們大量并發(fā)進行讀寫的時候,怎么保證原子性呢,這里要引入信號量進行控制。

 

  PHP 也提供了內(nèi)置擴展 sysvsem ,其實我們在看sysvsem 提供的一系列sem_*的方法的時候,就會想到,這和上面提到的shmop_*有什么區(qū)別呢,我們來看官房文檔中的這一個解釋:PHP already had a shared memory extension (sysvshm) written by Christian Cartus, 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 擴展提供的方法在存儲之前對用戶的數(shù)據(jù)進行serialize處理,這里就導(dǎo)致這個存儲的數(shù)據(jù)是無法與其它語言共享的,這一系列方法是php only的方法。

 

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

 

  <?php $key = ftok(_FILE_, 'h') $mode = "c";  $permissions = 0755;  $size = 1024; // 內(nèi)存段的大小,單位是字節(jié)$key = ftok(\\__FILE_\\_, 'h'); $semid = sem_get($key); # 請求信號控制權(quán)if (sem_acquire($semid)) { $shmid = shmop_open($key, 'c', 0644, 1024); # 讀取并寫入數(shù)據(jù) shmop_write($shmid, '13800138000', 0); # 關(guān)閉內(nèi)存塊 shmop_close($shmid); # 釋放信號 sem_release($semid); }

 

  共享內(nèi)存的操作是非??斓?,在本地想要模擬實現(xiàn)寫入沖突是非常困難的,但是本地想模擬實現(xiàn)寫入沖突實際上是非常難的(考慮到計算機的執(zhí)行速度)。在本地測試中,使用 for 循環(huán)操作時如果不使用shmop_close 關(guān)閉資源會出現(xiàn)無法打開共享內(nèi)存的錯誤警告。這應(yīng)該是因為正在共享內(nèi)存被上一次操作占用中還沒有釋放導(dǎo)致。

 

  共享內(nèi)存,memcache,文件的讀寫速度對比。

 

  以下是同時讀寫1k的數(shù)據(jù)讀寫100000次的時間對比:

 

   PHP&nbsp;共享內(nèi)存使用場景及注意點  

共享內(nèi)存的使用場景,想了很久,結(jié)合自己曾經(jīng)做過的項目,發(fā)現(xiàn)能用到共享內(nèi)存的地方比較少。

 

 

文章來源:公眾賬號

您還未登錄,請先登錄

熱門帖子

最新帖子

?