PHP守护进程利用Redis队列实现业务

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多线程

PHP守护进程利用Redis队列实现业务_第1张图片

你可能感兴趣的:(队列,php,redis)