Php implements the memcached queue class by itself. Php implements the memcached queue class add (1 asdf); * $ obj-getQueueLength (); * $ obj-read (11); * $ obj-get (8 ); * classmemcacheQueue {publicstatic $ client; the memcache client connects to the pu php and implements the memcached queue class.
Add ('1asdf '); * $ obj-> getQueueLength (); * $ obj-> read (11); * $ obj-> get (8 ); */class memcacheQueue {public static $ client; // The memcache client connects to public $ access; // whether the queue can update private $ currentSide; // the current rotating queue plane: a/B private $ lastSide; // The queue surface of the previous rotation: A/B private $ sideAHead; // The first line value of A is private $ sideATail; // the end value of Team A is private $ sideBHead; // The first value of Team B is private $ sideBTail; // The end value of Team B is private $ currentHead; // The first value of the current team is private $ currentTail; // The Current Private $ lastHead; // first private $ lastTail; // last private $ expire; // expiration time, seconds, 1 ~ 2592000, that is, within 30 days; 0 is private $ sleepTime that never expires; // waiting for unlock time, microsecond private $ queueName; // queue name, unique value private $ retryNum; // Number of retries, = 10 * theoretical concurrency const MAXNUM = 2000; // (single-sided) maximum number of queues. we recommend that you set the maximum value to 10 K const HEAD_KEY = '_ lkqueuehead _'; // queue header kye const TAIL_KEY = '_ lkqueuetail _'; // queue end key const VALU_KEY = '_ lkqueuevalu _'; // queue value key const LOCK_KEY = '_ lkqueuelock _'; // queue lock key const SIDE_KEY = '_ lkqueueside _'; // rotation key/** constructor * @ para M [config] array memcache server parameter * @ param [queueName] string queue name * @ param [expire] string expiration time * @ return NULL */public function _ construct ($ queueName = '', $ expire = '', $ config ='') {if (empty ($ config) {self: $ client = memcache_pconnect ('localhost', 11211 );} elseif (is_array ($ config) {// array ('host' => '127. 0.0.1 ', 'port' => '000000') self: $ client = memcache_pconnect ($ config ['host'], $ config ['port']);} elsei F (is_string ($ config) {// "127.0.0.1: 11211" $ tmp = explode (':', $ config ); $ conf ['host'] = isset ($ tmp [0])? $ Tmp [0]: '192. 0.0.1 '; $ conf ['port'] = isset ($ tmp [1])? $ Tmp [1]: '000000'; self: $ client = memcache_pconnect ($ conf ['host'], $ conf ['port']);} if (! Self: $ client) return false; ignore_user_abort (TRUE); // when the customer disconnects, set_time_limit (0) can be continued ); // cancel the maximum latency of script execution $ this-> access = false; $ this-> sleepTime = 1000; $ expire = (empty ($ expire) & $ expire! = 0 )? 3600: (int) $ expire; $ this-> expire = $ expire; $ this-> queueName = $ queueName; $ this-> retryNum = 10000; $ side = memcache_add (self: $ client, $ queueName. self: SIDE_KEY, 'A', false, $ expire); $ this-> getHeadNTail ($ queueName); if (! Isset ($ this-> sideAHead) | empty ($ this-> sideAHead) $ this-> sideAHead = 0; if (! Isset ($ this-> sideATail) | empty ($ this-> sideATail) $ this-> sideATail = 0; if (! Isset ($ this-> sideBHead) | empty ($ this-> sideBHead) $ this-> sideBHead = 0; if (! Isset ($ this-> sideBHead) | empty ($ this-> sideBHead) $ this-> sideBHead = 0 ;} /** get the first and end values of a queue * @ param [queueName] string queue name * @ return NULL */private function getHeadNTail ($ queueName) {$ this-> sideAHead = (int) memcache_get (self: $ client, $ queueName. 'A '. self: HEAD_KEY); $ this-> sideATail = (int) memcache_get (self: $ client, $ queueName. 'A '. self: TAIL_KEY); $ this-> sideBHead = (int) memcache_get (self: $ clie Nt, $ queueName. 'B '. self: HEAD_KEY); $ this-> sideBTail = (int) memcache_get (self: $ client, $ queueName. 'B '. self: TAIL_KEY);}/** get the current rotating queue surface * @ return string queue surface name */public function getCurrentSide () {$ currentSide = memcache_get (self :: $ client, $ this-> queueName. self: SIDE_KEY); if ($ currentSide = 'a') {$ this-> currentSide = 'a'; $ this-> lastSide = 'B '; $ this-> currentHead = $ this-> sideAHead; $ this-> c UrrentTail = $ this-> sideATail; $ this-> lastHead = $ this-> sideBHead; $ this-> lastTail = $ this-> sideBTail ;} else {$ this-> currentSide = 'B'; $ this-> lastSide = 'a'; $ this-> currentHead = $ this-> sideBHead; $ this-> currentTail = $ this-> sideBTail; $ this-> lastHead = $ this-> sideAHead; $ this-> lastTail = $ this-> sideATail ;} return $ this-> currentSide;}/** queue lock * @ return boolean */private function getLock () {I F ($ this-> access === false) {while (! Memcache_add (self: $ client, $ this-> queueName. self: LOCK_KEY, 1, false, $ this-> expire) {usleep ($ this-> sleepTime); @ $ I ++; if ($ I >$ this-> retryNum) {// try to wait for N times return false; break;} return $ this-> access = true;} return false ;} /** unLock the queue * @ return NULL */private function unLock () {memcache_delete (self: $ client, $ this-> queueName. self: LOCK_KEY); $ this-> access = false;}/** add data * @ param [data] Value to be stored * @ return boolean */public function add ($ data) {$ result = false; if (! $ This-> getLock () {return $ result;} $ this-> getHeadNTail ($ this-> queueName); $ this-> getCurrentSide (); if ($ this-> isFull () {$ this-> unLock (); return false;} if ($ this-> currentTail <self: MAXNUM) {$ value_key = $ this-> queueName. $ this-> currentSide. self: VALU_KEY. $ this-> currentTail; if (memcache_add (self: $ client, $ value_key, $ data, false, $ this-> expire) {$ this-> changeTail (); $ result = true ;}} else {// The current queue is full. change the rotation plane $ this-> unLock (); $ this-> changeCurrentSide (); return $ this-> add ($ data );} $ this-> unLock (); return $ result ;} /** retrieve data * @ param [length] int data length * @ return array */public function get ($ length = 0) {if (! Is_numeric ($ length) return false; if (empty ($ length) $ length = self: MAXNUM * 2; // read all if (! $ This-> getLock () return false; if ($ this-> isEmpty () {$ this-> unLock (); return false ;} $ keyArray = $ this-> getKeyArray ($ length); $ lastKey = $ keyArray ['lastkey']; $ currentKey = $ keyArray ['currentkey']; $ keys = $ keyArray ['keys']; $ this-> changeHead ($ this-> lastSide, $ lastKey); $ this-> changeHead ($ this-> currentSide, $ currentKey); $ data = @ memcache_get (self: $ client, $ keys); foreach ($ keys as $ v) {// delete @ me after removal Mcache_delete (self: $ client, $ v, 0) ;}$ this-> unLock (); return $ data ;} /** read data * @ param [length] int data length * @ return array */public function read ($ length = 0) {if (! Is_numeric ($ length) return false; if (empty ($ length) $ length = self: MAXNUM * 2; // read all $ keyArray = $ this-> getKeyArray ($ length) by default; $ data = @ memcache_get (self: $ client, $ keyArray ['keys']); return $ data;}/** get the key array of a queue segment length * @ param [length] int queue length * @ return array */private function getKeyArray ($ length) {$ result = array ('keys' => array (), 'lastkey' => array (), 'currentkey' => array (); $ this-> getHeadNTa Il ($ this-> queueName); $ this-> getCurrentSide (); if (empty ($ length) return $ result; // first take the previous key $ I = $ result ['lastkey'] = 0; for ($ I = 0; $ I <$ length; $ I ++) {$ result ['lastkey'] = $ this-> lastHead + $ I; if ($ result ['lastkey'] >=$ this-> lastTail) break; $ result ['keys'] [] = $ this-> queueName. $ this-> lastSide. self: VALU_KEY. $ result ['lastkey'];} // Obtain the current key $ j = $ length-$ I; $ k = $ result ['currentkey'] = 0; For ($ k = 0; $ k <$ j; $ k ++) {$ result ['currentkey'] = $ this-> currentHead + $ k; if ($ result ['currentkey'] >=$ this-> currentTail) break; $ result ['Keys '] [] = $ this-> queueName. $ this-> currentSide. self: VALU_KEY. $ result ['currentkey'];} return $ result;}/** update the value at the end of the current rotation plane queue * @ return NULL */private function changeTail () {$ tail_key = $ this-> queueName. $ this-> currentSide. self: TAIL_KEY; memcache_add (self: $ c Lient, $ tail_key, 0, false, $ this-> expire); // If not, insert; if yes, false; // memcache_increment (self: $ client, $ tail_key, 1); // queue tail + 1 $ v = memcache_get (self ::$ client, $ tail_key) + 1; memcache_set (self ::$ client, $ tail_key, $ v, false, $ this-> expire );} /** UPDATE The first value of the queue * @ param [side] string the surface to be updated * @ param [headValue] int the first value of the queue * @ return NULL */private function changeHead ($ side, $ headValue) {if ($ headValue <1) return fal Se; $ head_key = $ this-> queueName. $ side. self: HEAD_KEY; $ tail_key = $ this-> queueName. $ side. self: TAIL_KEY; $ sideTail = memcache_get (self ::$ client, $ tail_key); if ($ headValue <$ sideTail) {memcache_set (self ::$ client, $ head_key, $ headValue + 1, false, $ this-> expire);} elseif ($ headValue >=$ sideTail) {$ this-> resetSide ($ side );}} /** reset the queue surface to set the frontend and backend values of the queue to 0 * @ param [side] string to be reset * @ return NULL */Private function resetSide ($ side) {$ head_key = $ this-> queueName. $ side. self: HEAD_KEY; $ tail_key = $ this-> queueName. $ side. self: TAIL_KEY; memcache_set (self: $ client, $ head_key, 0, false, $ this-> expire); memcache_set (self: $ client, $ tail_key, 0, false, $ this-> expire);}/** change the current rotating queue surface * @ return string */private function changeCurrentSide () {$ currentSide = memcache_get (self :: $ client, $ this-> queue Name. self: SIDE_KEY); if ($ currentSide = 'a') {memcache_set (self: $ client, $ this-> queueName. self: SIDE_KEY, 'B', false, $ this-> expire); $ this-> currentSide = 'B';} else {memcache_set (self: $ client, $ this-> queueName. self: SIDE_KEY, 'A', false, $ this-> expire); $ this-> currentSide = 'a';} return $ this-> currentSide ;} /** check whether the current queue is full * @ return boolean */public function isFull () {$ result = false; if ($ t His-> sideATail = self: MAXNUM & $ this-> sideBTail = self: MAXNUM) {$ result = true;} return $ result ;} /** check whether the current queue is empty * @ return boolean */public function isEmpty () {$ result = true; if ($ this-> sideATail> 0 | $ this-> sideBTail> 0) {$ result = false;} return $ result ;} /** get the length of the current queue * this length is the theoretical length, and some elements are lost due to expiration failure, the actual length is less than or equal to this length * @ return int */public function getQueueLength () {$ this-> getHeadNTail ($ thi S-> queueName); $ this-> getCurrentSide (); $ sideALength = $ this-> sideATail-$ this-> sideAHead; $ sideBLength = $ this-> sideBTail-$ this-> sideBHead; $ result = $ sideALength + $ sideBLength; return $ result;}/** Clear data in the current queue, only the HEAD_KEY, TAIL_KEY, and SIDE_KEY Keys * @ return boolean */public function clear () {if (! $ This-> getLock () return false; for ($ I = 0; $ I
QueueName. 'A '. self: VALU_KEY. $ I, 0); @ memcache_delete (self: $ client, $ this-> queueName. 'B '. self: VALU_KEY. $ I, 0) ;}$ this-> unLock (); $ this-> resetSide ('A'); $ this-> resetSide ('B '); return true;}/** Clear all memcache cached data * @ return NULL */public function memFlush () {memcache_flush (self ::$ client );}}
Revoke add (1 asdf); * $ obj-getQueueLength (); * $ obj-read (11); * $ obj-get (8 ); */class memcacheQueue {public static $ client; // connect the memcache client to pu...