PHP實現的memcache環形隊列類執行個體

來源:互聯網
上載者:User
本文執行個體講述了PHP實現的memcache環形隊列類。分享給大家供大家參考。具體如下:

這裡介紹了PHP實現的memcache環形隊列類。沒咋學過資料結構,因為業務需要,所以只是硬著頭皮類比的! 參考PHP memcache 隊列代碼。為使隊列隨時可入可出,且不受int長度越界危險(單鏈採取Head自增的話不作處理有越界可能),所以索性改寫成環形隊列。可能還有BUG,忘見諒!

'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)) ? 0 : (int) $expire + 1;  $this->expire  = $expire;  $this->queueName = $queueName;  $this->retryNum = 20000;  $this->MAXNUM  = $maxqueue != null ? $maxqueue : 1;  $this->canRewrite = $canRewrite;  $this->getHeadAndTail();  if (!isset($this->HEAD) || empty($this->HEAD))   $this->HEAD = 0;  if (!isset($this->TAIL) || empty($this->TAIL))   $this->TAIL = 0;  if (!isset($this->LEN) || empty($this->LEN))   $this->LEN = 0; } //擷取隊列首尾指標資訊和長度 private function getHeadAndTail() {  $this->HEAD = (int) memcache_get(self::$client, $this->queueName . self::HEAD_KEY);  $this->TAIL = (int) memcache_get(self::$client, $this->queueName . self::TAIL_KEY);  $this->LEN = (int) memcache_get(self::$client, $this->queueName . self::LENGTH_KEY); } // 利用memcache_add原子性加鎖 private function lock() {  if ($this->access === false) {   $i = 0;   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; } //更新頭部指標指向,指向下一個位置 private function incrHead() {  //$this->getHeadAndTail(); //擷取最新指標資訊 ,由於本方法體均在鎖內調用,其鎖內已調用了此方法,本行注釋  $this->HEAD++; //頭部指標下移  if ($this->HEAD >= $this->MAXNUM) {   $this->HEAD = 0; //邊界值修正  }  ;  $this->LEN--; //Head的移動由Pop觸發,所以相當於數量減少  if ($this->LEN < 0) {   $this->LEN = 0; //邊界值修正  }  ;  memcache_set(self::$client, $this->queueName . self::HEAD_KEY, $this->HEAD, false, $this->expire); //更新  memcache_set(self::$client, $this->queueName . self::LENGTH_KEY, $this->LEN, false, $this->expire); //更新 } //更新尾部指標指向,指向下一個位置 private function incrTail() {  //$this->getHeadAndTail(); //擷取最新指標資訊,由於本方法體均在鎖內調用,其鎖內已調用了此方法,本行注釋  $this->TAIL++; //尾部指標下移  if ($this->TAIL >= $this->MAXNUM) {   $this->TAIL = 0; //邊界值修正  }  ;  $this->LEN++; //Head的移動由Push觸發,所以相當於數量增加  if ($this->LEN >= $this->MAXNUM) {   $this->LEN = $this->MAXNUM; //邊界值長度修正  }  ;  memcache_set(self::$client, $this->queueName . self::TAIL_KEY, $this->TAIL, false, $this->expire); //更新  memcache_set(self::$client, $this->queueName . self::LENGTH_KEY, $this->LEN, false, $this->expire); //更新 } // 解鎖 private function unLock() {  memcache_delete(self::$client, $this->queueName . self::LOCK_KEY);  $this->access = false; } //判斷是否滿隊列 public function isFull() {  //外部直接調用的時候由於沒有鎖所以此處的值是個大概值,並不很準確,但是內部調用由於在前面有lock,所以可信  if ($this->canRewrite)   return false;  return $this->LEN == $this->MAXNUM ? true : false; } //判斷是否為空白 public function isEmpty() {  //外部直接調用的時候由於沒有鎖所以此處的值是個大概值,並不很準確,但是內部調用由於在前面有lock,所以可信  return $this->LEN == 0 ? true : false; } public function getLen() {  //外部直接調用的時候由於沒有鎖所以此處的值是個大概值,並不很準確,但是內部調用由於在前面有lock,所以可信  return $this->LEN; } /*  * push值  * @param mixed 值  * @return bool  */ public function push($data = '') {  $result = false;  if (empty($data))   return $result;  if (!$this->lock()) {   return $result;  }  $this->getHeadAndTail(); //擷取最新指標資訊  if ($this->isFull()) { //只有在非覆寫下才有Full概念   $this->unLock();   return false;  }  if (memcache_set(self::$client, $this->queueName . self::VALU_KEY . $this->TAIL, $data, MEMCACHE_COMPRESSED, $this->expire)) {   //當推送後,發現尾部和頭部重合(此時指標還未移動),且右邊仍有未由Head讀取的資料,那麼移動Head指標,避免尾部指標跨越Head   if ($this->TAIL == $this->HEAD && $this->LEN >= 1) {    $this->incrHead();   }   $this->incrTail(); //移動尾部指標   $result = true;  }  $this->unLock();  return $result; } /*  * Pop一個值  * @param [length] int 隊列長度  * @return array  */ public function pop($length = 0) {  if (!is_numeric($length))   return false;  if (!$this->lock())   return false;  $this->getHeadAndTail();  if (empty($length))   $length = $this->LEN; //預設讀取所有  if ($this->isEmpty()) {   $this->unLock();   return false;  }  //擷取長度超出隊列長度後進行修正  if ($length > $this->LEN)   $length = $this->LEN;  $data = $this->popKeyArray($length);  $this->unLock();  return $data; } /*  * pop某段長度的值  * @param [length] int 隊列長度  * @return array  */ private function popKeyArray($length) {  $result = array();  if (empty($length))   return $result;  for ($k = 0; $k < $length; $k++) {   $result[] = @memcache_get(self::$client, $this->queueName . self::VALU_KEY . $this->HEAD);   @memcache_delete(self::$client, $this->queueName . self::VALU_KEY . $this->HEAD, 0);   //當提取值後,發現頭部和尾部重合(此時指標還未移動),且右邊沒有資料,即隊列中最後一個資料被完全掏空,此時指標停留在本地不移動,隊列長度變為0   if ($this->TAIL == $this->HEAD && $this->LEN <= 1) {    $this->LEN = 0;    memcache_set(self::$client, $this->queueName . self::LENGTH_KEY, $this->LEN, false, $this->expire); //更新    break;   } else {    $this->incrHead(); //首尾未重合,或者重合但是仍有未讀取出的資料,均移動HEAD指標到下一處待讀取位置   }  }  return $result; } /*  * 重設隊列  * * @return NULL  */ private function reset($all = false) {  if ($all) {   memcache_delete(self::$client, $this->queueName . self::HEAD_KEY, 0);   memcache_delete(self::$client, $this->queueName . self::TAIL_KEY, 0);   memcache_delete(self::$client, $this->queueName . self::LENGTH_KEY, 0);  } else {   $this->HEAD = $this->TAIL = $this->LEN = 0;   memcache_set(self::$client, $this->queueName . self::HEAD_KEY, 0, false, $this->expire);   memcache_set(self::$client, $this->queueName . self::TAIL_KEY, 0, false, $this->expire);   memcache_set(self::$client, $this->queueName . self::LENGTH_KEY, 0, false, $this->expire);  } } /*  * 清除所有memcache快取資料  * @return NULL  */ public function memFlush() {  memcache_flush(self::$client); } public function clear($all = false) {  if (!$this->lock())   return false;  $this->getHeadAndTail();  $Head = $this->HEAD;  $Length = $this->LEN;  $curr = 0;  for ($i = 0; $i < $Length; $i++) {   $curr = $this->$Head + $i;   if ($curr >= $this->MAXNUM) {    $this->HEAD = $curr = 0;   }   @memcache_delete(self::$client, $this->queueName . self::VALU_KEY . $curr, 0);  }  $this->unLock();  $this->reset($all);  return true; }}

希望本文所述對大家的php程式設計有所協助。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    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.