The principle of Memche Message Queuing is to make a fuss over the key to do a continuous number plus the prefix records after serialization of messages or logs. The content is then landed in a file or database through a timer program.
The use of PHP to implement Message Queuing, such as sending a large number of emails to send a time-consuming problem, you can take the queue.
Lightweight queuing servers for easy implementation of queues are:
Starling lightweight persistent servers that support the Memcache protocol
Https://github.com/starling/starling
BEANSTALKD lightweight, efficient, support for persistence, can handle about 3000 of queues per second
http://kr.github.com/beanstalkd/
You can also use memcache/memcached in PHP to implement Message Queuing.
Copy Code code as follows:
<?php
/**
* Memcache Message Queuing class
*/
Class QMC {
Const PREFIX = ' Asdfasdffwqke ';
/**
* Initialization of 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 Counter, add count and return the new count
* @param string $key counter
* @param int $offset count increment, which can be negative. 0 for unchanged Count
* @param int $time time
* @return Int/false failure is return false, count after returning the update counter when successful
*/
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;
}
/**
* Write queue
* @param string $key
* @param mixed $value
* @return BOOL
*/
static public Function input ($key, $value) {
$MC = Self::mc_init ();
$w _key = self::P refix. $key. ' W ';
$v _key = self::P refix. $key. Self::set_counter ($w _key, 1);
Return $MC->set ($v _key, $value);
}
/**
* Read the data in the queue
* @param string $key
* @param int $max Read the maximum number of bars
* @return Array
*/
static public function output ($key, $max = 100) {
$out = Array ();
$MC = Self::mc_init ();
$r _key = self::P refix. $key. ' R ';
$w _key = self::P refix. $key. ' W ';
$r _p = Self::set_counter ($r _key, 0);//Read pointer
$w _p = Self::set_counter ($w _key, 0);//write pointer
if ($r _p = = 0) $r _p = 1;
while ($w _p >= $r _p) {
if (--$max < 0) break;
$v _key = self::P refix. $key. $r _p;
$r _p = Self::set_counter ($r _key, 1);
$out [] = $MC->get ($v _key);
$MC->delete ($v _key);
}
return $out;
}
}
/**
How to use:
Qmc::input ($key, $value);//write queue
$list = Qmc::output ($key);//Read queue
*/
?>
Based on PHP shared memory implementation of Message Queuing:
Copy Code code as follows:
<?php
/**
* Using shared Memory for PHP loop memory queue implementation
* Supports multiple processes to support storage of various data types
* Note: Complete the team or outbound operation, use Unset () as soon as possible to release the critical section
*
* @author wangbinandi@gmail.com
* @created 2009-12-23
*/
Class Shmqueue
{
Private $maxQSize = 0; Maximum Queue Length
Private $front = 0; Team Head pointer
Private $rear = 0; Team Tail pointer
Private $blockSize = 256; Size of block (byte)
Private $memSize = 25600; Maximum shared memory (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;
A signal quantity.
$this->semid = Sem_get ($shmkey, 1);
Sem_acquire ($this->semid); Apply for entry into critical section
$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) {//Team full
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) {//Team empty
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); Out of the critical section, releasing the signal volume
}
}
/*
Enter the team operation
$SHMQ = new Shmqueue ();
$data = ' test data ';
$SHMQ->enqueue ($data);
Unset ($SHMQ);
Out Team operation
$SHMQ = new Shmqueue ();
$data = $shmq->dequeue ();
Unset ($SHMQ);
*/
?>
For a large message queue, frequent serialization and deserialization of large databases can be costly. Here is a message queue I implemented with PHP, just to insert a data in the tail, the operation of the tail, do not operate the entire message queue for reading, and operation. However, this message queue is not thread safe, I just try to avoid the possibility of conflict. If the message is not very dense, such as a few seconds, you can still consider using this.
If you want to implement thread-safe, one suggestion is to lock through the file and then do the operation. Here's the code:
The code is as follows:
Copy Code code as follows:
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 Object A");
}
$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->max Size)
{
$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;
}
}