PHP可以用 GO也可以用这个不限制
队列使用场景,大量用户信息推送,大量祝福短信发送等
核心技术点 Redis的lpush brpop
- lpush 负责向key中写入数据
- brpop 阻塞模式获取key中的值从而实现业务
模拟实例。向用户发送短信
PHP版代码2.0
生成者
* Date: 2019-12-02
* Time: 11:11
*/
ini_set('default_socket_timeout', -1); //不超时
// 声明对象
$redis = new \Redis();
// 连接Redis
$r = $redis->connect('127.0.0.1', 6379);
// 选择Redis DB
$redis->select(4);
// 声明SMS队列的key
$key = 'SMS_QUEUE';
//写入数据
for ($i = 0; $i < 10; $i++) {
// 获取随机手机号 // 有的时候不同用户文本内容不一样 最好可以分开设置。注意key名可以根据情况更改
$json = json_encode(["mobile"=>randomPhoneNumber(),"msg"=>"【滴滴答】尊敬的用户您好!祝您新年快乐!"]);
// 左入队列
$redis->lPush($key, $json);
echo 'yes:' . $i . PHP_EOL;
}
function randomPhoneNumber()
{
// 手机号头
$header = ["133", "149", "153", "173", "177",
"180", "181", "189", "199", "130", "131", "132",
"145", "155", "156", "166", "171", "175", "176",
"185", "186", "166", "134", "135", "136", "137",
"138", "139", "147", "150", "151", "152", "157",
"158", "159", "172", "178", "182", "183", "184",
"187", "188", "198", "170", "171"];
$count = count($header);
$header_value = rand(0, $count - 1);
return $header[$header_value] . '****' . rand(1000, 9999);
}
消费者
* Date: 2019-12-02
* Time: 10:58
*/
ini_set('default_socket_timeout', -1); //不超时
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
$redis->select(4);//切换到db4
$redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
While ($key_arr = $redis->brpop('SMS_QUEUE', 0)) {
try{
// key_arr 是一个数组 0 表示key名称 SMS_QUEUE ,1 表示获取到的值
usleep(100000);
$json = $key_arr[1];
//解析json
$json_arr = json_decode($json,true);
if(is_array($json_arr) && count($json_arr)==2){
if(!sms($json_arr["mobile"], $json_arr["msg"])){
throw new Exception("发送失败");
}
}else{
throw new Exception("解析失败");
}
}catch (Exception $e){
// 左入队列
$redis->lPush("SMS_QUEUE", $json);
}
}
// 发送短信函数
function sms($mobile, $msg)
{
echo '用户手机号:' . $mobile . ',信息:' . $msg . ' 发送成功!' . PHP_EOL;
return true;
}
PHP版代码1.0
生产者
* Date: 2019-12-02
* Time: 11:11
*/
ini_set('default_socket_timeout', -1); //不超时
// 声明对象
$redis = new \Redis();
// 连接Redis
$r = $redis->connect('127.0.0.1', 6379);
// 选择Redis DB
$redis->select(4);
// 声明SMS队列的key
$key = 'SMS_QUEUE';
//写入数据
for ($i = 0; $i < 10; $i++) {
// 获取随机手机号
$m = randomPhoneNumber();
// 左入队列
$redis->lPush($key, $m);
// 有的时候不同用户文本内容不一样 最好可以分开设置。注意key名可以根据情况更改
$redis->set($m, '【滴滴答】尊敬的用户您好!祝您新年快乐!');
echo 'yes:' . $i . PHP_EOL;
}
function randomPhoneNumber()
{
// 手机号头
$header = ["133", "149", "153", "173", "177",
"180", "181", "189", "199", "130", "131", "132",
"145", "155", "156", "166", "171", "175", "176",
"185", "186", "166", "134", "135", "136", "137",
"138", "139", "147", "150", "151", "152", "157",
"158", "159", "172", "178", "182", "183", "184",
"187", "188", "198", "170", "171"];
$count = count($header);
$header_value = rand(0, $count - 1);
return $header[$header_value] . '****' . rand(1000, 9999);
}
消费者
* Date: 2019-12-02
* Time: 10:58
*/
ini_set('default_socket_timeout', -1); //不超时
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
$redis->select(4);//切换到db3
$redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
While ($key_arr = $redis->brpop('SMS_QUEUE', 0)) {
// key_arr 是一个数组 0 表示key名称 SMS_QUEUE ,1 表示获取到的值
usleep(100000);
$key = $key_arr[1];
if ($msg = $redis->get($key)) {
sms($key, $msg);
$redis->del(key());
}
}
// 发送短信函数
function sms($mobile, $msg)
{
echo '用户手机号:' . $mobile . ',信息:' . $msg . ' 发送成功!' . PHP_EOL;
}
守护进程可以用nohup创建,给消费者创建守护进程
作者写的corntab supervisor对比
进程关闭后重启
?疑问-如果lpush很多手机号该怎么办呢?
swoole多线程