亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > 建站經驗 > 正文

PHP實現的memcache環形隊列類實例

2024-04-25 20:40:11
字體:
來源:轉載
供稿:網友

本文實例講述了PHP實現的memcache環形隊列類。分享給大家供大家參考。具體如下:

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

<?php

/**

* PHP memcache 環形隊列類

* 原作者 LKK/lianq.net

* 修改 FoxHunter

* 因業務需要只保留的隊列中的Pop和Push,修改過期時間為0即永久

*/

class MQueue

{

public static $client;

private $expire; //過期時間,秒,1~2592000,即30天內

private $sleepTime; //等待解鎖時間,微秒

private $queueName; //隊列名稱,唯一值

private $retryNum; //嘗試次數

private $MAXNUM; //最大隊列容量

private $canRewrite; //是否可以覆寫開關,滿出來的內容從頭部開始覆蓋重寫原來的數據

private $HEAD; //下一步要進入的指針位置

private $TAIL; //下一步要進入的指針位置

private $LEN; //隊列現有長度

const LOCK_KEY = '_Fox_MQ_LOCK_'; //鎖存儲標示

const LENGTH_KEY = '_Fox_MQ_LENGTH_'; //隊列現長度存儲標示

const VALU_KEY = '_Fox_MQ_VAL_'; //隊列鍵值存儲標示

const HEAD_KEY = '_Fox_MQ_HEAD_'; //隊列HEAD指針位置標示

const TAIL_KEY = '_Fox_MQ_TAIL_'; //隊列TAIL指針位置標示

/*

* 構造函數

* 對于同一個$queueName,實例化時必須保障構造函數的參數值一致,否則pop和push會導隊列順序混亂

*/

public function __construct($queueName = '', $maxqueue = 1, $canRewrite = false, $expire = 0, $config = '')

{

if (empty($config)) {

self::$client = memcache_pconnect('127.0.0.1', 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)) ? 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程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人福利在线视频| 欧美国产中文字幕| 欧美日韩国产二区| 日韩中文字幕亚洲| 久久精品91久久久久久再现| 欧美激情一区二区三区在线视频观看| 亚洲精选一区二区| 草民午夜欧美限制a级福利片| 久久久视频在线| 亚洲视频在线观看免费| 永久免费毛片在线播放不卡| 欧美在线中文字幕| 欧美色视频日本版| 欧美国产日产韩国视频| 国产亚洲精品美女久久久| 久久99国产精品久久久久久久久| 国产精品大片wwwwww| 欧美日韩免费在线观看| 在线视频欧美日韩精品| 2019中文字幕免费视频| 日韩成人在线视频观看| 麻豆精品精华液| 久久亚洲精品一区| 亚洲精品永久免费精品| 欧美精品第一页在线播放| 亚洲精品久久久久国产| 午夜精品福利电影| 中文字幕日韩专区| 久热国产精品视频| 1769国内精品视频在线播放| 一区二区三区国产视频| 日韩专区中文字幕| 91久久在线视频| 国产精品一二三视频| 日韩高清人体午夜| 欧美精品一区二区免费| 国产亚洲福利一区| 日本免费一区二区三区视频观看| 欧美精品在线第一页| 久久777国产线看观看精品| 国产精品日韩欧美综合| 国产999在线观看| 日韩视频免费大全中文字幕| 国产成人精品国内自产拍免费看| 国产99久久精品一区二区 夜夜躁日日躁| 日韩中文字幕视频在线观看| 欧美日韩午夜剧场| 国产精品对白刺激| 国产精品视频网址| 日韩在线视频线视频免费网站| 欧美日在线观看| 久久久亚洲国产天美传媒修理工| 日韩精品极品在线观看播放免费视频| 国产精品九九九| 欧美视频免费在线观看| 久久综合亚洲社区| 中文字幕自拍vr一区二区三区| 综合av色偷偷网| 国产精品美女久久| 日韩美女写真福利在线观看| 久久99精品久久久久久青青91| 色综合五月天导航| 国产一区二区三区三区在线观看| 国产欧美精品一区二区| 日韩不卡中文字幕| 国产日韩综合一区二区性色av| 精品国产一区av| 自拍偷拍亚洲一区| 亚洲免费伊人电影在线观看av| 91中文精品字幕在线视频| 欧美视频中文在线看| 草民午夜欧美限制a级福利片| 不卡av日日日| 日韩中文字幕第一页| 日本亚洲欧洲色α| 欧美视频在线看| 色偷偷9999www| 亚洲人成免费电影| 国产原创欧美精品| 精品福利樱桃av导航| 亚洲成人久久久久| 久久91亚洲人成电影网站| 国产视频精品自拍| 日韩中文字幕在线视频| 亚洲一区二区久久久久久| 日韩极品精品视频免费观看| 浅井舞香一区二区| 亚洲欧美日韩直播| 6080yy精品一区二区三区| 亚洲网站视频福利| 国产精品天天狠天天看| 成人xxxxx| 午夜精品一区二区三区在线| 亚洲精品国产品国语在线| 欧美午夜激情小视频| 日韩欧亚中文在线| 国产日韩精品入口| 亚洲第一级黄色片| 一本久久综合亚洲鲁鲁| 亚洲精品国产精品国自产在线| www.99久久热国产日韩欧美.com| 欧美尤物巨大精品爽| 日韩黄色高清视频| 日韩国产高清污视频在线观看| 欧美激情视频一区二区三区不卡| 色婷婷亚洲mv天堂mv在影片| 日韩成人中文字幕| 欧美成人sm免费视频| 久久久天堂国产精品女人| 亚洲美女久久久| 欧美最猛性xxxxx(亚洲精品)| 欧美日韩在线视频首页| 国产精品丝袜视频| 中文字幕精品在线视频| 国产日韩在线一区| 国产日韩欧美影视| 精品丝袜一区二区三区| 日韩在线视频免费观看高清中文| 精品亚洲一区二区三区四区五区| 亚洲国产精品99久久| 国产偷国产偷亚洲清高网站| 久久综合免费视频| 日韩欧美黄色动漫| 夜夜嗨av色一区二区不卡| 欧美精品久久久久久久久| 最新69国产成人精品视频免费| 亚洲国产精品嫩草影院久久| 亚洲人成在线一二| 国产精品久久久| 中文字幕亚洲天堂| 亚洲天堂免费视频| 92裸体在线视频网站| 日本一区二三区好的精华液| 亚洲天堂网站在线观看视频| 日韩在线视频导航| 亚洲男人的天堂在线| 久久久999精品| 亚洲黄色www网站| 国产视频精品久久久| 一本久久综合亚洲鲁鲁| 国产成人亚洲精品| 国产97免费视| 欧美专区第一页| 欧洲亚洲免费视频| 国产美女直播视频一区| 自拍偷拍亚洲精品| 欧美日韩亚洲精品内裤| 国产欧美精品一区二区三区-老狼| 日韩av影院在线观看| 久久国产精品久久久久久久久久| 亚洲欧美日韩直播| 91大神福利视频在线| 欧美日韩亚洲精品一区二区三区| 国内免费久久久久久久久久久| 国产97在线|日韩| 日本精品一区二区三区在线播放视频| 精品久久久久久久久国产字幕| 国产精品v片在线观看不卡| 韩国一区二区电影| 欧美日韩不卡合集视频| 欧美最猛性xxxxx亚洲精品| 欧美精品www| 日韩av有码在线| 欧美日韩免费在线|