摘要:諸如此類,隊列的應用范圍是如此之廣。方案抽象到更高一層,開發(fā)一套通用異步處理隊列適用于任何復雜的業(yè)務邏輯那么,作為架構(gòu)師,使用隊列的做法,將抽象層和業(yè)務層分離,可具有良好的擴展性和可維護性。
一、隊列使用場景:為什么需要隊列
在web開發(fā)中,我們經(jīng)常會遇到需要處理批量任務的時候,這些批量任務可能是用戶提交的,也可能是當系統(tǒng)被某個事件觸發(fā)時需要進行批量處理的,面對這樣的任務,如果是用戶提交的批量任務,初級程序員只能讓用戶觸發(fā)提交動作后,等待服務器處理完畢,并且將結(jié)果返回到瀏覽器,期間用戶不能關(guān)掉瀏覽器窗口,如果數(shù)據(jù)比較大,或者處理速度比較慢,那用戶體驗將會因此受到直接影響。但是當我們使用某訊或者某浪的郵箱時,點擊群發(fā)郵件之后,只需等待很短的時間,瀏覽器提示提交成功,正在發(fā)送之類的信息時,用戶就可以關(guān)掉瀏覽器,稍后,收件地址欄里的郵箱將陸續(xù)收到該群發(fā)郵件,再比如群發(fā)定時郵件,以及當商城系統(tǒng)中有客戶下單,客戶,客服,倉庫等相關(guān)人員收到訂單郵件信息。諸如此類,隊列的應用范圍是如此之廣。
二 :普通工程師的解決方案和架構(gòu)師的解決方案
方案1:建表存郵件,消息等,用定時程序取出發(fā)送。
方案2:抽象到更高一層,開發(fā)一套通用異步處理隊列適用于任何復雜的業(yè)務邏輯
那么,作為架構(gòu)師,使用隊列的做法,將抽象層和業(yè)務層分離,可具有良好的擴展性和可維護性。相比較而言就高明了許多,下面就我們介紹一下自定義隊列的實現(xiàn)思路和方法。
三 :隊列總體設計
1:需要隊列程序,提供加入隊列接口和取隊列接口等
2:需要存儲隊列,文件或者數(shù)據(jù)庫
3:需要定時程序取出隊列并執(zhí)行
4:其它擴展功能:優(yōu)先級,日志,定時等
代碼的目錄結(jié)構(gòu)如下,每個文件的作用用//注釋來標明
|--addTask.php //添加任務到隊列的例子
|--cronMission.php //定時任務調(diào)度程序,例如linux中受crontab直接調(diào)用的文件,業(yè)務邏輯工程師可以在這個文件中靈活定義自己的隊列任務,從而不用每個隊列任務都需要上服務器修改crontab,從而在安全性,便捷性方面有很大提高
|--db.php //數(shù)據(jù)庫操作
|--db.sql //建立隊列需要用到的基本表結(jié)構(gòu)
|--doQueue.php //執(zhí)行隊列任務
|--Queue.class.php //隊列核心業(yè)務在這里定義,包括將任務加入隊列,讀隊列,更改隊列任務狀態(tài)
|--sendMsg.php //隊列要實現(xiàn)具體任務的業(yè)務接口,比如現(xiàn)有系統(tǒng)的發(fā)送消息的接口,這里例子中因為將此隊列程序和現(xiàn)有系統(tǒng)系統(tǒng)集成,用寫入日志來演示
四 :隊列具體實現(xiàn)一:建任務存儲表
1:
先來個最基本的:
CREATE TABLE`queue` ( id int(11) NOT NULL auto_increment primarykey, taskphp varchar(128) NOT NULL default "", param text not null default "", status tinyint not null default 0, ctime timestamp NOT NULL default CURRENT_TIMESTAMP, KEY (ctime) ) ENGINE=InnoDBDEFAULT CHARSET=utf8;
字段解釋:
taskphp:處理業(yè)務的接口文件
param:處理業(yè)務的接口文件需要接收的參數(shù)
status:任務處理狀態(tài),0為未處理,處理完畢更改為1
五 、隊列具體實現(xiàn)二:定義調(diào)用接口
寫核心類Queue.class.php, 實現(xiàn)基本接口:
1:加入隊列接口
l //$param1 為執(zhí)行任務的程序,$param2 為程序參數(shù),可以為序列化的數(shù)據(jù)
l $cqueue->add($param1,$param2);
2: 讀取隊列接口
l $tasks = $cqueue->getQueueTask($limit = 1000);
3:更新任務狀態(tài)
l $cqueue->updateTaskStatus($id);
4:a2s是自定義的一個數(shù)組轉(zhuǎn)換字符串方法,這里不要使用json_encode,容易出現(xiàn)問題,同樣,從數(shù)據(jù)庫中取出轉(zhuǎn)換為數(shù)組的時候,使用s2a方法
l $re = $cqueue->add("sendMsg.php", Queue::a2s($arr));
4,//發(fā)信息的人的UID * "uids" => array(6,234,34,67,7888,2355), //接收信息的人的UID * "content" => "xxxxx",//信息內(nèi)容 * ); * $cqueue = new Queue(); * $cqueue->add("/app/send_msg.php", serialize($arr)); * */ public function add($taskphp,$param) { $taskphp = mysql_real_escape_string($taskphp); //$param = mysql_real_escape_string($param); $param = $param; $sql = "insert into queue (taskphp, param) values("".$taskphp."", "".$param."")"; $re = execute($sql); if ($re) { $pid = mysql_insert_id(); return $pid; } else { return false; } } /** * 讀取任務隊列 * * @param string $limit 一次取多少條 */ public function getQueueTask($limit = 1000) { $limit = (int)$limit; $sql = "select id, taskphp, param from queue where status = 0 order by id asc"; $re = query($sql); return $re; } /** * 更新任務狀態(tài) * * @param string $limit 一次取多少條 */ public function updateTaskByID($id) { $id = (int)$id; $mtime = time(); $sql = "update queue set status =1, mtime = ".$mtime." where id = ".$id; $re = execute($sql); return $re; } public static function a2s($arr) { $str = ""; foreach ($arr as $key => $value) { if (is_array($value)) { foreach ($value as $value2) { $str .= urlencode($key) . "[]=" . urlencode($value2) . "&"; } } else { $str .= urlencode($key) . "=" . urlencode($value) . "&"; } } return $str; } public static function s2a($str) { $arr = array(); parse_str($str, $arr); return $arr; } } ?>
接下來就是部署調(diào)度了, 這個呢也不是就配置crontab那么簡單,要可維護性,可擴展性好,能多進程并發(fā)執(zhí)行,能監(jiān)控隊列運行狀態(tài)等等,太長了,這個下一篇講。
本內(nèi)容來自本人講的公開課:http://www.ucai.cn/train?f=17
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/20767.html
摘要:可變隊列會對長期沒有更新動態(tài)的那部分不活躍用戶進行減緩速度,減緩對他們微博的獲取頻率,同時加大對活躍用戶的獲取頻率。 注:本文為轉(zhuǎn)載,原文請查看star7th的個人博客。 一、什么是 HTQ 先介紹下基本概念。 我們在編寫程序時,偶爾會遇到需要用到異步隊列的情況。比如說,我發(fā)送一萬封郵件,如果單純使用一個for循環(huán)來發(fā)送,則執(zhí)行時間要很長,要等很久才能發(fā)完,同時很容易導致阻塞、超時等問...
摘要:而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會作為任務隊列掛在當前循環(huán)的末尾執(zhí)行。在下,觀察者基于監(jiān)聽事件的完成情況在下基于多線程創(chuàng)建。 主要問題: 1、JS引擎是單線程,如何完成事件循環(huán)的? 2、定時器函數(shù)為什么計時不準確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點?有什么解決方...
摘要:宏任務和微任務這兩個是指兩個隊列,腳本整體代碼的回調(diào)及渲染都會被加入到隊列中回調(diào)瀏覽器實現(xiàn)回調(diào)都會被加入到隊列。 1. macrotask (宏任務)和 microtask (微任務) 這兩個是指兩個隊列,腳本整體代碼、setTimeout、setInterval、setImmediate、I/O、的回調(diào)及UI渲染都會被加入到 macrotask 隊列中, process.nextTi...
閱讀 1417·2021-11-09 09:45
閱讀 1785·2021-11-04 16:09
閱讀 1449·2021-10-14 09:43
閱讀 1814·2021-09-22 15:24
閱讀 1589·2021-09-07 10:06
閱讀 1597·2019-08-30 14:15
閱讀 980·2019-08-30 12:56
閱讀 1563·2019-08-29 17:22