Php memcache class sharing (memcache Queue)

Source: Internet
Author: User

MemcacheQueue. class. php
Copy codeThe Code is as follows:
<? Php
/**
* PHP memcache queue class
* @ Author LKK/lianq.net
* @ Version 0.3
* @ Modify description:
* 1. abandoned the previous AB plane rotation idea, and used arrays like arrays to rewrite this class.
* 2. the queue is first-in-first-out by default, but the reverse reading function is added.
* 3. I would like to thank FoxHunter, a netizen, for his valuable comments.
* @ Example:
* $ Obj = new memcacheQueue ('duilie ');
* $ Obj-> add ('1asdf ');
* $ Obj-> getQueueLength ();
* $ Obj-> read (10 );
* $ Obj-> get (8 );
*/
Class memcacheQueue {
Public static $ client; // memcache client Connection
Public $ access; // whether the queue can be updated
Private $ expire; // expiration time, in seconds, 1 ~ 2592000, that is, within 30 days
Private $ sleepTime; // waiting for unlock time, in microseconds
Private $ queueName; // queue name, unique value
Private $ retryNum; // Number of retries, = 10 * theoretical concurrency
Public $ currentHead; // the first value of the current team.
Public $ currentTail; // current team end value

Const MAXNUM = 20000; // maximum number of queues. the maximum number of queues is 10 K.
Const HEAD_KEY = '_ lkqueuehead _'; // The first kye of the queue
Const TAIL_KEY = '_ lkqueuetail _'; // the end key of the queue.
Const VALU_KEY = '_ lkqueuevalu _'; // queue value key
Const LOCK_KEY = '_ lkqueuelock _'; // queue Lock key

/**
* Constructor
* @ Param string $ queueName queue name
* @ Param int $ expire expiration time
* @ Param array $ config memcache Configuration
*
* @ Return <type>
*/
Public function _ construct ($ queueName = '', $ expire = 0, $ config = ''){
If (empty ($ config )){
Self: $ client = memcache_pconnect ('2017. 0.0.1 ', 127 );
} Elseif (is_array ($ config) {// array ('host' => '2017. 0.0.1 ', 'Port' => '2016 ')
Self: $ client = memcache_pconnect ($ config ['host'], $ config ['Port']);
} Elseif (is_string ($ config) {// "127.0.0.1: 11211"
$ Tmp = explode (':', $ config );
$ Conf ['host'] = isset ($ tmp [0])? $ Tmp [0]: '2017. 0.0.1 ';
$ Conf ['Port'] = isset ($ tmp [1])? $ Tmp [1]: '20140901 ';
Self: $ client = memcache_pconnect ($ conf ['host'], $ conf ['Port']);
}
If (! Self: $ client) return false;

Ignore_user_abort (true); // when the customer disconnects, continue execution is allowed.
Set_time_limit (0); // cancels the upper limit of script execution latency

$ This-> access = false;
$ This-& gt; sleepTime = 1000;
$ Expire = empty ($ expire )? 3600: intval ($ expire) + 1;
$ This-> expire = $ expire;
$ This-> queueName = $ queueName;
$ This-> retrynum= 1000;

$ This-> head_key = $ this-> queueName. self: HEAD_KEY;
$ This-> tail_key = $ this-> queueName. self: TAIL_KEY;
$ This-> lock_key = $ this-> queueName. self: LOCK_KEY;

$ This-> _ initSetHeadNTail ();
}

/**
* Initialize and set the first and end values of the queue.
*/
Private function _ initSetHeadNTail (){
// The first value of the current queue
$ This-> currentHead = memcache_get (self: $ client, $ this-> head_key );
If ($ this-> currentHead = false) $ this-> currentHead = 0;

// The value at the end of the current queue
$ This-> currentTail = memcache_get (self: $ client, $ this-> tail_key );
If ($ this-> currentTail = false) $ this-> currentTail = 0;
}

/**
* When an element is retrieved, the first value of the queue is changed.
* @ Param int $ step value
*/
Private function _ changeHead ($ step = 1 ){
$ This-> currentHead + = $ step;
Memcache_set (self: $ client, $ this-> head_key, $ this-> currentHead, false, $ this-> expire );
}

/**
* When an element is added, the value at the end of the queue is changed.
* @ Param int $ step value
* @ Param bool $ whether the reverse is reversed
* @ Return null
*/
Private function _ changeTail ($ step = 1, $ reverse = false ){
If (! $ Reverse ){
$ This-> currentTail + = $ step;
} Else {
$ This-> currentTail-= $ step;
}

Memcache_set (self: $ client, $ this-> tail_key, $ this-> currentTail, false, $ this-> expire );
}

/**
* Whether the queue is empty
* @ Return bool
*/
Private function _ isEmpty (){
Return (bool) ($ this-> currentHead ===$ this-> currentTail );
}

/**
* Whether the queue is full
* @ Return bool
*/
Private function _ isFull (){
$ Len = $ this-> currentTail-$ this-> currentHead;
Return (bool) ($ len = self: MAXNUM );
}

/**
* Queue locking
*/
Private function _ getLock (){
If ($ this-> access === false ){
While (! Memcache_add (self: $ client, $ this-> lock_key, 1, false, $ this-> expire )){
Usleep ($ this-> sleepTime );
@ $ I ++;
If ($ I> $ this-> retryNum) {// try to wait N times
Return false;
Break;
}
}

$ This-> _ initSetHeadNTail ();
Return $ this-> access = true;
}

Return $ this-> access;
}

/**
* Queue unlock
*/
Private function _ unLock (){
Memcache_delete (self: $ client, $ this-> lock_key, 0 );
$ This-> access = false;
}

/**
* Get the length of the current queue
* This length is the theoretical length. Some elements are lost due to expiration. The actual length <= this length
* @ Return int
*/
Public function getQueueLength (){
$ This-> _ initSetHeadNTail ();
Return intval ($ this-> currentTail-$ this-> currentHead );
}

/**
* Add queue data
* @ Param void $ data the data to be added
* @ Return bool
*/
Public function add ($ data ){
If (! $ This-> _ getLock () return false;

If ($ this-> _ isFull ()){
$ This-> _ unLock ();
Return false;
}

$ Value_key = $ this-> queueName. self: VALU_KEY. strval ($ this-> currentTail + 1 );
$ Result = memcache_set (self: $ client, $ value_key, $ data, MEMCACHE_COMPRESSED, $ this-> expire );
If ($ result ){
$ This-> _ changeTail ();
}

$ This-> _ unLock ();
Return $ result;
}

/**
* Reading queue data
* @ Param int $ length the length to be read (negative number is used for reverse READING)
* @ Return array
*/
Public function read ($ length = 0 ){
If (! Is_numeric ($ length) return false;
$ This-> _ initSetHeadNTail ();

If ($ this-> _ isEmpty ()){
Return false;
}

If (empty ($ length) $ length = self: MAXNUM; // all by default
$ KeyArr = array ();
If ($ length> 0) {// forward read (from the first to the end of the queue)
$ TmpMin = $ this-> currentHead;
$ TmpMax = $ tmpMin + $ length;
For ($ I = $ tmpMin; $ I <= $ tmpMax; $ I ++ ){
$ KeyArr [] = $ this-> queueName. self: VALU_KEY. $ I;
}
} Else {// reverse read (from the end of the queue to the first of the queue)
$ TmpMax = $ this-> currentTail;
$ TmpMin = $ tmpMax + $ length;
For ($ I = $ tmpMax; $ I> $ tmpMin; $ I --){
$ KeyArr [] = $ this-> queueName. self: VALU_KEY. $ I;
}
}

$ Result = @ memcache_get (self: $ client, $ keyArr );

Return $ result;
}

/**
* Retrieve queue data
* @ Param int $ length the length to be retrieved (negative number is used for reverse READING)
* @ Return array
*/
Public function get ($ length = 0 ){
If (! Is_numeric ($ length) return false;
If (! $ This-> _ getLock () return false;

If ($ this-> _ isEmpty ()){
$ This-> _ unLock ();
Return false;
}

If (empty ($ length) $ length = self: MAXNUM; // all by default
$ Length = intval ($ length );
$ KeyArr = array ();
If ($ length> 0) {// forward read (from the first to the end of the queue)
$ TmpMin = $ this-> currentHead;
$ TmpMax = $ tmpMin + $ length;
For ($ I = $ tmpMin; $ I <= $ tmpMax; $ I ++ ){
$ KeyArr [] = $ this-> queueName. self: VALU_KEY. $ I;
}
$ This-> _ changeHead ($ length );
} Else {// reverse read (from the end of the queue to the first of the queue)
$ TmpMax = $ this-> currentTail;
$ TmpMin = $ tmpMax + $ length;
For ($ I = $ tmpMax; $ I> $ tmpMin; $ I --){
$ KeyArr [] = $ this-> queueName. self: VALU_KEY. $ I;
}
$ This-> _ changeTail (abs ($ length), true );
}
$ Result = @ memcache_get (self: $ client, $ keyArr );

Foreach ($ keyArr as $ v) {// delete it after Removal
@ Memcache_delete (self: $ client, $ v, 0 );
}

$ This-> _ unLock ();

Return $ result;
}

/**
* Clear a queue
*/
Public function clear (){
If (! $ This-> _ getLock () return false;

If ($ this-> _ isEmpty ()){
$ This-> _ unLock ();
Return false;
}

$ TmpMin = $ this-> currentHead --;
$ TmpMax = $ this-> currentTail ++;

For ($ I = $ tmpMin; $ I <= $ tmpMax; $ I ++ ){
$ TmpKey = $ this-> queueName. self: VALU_KEY. $ I;
@ Memcache_delete (self: $ client, $ tmpKey, 0 );
}

$ This-> currentTail = $ this-> currentHead = 0;
Memcache_set (self: $ client, $ this-> head_key, $ this-> currentHead, false, $ this-> expire );
Memcache_set (self: $ client, $ this-> tail_key, $ this-> currentTail, false, $ this-> expire );

$ This-> _ unLock ();
}

/*
* Clear all memcache cache data
*/
Public function memFlush (){
Memcache_flush (self: $ client );
}

} // End class

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.