検索
ホームページバックエンド開発PHPチュートリアルPHP+memcache实现消息队列案例分享_PHP

memcache

memche消息队列的原理就是在key上做文章,用以做一个连续的数字加上前缀记录序列化以后消息或者日志。然后通过定时程序将内容落地到文件或者数据库。

php实现消息队列的用处比如在做发送邮件时发送大量邮件很费时间的问题,那么可以采取队列。
方便实现队列的轻量级队列服务器是:
starling支持memcache协议的轻量级持久化服务器
https://github.com/starling/starling
Beanstalkd轻量、高效,支持持久化,每秒可处理3000左右的队列
http://kr.github.com/beanstalkd/
php中也可以使用memcache/memcached来实现消息队列。

复制代码 代码如下:
        /**
    * Memcache 消息队列类
    */ 
    class QMC { 
    const PREFIX = 'ASDFASDFFWQKE'; 
    /**
    * 初始化mc
    * @staticvar string $mc
    * @return Memcache
    */ 
    static private function mc_init() { 
    static $mc = null; 
    if (is_null($mc)) { 
    $mc = new Memcache; 
    $mc->connect('127.0.0.1', 11211); 
    } 
    return $mc; 
    } 
    /**
    * mc 计数器,增加计数并返回新的计数
    * @param string $key   计数器
    * @param int $offset   计数增量,可为负数.0为不改变计数
    * @param int $time     时间
    * @return int/false    失败是返回false,成功时返回更新计数器后的计数
    */ 
    static public function set_counter( $key, $offset, $time=0 ){ 
    $mc = self::mc_init(); 
    $val = $mc->get($key); 
    if( !is_numeric($val) || $val     $ret = $mc->set( $key, 0, $time ); 
    if( !$ret ) return false; 
    $val = 0; 
    } 
    $offset = intval( $offset ); 
    if( $offset > 0 ){ 
    return $mc->increment( $key, $offset ); 
    }elseif( $offset     return $mc->decrement( $key, -$offset ); 
    } 
    return $val; 
    } 
    /**
    * 写入队列
    * @param string $key
    * @param mixed $value
    * @return bool
    */ 
    static public function input( $key, $value ){ 
    $mc = self::mc_init(); 
    $w_key = self::PREFIX.$key.'W'; 
    $v_key = self::PREFIX.$key.self::set_counter($w_key, 1); 
    return $mc->set( $v_key, $value ); 
    } 
    /**
    * 读取队列里的数据
    * @param string $key
    * @param int $max  最多读取条数
    * @return array
    */ 
    static public function output( $key, $max=100 ){ 
    $out = array(); 
    $mc = self::mc_init(); 
    $r_key = self::PREFIX.$key.'R'; 
    $w_key = self::PREFIX.$key.'W'; 
    $r_p   = self::set_counter( $r_key, 0 );//读指针 
    $w_p   = self::set_counter( $w_key, 0 );//写指针 
    if( $r_p == 0 ) $r_p = 1; 
    while( $w_p >= $r_p ){ 
    if( --$max     $v_key = self::PREFIX.$key.$r_p; 
    $r_p = self::set_counter( $r_key, 1 ); 
    $out[] = $mc->get( $v_key ); 
    $mc->delete($v_key); 
    } 
    return $out; 
    } 
    } 
    /**
    使用方法:
    QMC::input($key, $value );//写入队列
    $list = QMC::output($key);//读取队列
    */ 
    ?> 

基于PHP共享内存实现的消息队列:

复制代码 代码如下:
/**
* 使用共享内存的PHP循环内存队列实现
* 支持多进程, 支持各种数据类型的存储
* 注: 完成入队或出队操作,尽快使用unset(), 以释放临界区
*
* @author wangbinandi@gmail.com
* @created 2009-12-23
*/ 
class ShmQueue 

private $maxQSize = 0; // 队列最大长度 
private $front = 0; // 队头指针 
private $rear = 0;  // 队尾指针 
private $blockSize = 256;  // 块的大小(byte) 
private $memSize = 25600;  // 最大共享内存(byte) 
private $shmId = 0; 
private $filePtr = './shmq.ptr'; 
private $semId = 0; 
public function __construct() 

$shmkey = ftok(__FILE__, 't'); 
$this->shmId = shmop_open($shmkey, "c", 0644, $this->memSize ); 
$this->maxQSize = $this->memSize / $this->blockSize; 
// 申?一个信号量 
$this->semId = sem_get($shmkey, 1); 
sem_acquire($this->semId); // 申请进入临界区 
$this->init(); 

private function init() 

if ( file_exists($this->filePtr) ){ 
$contents = file_get_contents($this->filePtr); 
$data = explode( '|', $contents ); 
if ( isset($data[0]) && isset($data[1])){ 
$this->front = (int)$data[0]; 
$this->rear  = (int)$data[1]; 



public function getLength() 

return (($this->rear - $this->front + $this->memSize) % ($this->memSize) )/$this->blockSize; 

public function enQueue( $value ) 

if ( $this->ptrInc($this->rear) == $this->front ){ // 队满 
return false; 

$data = $this->encode($value); 
shmop_write($this->shmId, $data, $this->rear ); 
$this->rear = $this->ptrInc($this->rear); 
return true; 

public function deQueue() 

if ( $this->front == $this->rear ){ // 队空 
return false; 

$value = shmop_read($this->shmId, $this->front, $this->blockSize-1); 
$this->front = $this->ptrInc($this->front); 
return $this->decode($value); 

private function ptrInc( $ptr ) 

return ($ptr + $this->blockSize) % ($this->memSize); 

private function encode( $value ) 

$data = serialize($value) . "__eof"; 
echo ''; 
echo strlen($data); 
echo ''; 
echo $this->blockSize -1; 
echo ''; 
if ( strlen($data) > $this->blockSize -1 ){ 
throw new Exception(strlen($data)." is overload block size!"); 

return $data; 

private function decode( $value ) 

$data = explode("__eof", $value); 
return unserialize($data[0]); 

public function __destruct() 

$data = $this->front . '|' . $this->rear; 
file_put_contents($this->filePtr, $data); 
sem_release($this->semId); // 出临界区, 释放信号量 


/*
// 进队操作
$shmq = new ShmQueue();
$data = 'test data';
$shmq->enQueue($data);
unset($shmq);
// 出队操作
$shmq = new ShmQueue();
$data = $shmq->deQueue();
unset($shmq);
*/ 
?>

对于一个很大的消息队列,频繁进行进行大数据库的序列化 和 反序列化,有太耗费。下面是我用PHP 实现的一个消息队列,只需要在尾部插入一个数据,就操作尾部,不用操作整个消息队列进行读取,与操作。但是,这个消息队列不是线程安全的,我只是尽量的避免了冲突的可能性。如果消息不是非常的密集,比如几秒钟才一个,还是可以考虑这样使用的。
如果你要实现线程安全的,一个建议是通过文件进行锁定,然后进行操作。下面是代码:
代码如下:

复制代码 代码如下:
    class Memcache_Queue  
    {  
    private $memcache;  
    private $name;  
    private $prefix;  
    function __construct($maxSize, $name, $memcache, $prefix = "__memcache_queue__")  
    {  
    if ($memcache == null) {  
    throw new Exception("memcache object is null, new the object first.");  
    }  
    $this->memcache = $memcache;  
    $this->name = $name;  
    $this->prefix = $prefix;  
    $this->maxSize = $maxSize;  
    $this->front = 0;  
    $this->real = 0;  
    $this->size = 0;  
    }  
    function __get($name)  
    {  
    return $this->get($name);  
    }  
    function __set($name, $value)  
    {  
    $this->add($name, $value);  
    return $this;  
    }  
    function isEmpty()  
    {  
    return $this->size == 0;  
    }  
    function isFull()  
    {  
    return $this->size == $this->maxSize;  
    }  
    function enQueue($data)  
    {  
    if ($this->isFull()) {  
    throw new Exception("Queue is Full");  
    }  
    $this->increment("size");  
    $this->set($this->real, $data);  
    $this->set("real", ($this->real + 1) % $this->maxSize);  
    return $this;  
    }  
    function deQueue()  
    {  
    if ($this->isEmpty()) {  
    throw new Exception("Queue is Empty");  
    }  
    $this->decrement("size");  
    $this->delete($this->front);  
    $this->set("front", ($this->front + 1) % $this->maxSize);  
    return $this;  
    }  
    function getTop()  
    {  
    return $this->get($this->front);  
    }  
    function getAll()  
    {  
    return $this->getPage();  
    }  
    function getPage($offset = 0, $limit = 0)  
    {  
    if ($this->isEmpty() || $this->size     return null;  
    }  
    $keys[] = $this->getKeyByPos(($this->front + $offset) % $this->maxSize);  
    $num = 1;  
    for ($pos = ($this->front + $offset + 1) % $this->maxSize; $pos != $this->real; $pos = ($pos + 1) % $this->maxSize)  
    {  
    $keys[] = $this->getKeyByPos($pos);  
    $num++;  
    if ($limit > 0 && $limit == $num) {  
    break;  
    }  
    }  
    return array_values($this->memcache->get($keys));  
    }  
    function makeEmpty()  
    {  
    $keys = $this->getAllKeys();  
    foreach ($keys as $value) {  
    $this->delete($value);  
    }  
    $this->delete("real");  
    $this->delete("front");  
    $this->delete("size");  
    $this->delete("maxSize");  
    }  
    private function getAllKeys()  
    {  
    if ($this->isEmpty())  
    {  
    return array();  
    }  
    $keys[] = $this->getKeyByPos($this->front);  
    for ($pos = ($this->front + 1) % $this->maxSize; $pos != $this->real; $pos = ($pos + 1) % $this->maxSize)  
    {  
    $keys[] = $this->getKeyByPos($pos);  
    }  
    return $keys;  
    }  
    private function add($pos, $data)  
    {  
    $this->memcache->add($this->getKeyByPos($pos), $data);  
    return $this;  
    }  
    private function increment($pos)  
    {  
    return $this->memcache->increment($this->getKeyByPos($pos));  
    }  
    private function decrement($pos)  
    {  
    $this->memcache->decrement($this->getKeyByPos($pos));  
    }  
    private function set($pos, $data)  
    {  
    $this->memcache->set($this->getKeyByPos($pos), $data);  
    return $this;  
    }  
    private function get($pos)  
    {  
    return $this->memcache->get($this->getKeyByPos($pos));  
    }  
    private function delete($pos)  
    {  
    return $this->memcache->delete($this->getKeyByPos($pos));  
    }  
    private function getKeyByPos($pos)  
    {  
    return $this->prefix . $this->name . $pos;  
    }  
    }  

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
誇大広告を超えて:今日のPHPの役割の評価誇大広告を超えて:今日のPHPの役割の評価Apr 12, 2025 am 12:17 AM

PHPは、特にWeb開発の分野で、最新のプログラミングで強力で広く使用されているツールのままです。 1)PHPは使いやすく、データベースとシームレスに統合されており、多くの開発者にとって最初の選択肢です。 2)動的コンテンツ生成とオブジェクト指向プログラミングをサポートし、Webサイトを迅速に作成および保守するのに適しています。 3)PHPのパフォーマンスは、データベースクエリをキャッシュおよび最適化することで改善でき、その広範なコミュニティと豊富なエコシステムにより、今日のテクノロジースタックでは依然として重要になります。

PHPの弱い参照は何ですか、そしていつ有用ですか?PHPの弱い参照は何ですか、そしていつ有用ですか?Apr 12, 2025 am 12:13 AM

PHPでは、弱い参照クラスを通じて弱い参照が実装され、ガベージコレクターがオブジェクトの回収を妨げません。弱い参照は、キャッシュシステムやイベントリスナーなどのシナリオに適しています。オブジェクトの生存を保証することはできず、ごみ収集が遅れる可能性があることに注意する必要があります。

PHPで__invoke Magicメソッドを説明してください。PHPで__invoke Magicメソッドを説明してください。Apr 12, 2025 am 12:07 AM

\ _ \ _ Invokeメソッドを使用すると、オブジェクトを関数のように呼び出すことができます。 1。オブジェクトを呼び出すことができるように\ _ \ _呼び出しメソッドを定義します。 2。$ obj(...)構文を使用すると、PHPは\ _ \ _ Invokeメソッドを実行します。 3。ロギングや計算機、コードの柔軟性の向上、読みやすさなどのシナリオに適しています。

同時性については、PHP 8.1の繊維を説明します。同時性については、PHP 8.1の繊維を説明します。Apr 12, 2025 am 12:05 AM

繊維はPhp8.1で導入され、同時処理機能が改善されました。 1)繊維は、コルーチンと同様の軽量の並行性モデルです。 2)開発者がタスクの実行フローを手動で制御できるようにし、I/O集約型タスクの処理に適しています。 3)繊維を使用すると、より効率的で応答性の高いコードを書き込むことができます。

PHPコミュニティ:リソース、サポート、開発PHPコミュニティ:リソース、サポート、開発Apr 12, 2025 am 12:04 AM

PHPコミュニティは、開発者の成長を支援するための豊富なリソースとサポートを提供します。 1)リソースには、公式のドキュメント、チュートリアル、ブログ、LaravelやSymfonyなどのオープンソースプロジェクトが含まれます。 2)StackOverFlow、Reddit、およびSlackチャネルを通じてサポートを取得できます。 3)開発動向は、RFCに従うことで学ぶことができます。 4)コミュニティへの統合は、積極的な参加、コード共有への貢献、および学習共有への貢献を通じて達成できます。

PHP対Python:違いを理解しますPHP対Python:違いを理解しますApr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

PHP:それは死にかけていますか、それとも単に適応していますか?PHP:それは死にかけていますか、それとも単に適応していますか?Apr 11, 2025 am 12:13 AM

PHPは死にかけていませんが、常に適応して進化しています。 1)PHPは、1994年以来、新しいテクノロジーの傾向に適応するために複数のバージョンの反復を受けています。 2)現在、電子商取引、コンテンツ管理システム、その他の分野で広く使用されています。 3)PHP8は、パフォーマンスと近代化を改善するために、JITコンパイラおよびその他の機能を導入します。 4)Opcacheを使用してPSR-12標準に従って、パフォーマンスとコードの品質を最適化します。

PHPの未来:適応と革新PHPの未来:適応と革新Apr 11, 2025 am 12:01 AM

PHPの将来は、新しいテクノロジーの傾向に適応し、革新的な機能を導入することで達成されます。1)クラウドコンピューティング、コンテナ化、マイクロサービスアーキテクチャに適応し、DockerとKubernetesをサポートします。 2)パフォーマンスとデータ処理の効率を改善するために、JITコンパイラと列挙タイプを導入します。 3)パフォーマンスを継続的に最適化し、ベストプラクティスを促進します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール