现在,memcache于server缓存广泛应用。下面我来介绍一下memcache消息队列中等待的样本实现,有需要了解的朋友可以参考。

memche消息队列原则key上做文章。后消息或者日志。

然后通过定时程序将内容落地到文件或者数据库

php实现消息队列的用处比方在做发送邮件时发送大量邮件非常费时间的问题。那么能够採取队列。

方便实现队列的轻量级队列server是:

starling支持memcache协议的轻量级持久化server

https://github.com/starling/starling

Beanstalkd轻量、高效,支持持久化,每秒可处理3000左右的队列

http://kr.github.com/beanstalkd/

php中也能够使用memcache/memcached来实现消息队列。

<?

php
/**
* 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 < 0 ){
$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 < 0 ){
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 < 0 ) break;
$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
/**
* 使用共享内存的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 < $offset) {
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;
}
}

   
 

版权声明:本文博主原创文章,博客,未经同意不得转载。

PHP memcache实现消息队列实例的更多相关文章

  1. System V 消息队列 实例

    前言: 消息队列是消息的链接表,存放在内核中,并由消息队列标识符标识.我们将称消息队列为 “队列”,其标识符为“队列I D”.msgget创建一个新队列或打开一个存在的队列; msgsnd向队列末端添 ...

  2. PHP下用Memcache 实现消息队列

    Memcache 一般用于缓存服务.但是很多时候,比如一个消息广播系统,需要一个消息队列.直接从数据库取消息,负载往往不行.如果将整个消息队列用一个key缓存到memcache里面, 对于一个很大的消 ...

  3. system的消息队列实例

    1\创建或打开消息队列函数原型:int msgget(key_t key, int msgflg)参数第一个参数为ftok方法创建的一个kety_t或者为一个整数值第二个参数为逻辑控制,IPC_CRE ...

  4. 【6】.net msmq消息队列实例

    1.msmq消息队列windows环境安装 控制面板---->程序和功能---->启用或关闭Windows程序---->Microsoft Message Queue(MSMQ)服务 ...

  5. linux消息队列编程实例

    转自:linux 消息队列实例 前言: 消息队列就是一个消息的链表.可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向其中按照一定的规则添加新消息:对消息队列有读权 ...

  6. spring mvc redis消息队列

    通常情况下,为了提高系统开发的灵活性和可维护度,我们会采用消息队列队系统进行解耦.下面是一个采用spring redis实现的消息队列实例,但此实例会由于网络延迟和阻塞等情况导致消息处理的延时,因而不 ...

  7. 【转】MSMQ 微软消息队列 简单 示例

    MSMQ它的实现原理是:消息的发送者把自己想要发送的信息放入一个容器中(我们称之为Message),然后把它保存至一个系统公用空间的消息队列(Message Queue)中:本地或者是异地的消息接收程 ...

  8. Linux环境进程间通信(三):消息队列

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  9. (转)Linux环境进程间通信----系统 V 消息队列列

    转:http://www.ibm.com/developerworks/cn/linux/l-ipc/part3/ 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix通 ...

随机推荐

  1. 【6】和作为连续序列s

    称号:输入一个整数s,并打印出所有s整数的连续序列(含有至少2的数量). 如输入9,输出2.3.4和4.5两个序列 方案一:因为序列至少要2个数,则两个数上限值为(1+s)/2,我们能够枚举该序列的起 ...

  2. 使用clojure訪问SQL Server数据库

    (require '[korma.core :as kc]) (require '[korma.db :as kd]) (Class/forName "com.microsoft.jdbc. ...

  3. 【程序员联盟】官网上线啦!coderunity.com

    内容简介 欢天喜地,[程序员联盟]官网上线咯(此处应该有鸡蛋丢过来...) [程序员联盟]官网 大家也许会问:“这几天小编都没出文章,跑哪里happy去啦?是不是偷懒去了?” 小编:“臣妾冤枉啊.” ...

  4. 认识Require

    1. 加载require.js文件 <script type="text/javascript" src="js/require.js" data-mai ...

  5. HDU 1274 展开字符串 (递归+string类)

    题目链接:HDU 1274 展开字符串 中文题. 左括号进入DFS函数,右括号return到上一层. 注意return回去的是这个一层递归中的括号中的字母串. AC代码: #include<st ...

  6. thinkphp达到UploadFile.class.php图片上传功能

    片上传在站点里是非经常常使用的功能.ThinkPHP里也有自带的图片上传类(UploadFile.class.php) 和图片模型类(Image.class.php).方便于我们去实现图片上传功能,以 ...

  7. PowerDesigner有几个需要设置

    安装后PDM后.一些易于使用的设计人才需求. 一. 建立name与code做自己的主动关联,我们输入name当你不希望个别及连带code已经改变. 打开Tools->General Option ...

  8. bzoj 3333: 排队计划 解决问题的方法

    [原标题] 3333: 排队计划 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 161  Solved: 71 [Submit][Status] D ...

  9. HDN2048(交错复发)

    上帝.神与神 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  10. 也可以看看GCD(杭州电2504)(gcd)

    也可以看看GCD Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...