PHP memcache Ring Queue

Source: Internet
Author: User
PHP memcache Ring Queue class. Novice, did not learn the data structure, because the business needs, so just the bite-bullet simulation! The prototype is the PHP memcache queue code Lusi shared on Oschina. In order to make the queue readily available, and not by the int length cross-border danger (single chain take head self-increment words do not have to deal with the possibility of cross-border), so simply rewrite into a ring queue. There may be bugs, forget forgive!
  1. /**
  2. * PHP Memcache Ring Queue class
  3. * Original Author Lkk/lianq.net
  4. * Modify Foxhunter
  5. * Due to the business need to keep only the pop and push in the queue, the modification expires at 0 that is permanent
  6. */
  7. Class Mqueue
  8. {
  9. public static $client;
  10. Private $expire; Expiration time, seconds, 1~2592000, i.e. within 30 days
  11. Private $sleepTime; Wait for unlock time, microseconds
  12. Private $queueName; Queue name, unique value
  13. Private $retryNum; Number of attempts
  14. Private $MAXNUM; Maximum queue capacity
  15. Private $canRewrite; Whether the switch can be overwritten, the contents of the full out from the beginning overwrite the original data rewrite
  16. Private $HEAD; Next step to enter the pointer position
  17. Private $TAIL; Next step to enter the pointer position
  18. Private $LEN; Queue existing length
  19. Const Lock_key = ' _fox_mq_lock_ '; Lock Storage Indicator
  20. Const Length_key = ' _fox_mq_length_ '; Queue current length storage indication
  21. Const Valu_key = ' _fox_mq_val_ '; Queue key Value Storage indicator
  22. Const Head_key = ' _fox_mq_head_ '; Queue Head pointer position indication
  23. Const Tail_key = ' _fox_mq_tail_ '; Queue tail pointer position indication
  24. /*
  25. * Constructor function
  26. * For the same $queuename, the parameter values of the constructors must be guaranteed to be consistent when instantiated, otherwise the pop and push queue order is chaotic
  27. */
  28. Public function __construct ($queueName = ", $maxqueue = 1, $canRewrite = false, $expire = 0, $config = ')
  29. {
  30. if (empty ($config)) {
  31. Self:: $client = Memcache_pconnect (' 127.0.0.1 ', 11211);
  32. } elseif (Is_array ($config)) {//array (' host ' = ' 127.0.0.1 ', ' port ' = ' 11211 ')
  33. Self:: $client = Memcache_pconnect ($config [' Host '], $config [' Port '];
  34. } elseif (Is_string ($config)) {//"127.0.0.1:11211"
  35. $tmp = Explode (': ', $config);
  36. $conf [' host '] = isset ($tmp [0])? $tmp [0]: ' 127.0.0.1 ';
  37. $conf [' port '] = Isset ($tmp [1])? $tmp [1]: ' 11211 ';
  38. Self:: $client = Memcache_pconnect ($conf [' Host '], $conf [' Port '];
  39. }
  40. if (!self:: $client)
  41. return false;
  42. Ignore_user_abort (TRUE); Allow the client to continue execution when the customer disconnects
  43. Set_time_limit (0); Canceling the script execution delay limit
  44. $this->access = false;
  45. $this->sleeptime = 1000;
  46. $expire = (Empty ($expire))? 0: (int) $expire + 1;
  47. $this->expire = $expire;
  48. $this->queuename = $queueName;
  49. $this->retrynum = 20000;
  50. $this->maxnum = $maxqueue! = null? $maxqueue: 1;
  51. $this->canrewrite = $canRewrite;
  52. $this->getheadandtail ();
  53. if (!isset ($this->head) | | empty ($this->head))
  54. $this->head = 0;
  55. if (!isset ($this->tail) | | empty ($this->tail))
  56. $this->tail = 0;
  57. if (!isset ($this->len) | | empty ($this->len))
  58. $this->len = 0;
  59. }
  60. Get the queue end-to-end pointer information and length
  61. Private Function Getheadandtail ()
  62. {
  63. $this->head = (int) memcache_get (self:: $client, $this->queuename. Self::head_key);
  64. $this->tail = (int) memcache_get (self:: $client, $this->queuename. Self::tail_key);
  65. $this->len = (int) memcache_get (self:: $client, $this->queuename. Self::length_key);
  66. }
  67. The use of Memcache_add atomic lock
  68. Private Function Lock ()
  69. {
  70. if ($this->access = = = False) {
  71. $i = 0;
  72. while (!memcache_add (self:: $client, $this->queuename. Self::lock_key, 1, False, $this->expire)) {
  73. Usleep ($this->sleeptime);
  74. @ $i + +;
  75. if ($i > $this->retrynum) {//try to wait n times
  76. return false;
  77. Break
  78. }
  79. }
  80. return $this->access = true;
  81. }
  82. return false;
  83. }
  84. Update head pointer pointing to next position
  85. Private Function Incrhead ()
  86. {
  87. $this->getheadandtail (); Gets the latest pointer information, since the method body is called within the lock, and the method is called within its lock, the bank notes
  88. $this->head++; The head pointer moves down
  89. if ($this->head >= $this->maxnum) {
  90. $this->head = 0; Boundary value correction
  91. }
  92. ;
  93. $this->len--; The head movement is triggered by the pop, so the amount is reduced
  94. if ($this->len < 0) {
  95. $this->len = 0; Boundary value correction
  96. }
  97. ;
  98. Memcache_set (self:: $client, $this->queuename. Self::head_key, $this->head, False, $this->expire); Update
  99. Memcache_set (self:: $client, $this->queuename. Self::length_key, $this->len, False, $this->expire); Update
  100. }
  101. Update tail pointer pointing to next position
  102. Private Function Incrtail ()
  103. {
  104. $this->getheadandtail (); Gets the latest pointer information, since the method body is called within the lock, and the method is called within its lock, the bank notes
  105. $this->tail++; The trailing pointer moves down
  106. if ($this->tail >= $this->maxnum) {
  107. $this->tail = 0; Boundary value correction
  108. }
  109. ;
  110. $this->len++; The head movement is triggered by push, so the amount is increased
  111. if ($this->len >= $this->maxnum) {
  112. $this->len = $this->maxnum; Boundary Value Length correction
  113. }
  114. ;
  115. Memcache_set (self:: $client, $this->queuename. Self::tail_key, $this->tail, False, $this->expire); Update
  116. Memcache_set (self:: $client, $this->queuename. Self::length_key, $this->len, False, $this->expire); Update
  117. }
  118. Unlock
  119. Private Function UnLock ()
  120. {
  121. Memcache_delete (self:: $client, $this->queuename. Self::lock_key);
  122. $this->access = false;
  123. }
  124. Determine if the queue is full
  125. Public Function Isfull ()
  126. {
  127. External direct call because there is no lock so the value here is a approximate value, not very accurate, but the internal call because in front of the lock, so the trusted
  128. if ($this->canrewrite)
  129. return false;
  130. return $this->len = = $this->maxnum? True:false;
  131. }
  132. Determines whether the empty
  133. Public Function IsEmpty ()
  134. {
  135. External direct call because there is no lock so the value here is a approximate value, not very accurate, but the internal call because in front of the lock, so the trusted
  136. return $this->len = = 0? True:false;
  137. }
  138. Public Function Getlen ()
  139. {
  140. External direct call because there is no lock so the value here is a approximate value, not very accurate, but the internal call because in front of the lock, so the trusted
  141. return $this->len;
  142. }
  143. /*
  144. * Push Value
  145. * @param mixed value
  146. * @return BOOL
  147. */
  148. Public Function push ($data = ")
  149. {
  150. $result = false;
  151. if (empty ($data))
  152. return $result;
  153. if (! $this->lock ()) {
  154. return $result;
  155. }
  156. $this->getheadandtail (); Get the latest pointer information
  157. if ($this->isfull ()) {//The full concept is only available for non-overwrite
  158. $this->unlock ();
  159. return false;
  160. }
  161. if (Memcache_set (self:: $client, $this->queuename. Self::valu_key. $this->tail, $data, memcache_compressed, $ This->expire)) {
  162. When the push is found to coincide with the tail and head (when the pointer has not moved), and there is still data not read by head on the right, move the head pointer to avoid the tail pointer spanning head
  163. if ($this->tail = = $this->head && $this->len >= 1) {
  164. $this->incrhead ();
  165. }
  166. $this->incrtail (); Move tail pointer
  167. $result = true;
  168. }
  169. $this->unlock ();
  170. return $result;
  171. }
  172. /*
  173. * Pop One value
  174. * @param [length] int Queue Length
  175. * @return Array
  176. */
  177. Public Function pop ($length = 0)
  178. {
  179. if (!is_numeric ($length))
  180. return false;
  181. if (! $this->lock ())
  182. return false;
  183. $this->getheadandtail ();
  184. if (empty ($length))
  185. $length = $this->len; Default Read all
  186. if ($this->isempty ()) {
  187. $this->unlock ();
  188. return false;
  189. }
  190. Get fixed after length exceeds queue length
  191. if ($length > $this->len)
  192. $length = $this->len;
  193. $data = $this->popkeyarray ($length);
  194. $this->unlock ();
  195. return $data;
  196. }
  197. /*
  198. * Value of a segment length of pop
  199. * @param [length] int Queue Length
  200. * @return Array
  201. */
  202. Private Function Popkeyarray ($length)
  203. {
  204. $result = Array ();
  205. if (empty ($length))
  206. return $result;
  207. for ($k = 0; $k < $length; $k + +) {
  208. $result [] = @memcache_get (self:: $client, $this->queuename. Self::valu_key. $this->head);
  209. @memcache_delete (self:: $client, $this->queuename. Self::valu_key. $this->head, 0);
  210. When the value is extracted, the head and tail are coincident (when the pointer is not moved), and there is no data on the right, that is, the last data in the queue is completely hollowed out, the pointer stays locally and the queue length becomes 0
  211. if ($this->tail = = $this->head && $this->len <= 1) {
  212. $this->len = 0;
  213. Memcache_set (self:: $client, $this->queuename. Self::length_key, $this->len, False, $this->expire); Update
  214. Break
  215. } else {
  216. $this->incrhead (); Not coincident, or coincident but still have unread data, move the head pointer to the next location to read
  217. }
  218. }
  219. return $result;
  220. }
  221. /*
  222. * Reset Queue
  223. * * @return NULL
  224. */
  225. Private Function Reset ($all = False)
  226. {
  227. if ($all) {
  228. Memcache_delete (self:: $client, $this->queuename. Self::head_key, 0);
  229. Memcache_delete (self:: $client, $this->queuename. Self::tail_key, 0);
  230. Memcache_delete (self:: $client, $this->queuename. Self::length_key, 0);
  231. } else {
  232. $this->head = $this->tail = $this->len = 0;
  233. Memcache_set (self:: $client, $this->queuename. Self::head_key, 0, False, $this->expire);
  234. Memcache_set (self:: $client, $this->queuename. Self::tail_key, 0, False, $this->expire);
  235. Memcache_set (self:: $client, $this->queuename. Self::length_key, 0, False, $this->expire);
  236. }
  237. }
  238. /*
  239. * Clear all Memcache cache data
  240. * @return NULL
  241. */
  242. Public Function Memflush ()
  243. {
  244. Memcache_flush (self:: $client);
  245. }
  246. Public Function Clear ($all = False)
  247. {
  248. if (! $this->lock ())
  249. return false;
  250. $this->getheadandtail ();
  251. $Head = $this->head;
  252. $Length = $this->len;
  253. $curr = 0;
  254. for ($i = 0; $i < $Length; $i + +) {
  255. $curr = $this $Head + $i;
  256. if ($curr >= $this->maxnum) {
  257. $this->head = $curr = 0;
  258. }
  259. @memcache_delete (self:: $client, $this->queuename. Self::valu_key. $curr, 0);
  260. }
  261. $this->unlock ();
  262. $this->reset ($all);
  263. return true;
  264. }
  265. }
Copy Code
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    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.