php自己实现memcached的队列类
<!--?php /* * memcache队列类 * 支持多进程并发写入、读取 * 边写边读,AB面轮值替换 * @author guoyu * @create on 9:25 2014-9-28 * @qq技术行业交流群:136112330 * * @example: * $obj = new memcacheQueue('duilie'); * $obj--->add('1asdf'); * $obj->getQueueLength(); * $obj->read(11); * $obj->get(8); */ class memcacheQueue{ public static $client; //memcache客户端连接 public $access; //队列是否可更新 private $currentSide; //当前轮值的队列面:A/B private $lastSide; //上一轮值的队列面:A/B private $sideAHead; //A面队首值 private $sideATail; //A面队尾值 private $sideBHead; //B面队首值 private $sideBTail; //B面队尾值 private $currentHead; //当前队首值 private $currentTail; //当前队尾值 private $lastHead; //上轮队首值 private $lastTail; //上轮队尾值 private $expire; //过期时间,秒,1~2592000,即30天内;0为永不过期 private $sleepTime; //等待解锁时间,微秒 private $queueName; //队列名称,唯一值 private $retryNum; //重试次数,= 10 * 理论并发数 const MAXNUM = 2000; //(单面)最大队列数,建议上限10K const HEAD_KEY = '_lkkQueueHead_'; //队列首kye const TAIL_KEY = '_lkkQueueTail_'; //队列尾key const VALU_KEY = '_lkkQueueValu_'; //队列值key const LOCK_KEY = '_lkkQueueLock_'; //队列锁key const SIDE_KEY = '_lkkQueueSide_'; //轮值面key /* * 构造函数 * @param [config] array memcache服务器参数 * @param [queueName] string 队列名称 * @param [expire] string 过期时间 * @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'=>'11211') 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] : '127.0.0.1'; $conf['port'] = isset($tmp[1]) ? $tmp[1] : '11211'; self::$client = memcache_pconnect($conf['host'],$conf['port']); } if(!self::$client) return false; ignore_user_abort(TRUE);//当客户断开连接,允许继续执行 set_time_limit(0);//取消脚本执行延时上限 $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; } /* * 获取队列首尾值 * @param [queueName] string 队列名称 * @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::$client, $queueName.'B'. self::HEAD_KEY); $this->sideBTail = (int)memcache_get(self::$client, $queueName.'B'. self::TAIL_KEY); } /* * 获取当前轮值的队列面 * @return string 队列面名称 */ 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->currentTail = $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; } /* * 队列加锁 * @return boolean */ private function getLock(){ if($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){//尝试等待N次 return false; break; } } return $this->access = true; } return false; } /* * 队列解锁 * @return NULL */ private function unLock(){ memcache_delete(self::$client, $this->queueName .self::LOCK_KEY); $this->access = false; } /* * 添加数据 * @param [data] 要存储的值 * @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{//当前队列已满,更换轮值面 $this->unLock(); $this->changeCurrentSide(); return $this->add($data); } $this->unLock(); return $result; } /* * 取出数据 * @param [length] int 数据的长度 * @return array */ public function get($length=0){ if(!is_numeric($length)) return false; if(empty($length)) $length = self::MAXNUM * 2;//默认读取所有 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){//取出之后删除 @memcache_delete(self::$client, $v, 0); } $this->unLock(); return $data; } /* * 读取数据 * @param [length] int 数据的长度 * @return array */ public function read($length=0){ if(!is_numeric($length)) return false; if(empty($length)) $length = self::MAXNUM * 2;//默认读取所有 $keyArray = $this->getKeyArray($length); $data = @memcache_get(self::$client, $keyArray['keys']); return $data; } /* * 获取队列某段长度的key数组 * @param [length] int 队列长度 * @return array */ private function getKeyArray($length){ $result = array('keys'=>array(),'lastKey'=>array(),'currentKey'=>array()); $this->getHeadNTail($this->queueName); $this->getCurrentSide(); if(empty($length)) return $result; //先取上一面的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']; } //再取当前面的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; } /* * 更新当前轮值面队列尾的值 * @return NULL */ private function changeTail(){ $tail_key = $this->queueName .$this->currentSide . self::TAIL_KEY; memcache_add(self::$client, $tail_key, 0,false, $this->expire);//如果没有,则插入;有则false; //memcache_increment(self::$client, $tail_key, 1);//队列尾+1 $v = memcache_get(self::$client, $tail_key) +1; memcache_set(self::$client, $tail_key,$v,false,$this->expire); } /* * 更新队列首的值 * @param [side] string 要更新的面 * @param [headValue] int 队列首的值 * @return NULL */ private function changeHead($side,$headValue){ if($headValue < 1) return false; $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); } } /* * 重置队列面,即将该队列面的队首、队尾值置为0 * @param [side] string 要重置的面 * @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); } /* * 改变当前轮值队列面 * @return string */ private function changeCurrentSide(){ $currentSide = memcache_get(self::$client, $this->queueName . 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; } /* * 检查当前队列是否已满 * @return boolean */ public function isFull(){ $result = false; if($this->sideATail == self::MAXNUM && $this->sideBTail == self::MAXNUM){ $result = true; } return $result; } /* * 检查当前队列是否为空 * @return boolean */ public function isEmpty(){ $result = true; if($this->sideATail > 0 $this->sideBTail > 0){ $result = false; } return $result; } /* * 获取当前队列的长度 * 该长度为理论长度,某些元素由于过期失效而丢失,真实长度小于或等于该长度 * @return int */ public function getQueueLength(){ $this->getHeadNTail($this->queueName); $this->getCurrentSide(); $sideALength = $this->sideATail - $this->sideAHead; $sideBLength = $this->sideBTail - $this->sideBHead; $result = $sideALength + $sideBLength; return $result; } /* * 清空当前队列数据,仅保留HEAD_KEY、TAIL_KEY、SIDE_KEY三个key * @return boolean */ public function clear(){ if(!$this->getLock()) return false; for($i=0;$i<self::maxnum;$i++){ this-="">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; } /* * 清除所有memcache缓存数据 * @return NULL */ public function memFlush(){ memcache_flush(self::$client); } } </self::maxnum;$i++){>

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

許多用戶在選擇智慧型手錶的時候都會選擇的華為的品牌,其中華為GT3pro和GT4都是非常熱門的選擇,不少用戶都很好奇華為GT3pro和GT4有什麼區別,下面就給大家介紹一下二者。華為GT3pro和GT4有什麼差別一、外觀GT4:46mm和41mm,材質是玻璃鏡板+不鏽鋼機身+高分纖維後殼。 GT3pro:46.6mm和42.9mm,材質是藍寶石玻璃鏡+鈦金屬機身/陶瓷機身+陶瓷後殼二、健康GT4:採用最新的華為Truseen5.5+演算法,結果會更加的精準。 GT3pro:多了ECG心電圖和血管及安

報錯的原因NameResolutionError(self.host,self,e)frome是由urllib3函式庫中的例外類型,這個錯誤的原因是DNS解析失敗,也就是說,試圖解析的主機名稱或IP位址無法找到。這可能是由於輸入的URL位址不正確,或DNS伺服器暫時無法使用所導致的。如何解決解決此錯誤的方法可能有以下幾種:檢查輸入的URL地址是否正確,確保它是可訪問的確保DNS伺服器可用,您可以嘗試在命令行中使用"ping"命令來測試DNS伺服器是否可用嘗試使用IP位址而不是主機名稱來存取網站如果是在代理

C語言return的用法有:1、對於傳回值類型為void的函數,可以使用return語句來提前結束函數的執行;2、對於傳回值型別不為void的函數,return語句的作用是將函數的執行結果傳回給呼叫者;3、提前結束函數的執行,在函數內部,我們可以使用return語句來提前結束函數的執行,即使函數並沒有回傳值。

為什麼截圖工具在Windows11上不起作用了解問題的根本原因有助於找到正確的解決方案。以下是截圖工具可能無法正常工作的主要原因:對焦助手已開啟:這可以防止截圖工具開啟。應用程式損壞:如果截圖工具在啟動時崩潰,則可能已損壞。過時的圖形驅動程式:不相容的驅動程式可能會幹擾截圖工具。來自其他應用程式的干擾:其他正在運行的應用程式可能與截圖工具衝突。憑證已過期:升級過程中的錯誤可能會導致此issu簡單的解決方案這些適合大多數用戶,不需要任何特殊的技術知識。 1.更新視窗與Microsoft應用程式商店應用程

原始碼:publicclassReturnFinallyDemo{publicstaticvoidmain(String[]args){System.out.println(case1());}publicstaticintcase1(){intx;try{x=1;returnx;}finally{x=3;}}#輸出上述程式碼的輸出可以簡單地得出結論:return在finally之前執行,我們來看下字節碼層面上發生了什麼事情。下面截取case1方法的部分字節碼,並且對照源碼,將每個指令的含義註釋在

在介紹Python的self用法之前,先來介紹下Python中的類別和實例我們知道,物件導向最重要的概念就是類別(class)和實例(instance),類別是抽象的模板,例如學生這個抽象的事物,可以用一個Student類別來表示。而實例是根據類別創建出來的一個個具體的“物件”,每個物件都從類別中繼承有相同的方法,但各自的資料可能不同。 1.以Student類別為例,在Python中,定義類別如下:classStudent(object):pass(Object)表示該類別從哪個類別繼承下來的,Object類別是所有

第1部分:初始故障排除步驟檢查蘋果的系統狀態:在深入研究複雜的解決方案之前,讓我們先從基礎知識開始。問題可能不在於您的設備;蘋果的伺服器可能會關閉。造訪Apple的系統狀態頁面,查看AppStore是否正常運作。如果有問題,您所能做的就是等待Apple修復它。檢查您的網路連接:確保您擁有穩定的網路連接,因為「無法連接到AppStore」問題有時可歸因於連接不良。嘗試在Wi-Fi和行動數據之間切換或重置網路設定(「常規」>「重置」>「重置網路設定」>設定)。更新您的iOS版本:

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code
