1

应用场景

https://www.imooc.com/video/15163

冗余:延迟处理、保障完成
解耦:出入解耦
流量消峰:redis缓存
异步通信:异步场景
方便扩展:解耦的结果
排序保证:顺序处理

1、mysql加锁队列

-- 订单系统【生产方】 --
接收订单,核心代码:

    //把订单信息保存到订单表中
    $db = DB::getIntance();
    $res = $db->insert("order_queue", $insert_data);

-- 配送系统【消费方】 --
定时发货,核心代码:

    //1. 中间态:锁定处理中数据
    $waiting = ['status'=>0];
    $lock = ['status'=>1];
    $lock_res = $db->update('order_queue',$lock,$waiting,2); //每次刷新新处理2条

    if ($lock_res){
        //2. 对这些处理中数据进行配货
        $res = $db->selectAll('order_queue',$lock);
        //配货代码...

        //3. 修改订单状态为已完成
        $success = [
            'update_time' => date('Y-m-d H:i:s'),
            'status'=>2
        ];
        $res_last = $db->update("order_queue", $success,$lock);
        if($res_last){
            echo 'Success: '.$res_last;
        }else{
            echo 'Failed';
        }
    }

2、redis秒杀队列

秒杀场景下的流量消峰:
【生产方】

    if ($redis->lLen($redis_name) < $num) {
        $redis->rPush($redis_name, $uid . '%' . microtime());
        echo '秒杀成功' . $uid;
    } else {
        echo '秒杀已结束.';
    }

【消费方】

    sleep(2);
    $user = $redis->lPop($redis_name);
    if(!$user || $user=='nil'){ //为空判断
        continue;
    }else{
        $user_arr = explode('%', $user);
        $insert_data = [
            'uid' => $user_arr[0],
            'rtime' => date('Y-m-d H:i:s'),
            'req_time' => $user_arr[1]
        ];
        echo '-';
        $res = $db->insert('redis_queue',$insert_data); //数据库写入成功判断
        if(!$res){
            $redis->rPush($redis_name, $user);
        }
    }

3、rabbitmq应用解耦

可用于解耦、方便扩展
php-amqplib/php-amqplib: demo//publish.php、consumer.php
用法直接参考demo:

$exchange = 'router';
$queue = 'msgs';

$connection = new AMQPStreamConnection(HOST, PORT, USER, PASS, VHOST);
$channel = $connection->channel();

$channel->queue_declare($queue, false, true, false, false);

$channel->exchange_declare($exchange, AMQPExchangeType::DIRECT, false, true, false);

$channel->queue_bind($queue, $exchange);

$messageBody = implode(' ', array_slice($argv, 1));
$message = new AMQPMessage($messageBody, array('content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
$channel->basic_publish($message, $exchange);

$channel->close();
$connection->close();

结尾:代码同步

# 本机搭建
git clone https://github.com/cffycls/cluster.git /home/wwwroot
docker run --name rbt -p 5672:5672 \
    --network mybridge --ip=172.1.12.15 \
    -v /home/wwwroot/cluster/rabbitmq/rabbitmq.conf \
    -v /home/wwwroot/cluster/rabbitmq/data:/var/lib/rabbitmq/mnesia \
    -e RABBITMQ_ERLANG_COOKIE='123456' \
    -e RABBITMQ_DEFAULT_USER=root -e RABBITMQ_DEFAULT_PASS=123456 \
    -d rabbitmq

实例及数据库代码上传:
https://github.com/cffycls/msg_que


沧浪水
97 声望12 粉丝