> 백엔드 개발 > PHP 튜토리얼 > PHP로 구현된 memcached 대기열 클래스

PHP로 구현된 memcached 대기열 클래스

WBOY
풀어 주다: 2016-07-25 08:43:27
원래의
898명이 탐색했습니다.
  1. /*
  2. * memcache 대기열 클래스
  3. * 여러 프로세스에 의한 동시 쓰기 및 읽기 지원
  4. * 쓰는 동안 읽기, AB 문자 회전 교체
  5. * @author guoyu
  6. * @create on 9:25 2014-9-28
  7. * @qq 기술산업 교류회 : 136112330
  8. *
  9. * @예:
  10. * $obj = new memcacheQueue('duilie');
  11. * $obj->add('1asdf')
  12. * $obj->getQueueLength(); read(11); * $obj->get(8);
  13. */
  14. class memcacheQueue{
  15. public static $client
  16. public $access; //큐 업데이트 가능 여부
  17. private $currentSide; //현재 회전의 큐 쪽: A/B
  18. private $lastSide; //이전 회전의 큐 쪽: A/ B
  19. private $sideAHead; //A측의 첫 번째 값
  20. private $sideATail; //A측의 마지막 값
  21. private $sideBHead; //B측의 첫 번째 값
  22. private $sideBTail; // B팀의 마지막 값
  23. private $currentHead; //현재 팀의 첫 번째 값
  24. private $currentTail; //현재 팀의 마지막 값
  25. private $lastHead; > private $ lastTail; //팀의 마지막 라운드의 꼬리 값
  26. private $expire; //만료 시간, 초, 1~2592000, 즉 30일 이내에는 만료되지 않음을 의미합니다.
  27. private $ sleepTime; //잠금 해제 대기 시간, 마이크로초
  28. private $queueName; //큐 이름, 고유 값
  29. private $retryNum; //재시도 횟수, = 10 * 이론적인 동시성 수
  30. const MAXNUM = 2000; //(단면) 최대 대기열 수, 권장 상한은 10K입니다.
  31. const HEAD_KEY = '_lkkQueueHead_' // 대기열 헤드 키
  32. const TAIL_KEY = '_lkkQueueTail_' // 대기열 꼬리 키
  33. const VALU_KEY = '_lkkQueueValu_'; // 대기열 값 키
  34. const LOCK_KEY = '_lkkQueueLock_' // 대기열 잠금 키
  35. const SIDE_KEY = '_lkkQueueSide_' // 회전 표면 키
  36. /*
  37. * 생성자
  38. * @param [config] 배열 memcache 서버 매개변수
  39. * @param [queueName] 문자열 대기열 이름
  40. * @param [expire] 문자열 만료 시간
  41. * @return NULL
  42. */
  43. 공용 함수 __construct($queueName ='',$expire='',$config =''){
  44. if(empty($config)){
  45. self::$client = memcache_pconnect('localhost',11211 );
  46. }elseif(is_array($config)){//array('host'=>'127.0.0.1','port'=> ;'11211')
  47. self::$client = memcache_pconnect($config['host'],$config['port'])
  48. }elseif(is_string($config)){//"127.0 .0.1:11211"
  49. $tmp = 폭발(' :',$config);
  50. $conf['host'] = isset($tmp[0]) ? $tmp[0] : '127.0. 0.1';
  51. $conf['port'] = isset($tmp[1]) ? $tmp[1] : '11211'
  52. self::$client($conf['host') ],$conf['port']);
  53. }
  54. if(!self::$client) return false
  55. ignore_user_abort(TRUE);//클라이언트 연결이 끊어지면 실행을 허용합니다. 계속
  56. set_time_limit(0);//스크립트 실행 지연 상한
  57. $this->access = false
  58. $this->sleepTime = 1000; = (비어 있음($expire) && $expire!=0) ? 3600 : (int)$expire;
  59. $this->expire = $expire; 🎜> $this->retryNum = 10000;
  60. $side = memcache_add(self::$client, $queueName . self::SIDE_KEY, 'A',false, $expire)
  61. $ this->getHeadNTail($queueName);
  62. if (!isset($this->sideAHead) || 비어 있음($this->sideAHead)) $this->sideAHead = 0; (!isset($this->sideATail) || 비어 있음 ($this->sideATail)) $this->sideATail = 0
  63. if(!isset($this->sideBHead) || 비어 있음 ($this->sideBHead)) $this-> sideBHead = 0
  64. if(!isset($this->sideBHead) || 비어 있음($this->sideBHead)) $this-> sideBHead = 0
  65. }
  66. /*
  67. * 获取队列首尾值
  68. * @param [queueName] string 队列name称
  69. * @return NULL
  70. */
  71. 비공개 함수 getHeadNTail($queueName) {
  72. $this->sideAHead = (int)memcache_get(self::$client, $queueName.'A'.self::HEAD_KEY);
  73. $this->sideATail = (int)memcache_get(self::$client, $queueName.'A'.self::TAIL_KEY);
  74. $this->sideBHead = (int)memcache_get(self::$client, $queueName.'B'.self::HEAD_KEY);
  75. $this->sideBTail = (int)memcache_get(self::$client, $queueName.'B'.self::TAIL_KEY);
  76. }
  77. /*
  78. * 获取当前轮值的队列면
  79. * @return string 队列면명称
  80. */
  81. 공용 함수 getCurrentSide(){
  82. $ currentSide = memcache_get(self::$client, $this->queueName . self::SIDE_KEY);
  83. if($currentSide == 'A'){
  84. $this->currentSide = 'A';
  85. $this->lastSide = 'B';
  86. $this->currentHead = $this->sideAHead;
  87. $this->currentTail = $this->sideATail;
  88. $this->lastHead = $this->sideBHead;
  89. $this->lastTail = $this->sideBTail;
  90. }else{
  91. $this->currentSide = 'B';
  92. $this->lastSide = 'A';
  93. $this->currentHead = $this->sideBHead;
  94. $this->currentTail = $this->sideBTail;
  95. $this->lastHead = $this->sideAHead;
  96. $this->lastTail = $this->sideATail;
  97. }
  98. return $this->currentSide;
  99. }
  100. /*
  101. * 队列加锁
  102. * @return boolean
  103. */
  104. 비공개 함수 getLock(){
  105. if($this-> access === false){
  106. while(!memcache_add(self::$client, $this->queueName .self::LOCK_KEY, 1, false, $this->expire) ){
  107. usleep ($this->sleepTime);
  108. @$i ;
  109. if($i > $this->retryNum){//尝试等待N次
  110. return false;
  111. 휴식;
  112. }
  113. }
  114. return $this->access = true;
  115. }
  116. false를 반환합니다.
  117. }
  118. /*
  119. * 队列解锁
  120. * @return NULL
  121. */
  122. 비공개 함수 unLock(){
  123. memcache_delete(self::$client, $this->queueName .self::LOCK_KEY);
  124. $this->access = false;
  125. }
  126. /*
  127. * 添加数据
  128. * @param [data] 要存储的值
  129. * @return boolean
  130. */
  131. 공용 함수 add( $data){
  132. $result = false;
  133. if(!$this->getLock()){
  134. return $result;
  135. }
  136. $this->getHeadNTail($this->queueName);
  137. $this->getCurrentSide();
  138. if($this->isFull()){
  139. $this->unLock();
  140. false를 반환합니다.
  141. }
  142. if($this->currentTail < self::MAXNUM){
  143. $value_key = $this->queueName .$this->currentSide . 자기::VALU_KEY . $this->currentTail;
  144. if(memcache_add(self::$client, $value_key, $data, false, $this->expire)){
  145. $this->changeTail();
  146. $결과 = 참;
  147. }
  148. }else{//当前队列已满,更换轮值面
  149. $this->unLock();
  150. $this->changeCurrentSide();
  151. return $this->add($data);
  152. }
  153. $this->unLock();
  154. $결과 반환;
  155. }
  156. /*
  157. * 取出数据
  158. * @param [length] int 数据的长titude
  159. * @return 배열
  160. */
  161. 공용 함수 get( $length=0){
  162. if(!is_numeric($length)) return false;
  163. if(empty($length)) $length = self::MAXNUM * 2;//默认读取所有
  164. if(!$this->getLock()) return false;
  165. if($this->isEmpty()){
  166. $this->unLock();
  167. false를 반환합니다.
  168. }
  169. $keyArray = $this->getKeyArray($length);
  170. $lastKey = $keyArray['lastKey'];
  171. $currentKey = $keyArray['currentKey'];
  172. $keys = $keyArray['keys'];
  173. $this->changeHead($this->lastSide,$lastKey);
  174. $this->changeHead($this->currentSide,$currentKey);
  175. $data = @memcache_get(self::$client, $keys);
  176. foreach($keys as $v){//출지后删除
  177. @memcache_delete(self::$client, $v, 0);
  178. }
  179. $this->unLock();
  180. $data를 반환합니다.
  181. }
  182. /*
  183. * 读取数据
  184. * @param [length] int 数据的长島
  185. * @return 배열
  186. */
  187. 공용 함수 읽기 ($length=0){
  188. if(!is_numeric($length)) return false;
  189. if(empty($length)) $length = self::MAXNUM * 2;//默认读取所有
  190. $keyArray = $this->getKeyArray($length);
  191. $data = @memcache_get(self::$client, $keyArray['keys']);
  192. $data를 반환합니다.
  193. }
  194. /*
  195. * 获取队列某段长島的key数组
  196. * @param [length] int 队列长島
  197. * @return 배열
  198. */
  199. 개인 함수 getKeyArray($length){
  200. $result = array('keys'=>array(),'lastKey'=>array(),'currentKey'=>array());
  201. $this->getHeadNTail($this->queueName);
  202. $this->getCurrentSide();
  203. if(empty($length)) return $result;
  204. //상위 키
  205. $i = $result['lastKey'] = 0;
  206. for($i=0;$i<$length;$i ){
  207. $result['lastKey'] = $this->lastHead $i;
  208. if($result['lastKey'] >= $this->lastTail) break;
  209. $result['keys'][] = $this->queueName .$this->lastSide . 자기::VALU_KEY . $result['lastKey'];
  210. }
  211. //再取当앞면의 키
  212. $j = $length - $i;
  213. $k = $result['currentKey'] = 0;
  214. for($k=0;$k<$j;$k ){
  215. $result['currentKey'] = $this->currentHead $k;
  216. if($result['currentKey'] >= $this->currentTail) break;
  217. $result['keys'][] = $this->queueName .$this->currentSide . 자기::VALU_KEY . $result['현재키'];
  218. }
  219. $result 반환;
  220. }
  221. /*
  222. * 更新当前轮值면队列尾적值
  223. * @return NULL
  224. */
  225. 비공개 함수changeTail(){
  226. $tail_key = $this->queueName .$this->currentSide . 자기::TAIL_KEY;
  227. memcache_add(self::$client, $tail_key, 0,false, $this->expire);//如果没有,则插入;有则false;
  228. //memcache_increment(self::$client, $tail_key, 1);//队列尾 1
  229. $v = memcache_get(self::$client, $tail_key) 1;
  230. memcache_set(self::$client, $tail_key,$v,false,$this->expire);
  231. }
  232. /*
  233. * 更新队列首적值
  234. * @param [side] string 要更新的面
  235. * @param [headValue] int 队列首的值
  236. * @return NULL
  237. */
  238. 비공개 함수changeHead($side,$headValue){
  239. if($headValue < 1) return false;
  240. $head_key = $this->queueName .$side . 자기::HEAD_KEY;
  241. $tail_key = $this->queueName .$side . 자기::TAIL_KEY;
  242. $sideTail = memcache_get(self::$client, $tail_key);
  243. if($headValue < $sideTail){
  244. memcache_set(self::$client, $head_key,$headValue 1,false,$this->expire);
  245. }elseif($headValue >= $sideTail){
  246. $this->resetSide($side);
  247. }
  248. }
  249. /*
  250. * 큼 거대한 화면
  251. * @return NULL
  252. */
  253. 개인 함수 ResetSide($side){
  254. $head_key = $this->queueName .$side . 자기::HEAD_KEY;
  255. $tail_key = $this->queueName .$side . 자기::TAIL_KEY;
  256. memcache_set(self::$client, $head_key,0,false,$this->expire);
  257. memcache_set(self::$client, $tail_key,0,false,$this->expire);
  258. }
  259. /*
  260. * 改变当前轮值队列면
  261. * @return string
  262. */
  263. private functionchangeCurrentSide(){
  264. $currentSide = memcache_get(self::$ 클라이언트, $this->queueName .self::SIDE_KEY);
  265. if($currentSide == 'A'){
  266. memcache_set(self::$client, $this->queueName . self::SIDE_KEY,'B',false,$this->expire) ;
  267. $this->currentSide = 'B';
  268. }else{
  269. memcache_set(self::$client, $this->queueName . self::SIDE_KEY,'A',false,$this->expire);
  270. $this->currentSide = 'A';
  271. }
  272. return $this->currentSide;
  273. }
  274. /*
  275. * 检查当前队列是否已满
  276. * @return boolean
  277. */
  278. public function isFull(){
  279. $result = false ;
  280. if($this->sideATail == self::MAXNUM && $this->sideBTail == self::MAXNUM){
  281. $result = true;
  282. }
  283. $result 반환;
  284. }
  285. /*
  286. * 检查当前队列是否为空
  287. * @return boolean
  288. */
  289. public function isEmpty(){
  290. $result = true ;
  291. if($this->sideATail > 0 || $this->sideBTail > 0){
  292. $result = false;
  293. }
  294. $result 반환;
  295. }
  296. /*
  297. * 获取当前队列적 속도
  298. * 该长島为理论长島,某些元素由于过期失效而丢失,真实속도 小于或等于该长島
  299. * @return int
  300. */
  301. 공용 함수 getQueueLength(){
  302. $this->getHeadNTail($this->queueName);
  303. $this->getCurrentSide();
  304. $sideALength = $this->sideATail - $this->sideAHead;
  305. $sideBLength = $this->sideBTail - $this->sideBHead;
  306. $result = $sideALength $sideBLength;
  307. $result를 반환합니다.
  308. }
  309. /*
  310. * 清空当前队列数据,仅保留HEAD_KEY、TAIL_KEY、SIDE_KEY삼키key
  311. * @return boolean
  312. */
  313. 공개 함수 클리어( ){
  314. if(!$this->getLock()) return false;
  315. for($i=0;$i @memcache_delete(self::$client, $this->queueName.'A'.self::VALU_KEY . $i, 0);
  316. @memcache_delete(self::$client, $this->queueName.'B'.self::VALU_KEY .$i, 0);
  317. }
  318. $this->unLock();
  319. $this->resetSide('A');
  320. $this->resetSide('B');
  321. true를 반환합니다.
  322. }
  323. /*
  324. * 清除所有memcache缓存数据
  325. * @return NULL
  326. */
  327. 공용 함수 memFlush(){
  328. memcache_flush(self:: $클라이언트);
  329. }
  330. }
复제대码

PHP, 멤캐시


원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿