PHP消息隊列實現及應用:隊列處理訂單系統和配送系統

解耦案列:隊列處理 訂單系統和配送系統

我們在前面瞭解過消息隊列的使用場景: 
http://blog.csdn.net/github_26672553/article/details/78194336

這裏,我們要來處理其中一個場景:系統的解耦。

在電商項目中,當客戶提交了一個訂單之後,客戶在個人中心可以看到訂單處於配送中。 
這個時候就要參與進來一個系統,叫做『配送系統』。如果我們在做架構的時候,把訂單系統配送系統設計在一起的話就會出現一些問題:訂單系統的壓力比較大,但是配送系統沒有必要對這些壓力做及時的反應;我們不需要訂單系統出現故障之後導致配送系統故障。

所以我們需要把這2個系統分開,通過一箇中間的隊列表來實現這2個系統的溝通。

如下圖架構: 

具體到我們的程序代碼大致邏輯如下圖:

 

 

大致流程:order.php來接收用戶訂單,生成訂單號並對訂單進行處理(訂單系統);在訂單系統會把配送系統所需要的數據放入隊列表中;我們的配送系統goods.php會有個定時腳本每分鐘執行一次,處理隊列表中的數據。

簡單設計隊列表order_queue

CREATE TABLE `order_queue` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` int(11) unsigned NOT NULL COMMENT '訂單ID(從訂單系統來的)',
  `user_info` varchar(255) NOT NULL DEFAULT '' COMMENT '可以是用戶手機號/用戶id等(這裏只是演示)',
  `created_at` datetime NOT NULL COMMENT '訂單創建時間',
  `updated_at` datetime NOT NULL COMMENT '本記錄最後處理完成時間',
  `status` tinyint(2) NOT NULL COMMENT '0未處理,1已處理,2處理中',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

mysql訂單隊列

前面我們已經分析清楚了邏輯,剩下的就是代碼實現了。 
注意:我這裏只是演示代碼,單純爲了展示實現過程。

1、接收訂單,處理訂單order.php

<?php
// 這個文件是用來接收用戶的訂單信息 並寫入隊列的一個文件

if(!empty($_GET['user_info'])){
    // 驗證 過濾 接收的數據 
    // todo...

    // 這裏是應該首先是訂單中心的處理流程
    // 因爲訂單系統是一套單獨的系統 這裏就不編寫這個系統了
    // todo... 

    $order_id = rand(100000,99999); // 正常的訂單號從 訂單系統來,我們這裏只是演示

    // 把配送系統需要的訂單數據存入隊列表中
    $insert_data = array(
        'order_id'=>$order_id,
        'user_info'=>$_GET['user_info'],
        'created_at'=>date('Y-m-d H:i:s',time()),
        'status'=>0
    );
    // 把上面的數據 插入到order_queue表中
    // insert into order_queue
}

2、配送系統goods.php

<?php
// 這個文件主要是配送系統處理隊列表中的訂單並進行標記的文件

//分析:
//第一步:先把要處理的記錄更新爲『等待處理』
//第二步:選擇剛剛標記爲『等待處理』的記錄,然後進行配送系統的處理
//第三步:把上面前面處理過的程序標記『已完成』

/////////////////////這裏很重要,你一定要明白哦//////////////////////////////////////////////
//疑問:爲什麼不直接處理最後更新爲『已完成』,多了先標記爲『等待處理』?
//這是因爲配送系統很可能不是及時完成的,它中間會有一段處理的時間,如果還在處理中有其他程序來進行讀取和操作,就衝突了。
//這樣設計其實也是一個鎖的機制

//1、
$waiting = array('status'=>0);
$lock = array('status'=>2);
//把狀態爲0的記錄標記爲2,每次更新3條(具體每次幾條看情況)
$sql = "update order_queue set status=2 where status=0 limit 3";

//2、
if(上面update成功){
    // 選擇出要處理訂單內容
    // select * from order_queue where status = 2;

    // 然後由配貨系統進行處理
    // todo...

    //3、處理完成把訂單狀態更新爲已完成
    $success = array(
        'status'=>1,
        'updated_at'=>date('Y-m-d H:i:s',time())
    );

}else{
    echo 'All Finished';
}

3、linux服務器 定時任務

寫個shell腳本:goods.sh

#!/bin/bash

date "+%G-%m-%d %H:%M:%S"
cd /var/www/
php goods.php

這個腳本就是去執行orders.php這個程序的。

在linux服務器部署定時任務

crontab -e
*/1 * * * * /var/www/goods.sh >> /var/www/goods_shell.log 2>$1

每分鐘執行一次goods.sh文件,並記錄日誌到goods_shell.log文件(在對應目錄新建該文件)
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章