1. List command used
command | Effect |
---|---|
lPush | Insert one or more values into the list header |
rpoplpush | Pops up the last value of the list, inserts it into the header of another list, and returns the value |
lRem | Delete the given value in the list |
lIndex | Get values in the list by index |
2. Composition of the queue
Name | Duty |
---|---|
Producer | Publish news |
Consumer | Get and process messages |
monitor | Listen to the timeout message, pop it back to the original message queue, and ensure that the message can be processed by other consumers after the consumer hangs up or fails to process |
3.php implementation code
Producer.php
<?php /** * Created by PhpStorm. * User: jmsite.cn * Date: 2019/1/26 * Time: 0:13 */ try { //Declare the key name of message queue list $queueKey = 'testQueueKey'; $redis = new Redis(); $redis->connect('192.168.75.132', 6379); //Push 10 messages to the list for ($i = 0;$i < 10;$i++){ //Generate a unique ID for the message $uniqid = uniqid(mt_rand(10000, 99999).getmypid().memory_get_usage(), true); $ret = $redis->lPush($queueKey, json_encode(array('uniqid' => $uniqid, 'key' => 'key-'.$i, 'value' => 'data'))); var_dump($ret); } } catch (Exception $e){ echo $e->getMessage(); }
Consumer.php
<?php /** * Created by PhpStorm. * User: jmsite.cn * Date: 2019/1/26 * Time: 0:14 */ try { //Declare the key name of message queue list $queueKey = 'testQueueKey'; //Declare the key name of listener queue list $watchQueueKey = 'watchQueueKey'; $redis = new Redis(); $redis->connect('192.168.75.132', 6379); //Queue first in first out, pop up the first joined message, and put it into the listening queue at the same time while (true){ $ret = $redis->rpoplpush($queueKey, $watchQueueKey); if ($ret === false){ sleep(1); } else { $retArray = json_decode($ret, true); //Write unique id to cache to set validity period $redis->setex($retArray['uniqid'], 60, 0); //Simulation failure $rand = mt_rand(0,9); if ($rand < 3){ echo "failure:".$ret."\n"; } else { //todo //Process successfully removed message $redis->lRem($watchQueueKey, $ret, 0); echo "success:".$ret."\n"; } } } } catch (Exception $e){ echo $e->getMessage(); }
Listener Watcher.php
<?php /** * Created by PhpStorm. * User: jmsite.cn * Date: 2019/1/26 * Time: 0:15 */ try { //Declare the key name of message queue list $queueKey = 'testQueueKey'; //Declare the key name of listener queue list $watchQueueKey = 'watchQueueKey'; $redis = new Redis(); $redis->connect('192.168.75.132', 6379); while (true){ //Take a value at the end of the list $ret = $redis->lIndex($watchQueueKey, -1); //Sleep for 1 second if not present if ($ret === false){ sleep(1); } else { $retArray = json_decode($ret, true); $idCache = $redis->get($retArray['uniqid']); if ($idCache === false){ //If it has expired, it means that the task has timed out and the original queue is bounced back $redis->rpoplpush($watchQueueKey, $queueKey); echo "rpoplpush:".$ret."\n"; } else { //Processing, continue to wait sleep(1); } } } } catch (Exception $e){ echo $e->getMessage(); }
4. Execution queue
Turn on listener php Watcher.php
Open consumer php Consumer.php
Execution producer PHP producer.php
Producer output
int(1) int(2) int(3) int(4) int(5) int(6) int(7) int(8) int(9) int(10)
Monitor output
rpoplpush:{"uniqid":"28580267323642245c4bde640dd8f3.30292468","key":"key-1","value":"data"} rpoplpush:{"uniqid":"10258267323642245c4bde640e1cd9.95656605","key":"key-4","value":"data"} rpoplpush:{"uniqid":"43356267323642245c4bde640e88e9.50566706","key":"key-5","value":"data"} rpoplpush:{"uniqid":"59823267323642245c4bde640e98b5.51512314","key":"key-6","value":"data"} rpoplpush:{"uniqid":"83293267323642245c4bde640ed753.04622366","key":"key-9","value":"data"} rpoplpush:{"uniqid":"59823267323642245c4bde640e98b5.51512314","key":"key-6","value":"data"}
Consumer output
success:{"uniqid":"47280267323557445c4bde640dbfb4.78962728","key":"key-0","value":"data"} failure:{"uniqid":"28580267323642245c4bde640dd8f3.30292468","key":"key-1","value":"data"} success:{"uniqid":"39394267323642245c4bde640de992.34641654","key":"key-2","value":"data"} success:{"uniqid":"41335267323642245c4bde640df980.38466514","key":"key-3","value":"data"} failure:{"uniqid":"10258267323642245c4bde640e1cd9.95656605","key":"key-4","value":"data"} failure:{"uniqid":"43356267323642245c4bde640e88e9.50566706","key":"key-5","value":"data"} failure:{"uniqid":"59823267323642245c4bde640e98b5.51512314","key":"key-6","value":"data"} success:{"uniqid":"43817267323642245c4bde640ec189.44008738","key":"key-7","value":"data"} success:{"uniqid":"69276267323642245c4bde640ecb91.04877522","key":"key-8","value":"data"} failure:{"uniqid":"83293267323642245c4bde640ed753.04622366","key":"key-9","value":"data"} success:{"uniqid":"28580267323642245c4bde640dd8f3.30292468","key":"key-1","value":"data"} success:{"uniqid":"10258267323642245c4bde640e1cd9.95656605","key":"key-4","value":"data"} success:{"uniqid":"43356267323642245c4bde640e88e9.50566706","key":"key-5","value":"data"} failure:{"uniqid":"59823267323642245c4bde640e98b5.51512314","key":"key-6","value":"data"} success:{"uniqid":"83293267323642245c4bde640ed753.04622366","key":"key-9","value":"data"} success:{"uniqid":"59823267323642245c4bde640e98b5.51512314","key":"key-6","value":"data"}
We see that the message that the consumer failed in the first execution is bounced back to the message queue after the timeout. The consumer has the opportunity to execute again. The responsibility of the listener is to ensure that the message can bounce back to the original queue and be executed again after the consumer fails or hangs up
Original address: https://www.jmsite.cn/blog-615.html