PHP memcache リング キュー クラス。私は初心者で、ビジネス上のニーズがあるため、データ構造についてあまり学習していません。 プロトタイプは、oschina の lusi によって共有されている PHP memcache キュー コードです。 int の長さが境界を越えるリスクがなく、いつでもキューに出入りできるようにするため (シングルチェーンが Head 自動インクリメントを採用している場合、処理せずに境界を越える可能性があります)、単に循環キューに書き換えられるだけです。まだバグがあるかもしれません、ごめんなさい!
- /**
- * PHP memcache リング キュー クラス
- * オリジナル作成者 LKK/lianq.net
- * FoxHunter を修正
- * ビジネス上のニーズにより、キュー内のポップとプッシュのみが保持されます 有効期限を 0 に変更します。これは永続的です
- */
- class MQueue
- {
- public static $client;
-
- private $expire //有効期限、秒、1~2592000、つまり以内30 日
- private $sleepTime; // ロック解除までの待ち時間、マイクロ秒
- private $queueName; // キュー名、一意の値
- private $retryNum; // 試行回数
- private $MAXNUM; 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 の場合、インスタンス化するときは、コンストラクターのパラメーター値が一貫していることを確認する必要があります。そうでないと、ポップとプッシュによってキューの順序が混乱します
- */
- 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) ) || 空($this->TAIL))
- $this->TAIL = 0;
- if (!isset($this->LEN) || 空($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 アトミック ロックを使用します
- プライベート関数 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 $this- >LEN = 0; //境界値の修正
- }
- ;
- memcache_set(self::$client, $this->queueName . self::HEAD_KEY, $this->HEAD, false, $this->期限切れ); //更新
- 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++ //ヘッドの移動はPushによって引き起こされるので、量の増加に相当します
- if ($ this->LEN >= $this->MAXNUM ) {
- $this->LEN = $this->MAXNUM; //境界値の長さの修正
- }
- ;
- memcache_set(self::$client, $this->queueName . self::TAIL_KEY, $this ->TAIL, false, $this->expire); //Update
- memcache_set(self::$client, $this->queueName . self: :LENGTH_KEY, $this->LEN, false, $this ->expire); //Update
- }
-
-
- //ロック解除
- プライベート関数 unLock()
- {
- memcache_delete(self::$client, $this ->queueName . self::LOCK_KEY);
- $this ->access = false;
- }
-
- //キューがいっぱいかどうかを判断する
- public function isFull()
- {
- //外部から直接呼び出された場合、ロックがないため、ここでの値は近似値であり、あまり正確ではありませんが、その前にロックがあるため、内部呼び出しは信頼できます
- if ($this->canRewrite)
- return false;
- return。 $this->LEN == $this->MAXNUM ? true : false;
- }
-
- //空かどうかを判定
- public function isEmpty()
- {
- //外部から直接呼び出された場合は、ただし、内部呼び出しの前にロックがあるため、Trusted
- return $this->LEN == 0 true : false;
- }
-
- public function getLen()
- {
- //外部から直接呼び出された場合、ロックがないため、ここでの値は近似値であり、あまり正確ではありませんが、内部呼び出しでは前にロックがあるため、は信頼できます
- return $this->LEN;
- }
-
- /*
- * Push value
- * @param 混合値
- * @return bool
- */
- public function Push($data = '')
- {
-
- $result = false;
- if (empty($data))
- return $result;
-
- if (!$this->gt;lock()) {
- return $result;
- }
-
- $this->getHeadAndTail( ); //最新のポインター情報を取得します
-
- if ($this->isFull()) { //完全な概念は非上書き下でのみ使用可能です
- $ this->unLock();
- return false;
- }
-
- if (memcache_set(self::$client, $this->queueName . self::VALU_KEY . $this->TAIL, $data, MEMCACHE_COMPRESSED, $this->expire)) {
- //After押すと、尾部と頭が重なっていることがわかり(ポインタはまだ移動していません)、右側にまだヘッドが読み取っていないデータがあるため、尾部を避けるためにヘッドポインタを移動します ポインタがヘッドにまたがっています
- if ($this->TAIL == $this->HEAD && $this->LEN >= 1) {
- $this->incrHead();
- }
- $this->gt ;incrTail( ); //末尾ポインタを移動します
- $result = true;
- }
-
- $this->unLock();
- return $result;
- }
-
-
- /*
- * 値をポップします
- * @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->gt;popKeyArray($length);
- $this->unLock();
- return $data;
- }
-
-
- /*
- * 特定の長さの値をポップします
- * @param [length] int queue length
- * @return array
- */
- private function PopKeyArray($length)
- {
-
- $result = array() ;
- if (empty($length))
- return $result;
- for ($k = 0; $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) ;
- //値を抽出した後、先頭と末尾が重なっていることがわかり(この時点ではポインタは移動していません)、右側にはデータがありません。つまり、キューの最後のデータは完全に空です。このとき、ポインタはローカルに留まり、移動しません。 if ($this->TAIL == $this->HEAD && $this->LEN $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
- */
- プライベート関数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 $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;
- }
-
-
- }
-
コードをコピー
|