訊息佇列在是分布式系統中必不可少的中介軟體,目前在生產環境,使用較多的訊息佇列有activemq,rabbitmq,kafka,rocketmq等。然而對於乙個要求不高的小型系統來說,單獨使用維護這些佇列系統代價有點大。而redis可以在做快取的同時也滿足佇列的需求。redis的list是有序的列表,加上其出隊入隊函式,利用其特性很簡單的就能實現乙個訊息佇列。
一、業務層郵件入佇列
入佇列使用redis的lpush指令
lpush key value1 [value2]
將乙個或多個值插入到列表頭部
先將郵件詳情寫入mysql儲存,再將該郵件id push到redis佇列頭部
function sendsysmail($userid, $type, $content)
else
}二、後台佇列監聽
後台執行乙個php程序,監聽佇列,對佇列迴圈進行出佇列操作。一旦佇列有資料,就從mysql中取對應的郵件詳細情況進行傳送。
出隊操作使用brpop命令
brpop key1 [key2 ] timeout
移出並獲取列表的最後乙個元素,
如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。
使用過程中發生了件奇怪的事情,後台程序開啟後開始執行的好好的,並沒有什麼異常,但跑了一晚上,第二天再來看時便不正常了。
看了下redis的資料,都正常的出入佇列了,但是郵件並未傳送,日誌中也沒有傳送失敗的記錄。
一番折騰,發現是mysql連線這塊存在問題,mysql預設的連線超時時間是28800秒,即8小時,超過8小時,mysql連線就斷開了,過了一晚上,mysql自然就go away了。
於是在沒有佇列沒有資料的時候執行select 1來延長mysql連線的超時時間點,select 1執行異常時重新建立乙個mysql的連線替換之前的連線,以此來保持mysql的連線始終可用。
<?php
$config = include('config.php');
$redis = new redis();
$redis->connect($config['redis_host'], $config['redis_port']);
$pdo= new pdo($config['dsn'], $config['db_user'], $config['db_pwd'], array(pdo::attr_errmode => pdo::errmode_exception));
while (true)";
$res = $pdo->query($sql);
foreach ($res as $row)
else
}}else
catch (pdoexception $e) }
}?>
三、佇列監聽程式的守護程序
用shell寫的守護程序,方便佇列監聽程式的開啟關閉以及狀態檢視
#!/bin/bash#開啟
function start()
'`if [ "$pid" == "" ]
then
php -f mailqueue.php >> maillog &
echo "程式啟動成功"
else
echo "程式已經開啟過"fi}
#關閉function stop()
'`if [ "$pid" == "" ]
then
echo "程式未開啟"
else
kill -9 $pid
echo "程式關閉成功"fi}
#檢視開啟狀態
function status()
'`if [ "$pid" == "" ]
then
echo "程式未開啟"
else
echo "程式執行中,pid: $pid"fi}
#主程式
case "$1" in
"start")
start
;;"stop" )
stop
;;* )
echo "引數錯誤! usage: mailqueue [start|stop|status]";;
esac
四、執行演示
1.使用守護程序指令碼啟動佇列後台監聽程序
2.資料庫中新增一條測試資料
3.redis手動入隊資料,模擬業務入隊
4.檢視郵件傳送日誌
五、總結
這是乙個很簡單的訊息佇列程式,實現了訊息佇列最基本的功能。但要想穩定執行還有很多需要優化處理的地方。
1.程式只考慮了最簡單的狀況,對於郵件傳送失敗的情況只是打了日誌,並未做任何處理。可以在資料庫郵件詳情表增加記錄郵件傳送失敗次數的字段。郵件傳送失敗後,累加記錄失敗次數,設定乙個最大失敗次數,小於最大失敗次數則重新入佇列,再次傳送。直到達到最大失敗次數之後不再傳送,以此來提高郵件的傳送成功率。
2.重新啟動後資料的恢復,redis本身有完善資料備份機制,這點可以通過redis本身機制來實現。
AspectJ基於xml和基於註解
一 基於xml 執行的切入點中具體方法有返回值,則方法結束會立即執行後置通知,然後再執行環繞通知的放行之後的 2 連線點即所有可能的方法,切入點是正真被切的方法,連線點方法名 其中,只有環繞通知的切入點引數不一樣,是可以放行的切入點 3 異常通知是處理異常 切面類中的異常通知的方法引數列表中異常引數...
拓撲排序(基於dfs 基於佇列)
dfs函式的返回值表示是否成環,若存在有向環,則不存在拓撲排序。不包含有向環的有向圖稱為有向無環圖 dag 可以借助dfs完成拓撲排序,在訪問完乙個結點時把他加入當前拓撲序的首部。舉個栗子 比如乙個 1,2 1,3 2,3 的有向無環圖,就先搜尋1,再遞迴搜尋2,再搜尋3,3沒有出度了,於是放進拓撲...
基於insert update delete的注入
inset注入原理 所謂inset注入就是指我們前端註冊的資訊會被後台通過insert操作插入到資料庫裡邊去,若此時後台沒有做出相應的處理就會構成insert注入。insert注入方法 insert用法例如 insert into member username,pw,phonenum,email,...