訂單超時自動關閉的實現方案總結
統一來說,業務有“在一段時間之後,完成一個工作任務”的需求。
實現這種定時任務有哪些方法呢,來總結一下想到的方法。
一、定時輪詢
這是一個比較直接的思路,啟動一個計劃任務,每隔一定時間處理一次,這種處理方式只是適用比較小而簡單的專案。
假設訂單表的結構為:t_order(oid, finish_time, stars, status, …),更具體的,定時任務每隔一個小時會這麼做一次:
select oid from t_order where finish_time > 30minite and status=0;
update t_order set stars=5 and status=1 where oid in[…];
如果資料量很大,需要分頁查詢,分頁update,這將會是一個for迴圈。
定時輪詢的不足:
1、時效性差,會有一定的延遲,這個延遲時間最大就是每隔一定時間的大小,如果你設定每分鐘定時輪詢一次,那麼理論上訂單取消時間的最大誤差就有一分鐘,當然也可能更大,比如一分鐘之內有大量資料,但是一分鐘沒處理完,那麼下一分鐘的就會順延。
2、效率低。
二、被動取消
被動取消的方式很簡單:只有當使用者查詢訂單資訊時,我們再判斷該訂單是否超時,如果超時再進行超時邏輯的處理。
但是這種方式依賴於使用者的查詢操作觸發,這也就是說如果使用者不進行查詢訂單的操作,該訂單就永遠不會被取消。
不足:
1、會產生額外影響
比如統計,訂單數量等產生影響
2、影響使用者體驗
使用者開啟訂單列表可能要處理大量資料,影響顯示的實時性。
三、延時訊息
延時訊息設計與實現
高效延時訊息,包含兩個重要的資料結構:
(1)環形佇列,例如可以建立一個包含3600個slot的環形佇列(本質是個陣列)
(2)任務集合,環上每一個slot是一個Set
同時,啟動一個timer,這個timer每隔1s,在上述環形佇列中移動一格,有一個Current Index指標來標識正在檢測的slot。
Task結構中有兩個很重要的屬性:
(1)Cycle-Num:當Current Index第幾圈掃描到這個Slot時,執行任務
(2)Task-Function:需要執行的任務指標
假設當前Current Index指向第一格,當有延時訊息到達之後,例如希望3610秒之後,觸發一個延時訊息任務,只需:
(1)計算這個Task應該放在哪一個slot,現在指向1,3610秒之後,應該是第11格,所以這個Task應該放在第11個slot的Set中
(2)計算這個Task的Cycle-Num,由於環形佇列是3600格(每秒移動一格,正好1小時),這個任務是3610秒後執行,所以應該繞3610/3600=1圈之後再執行,於是Cycle-Num=1
Current Index不停的移動,每秒移動到一個新slot,這個slot中對應的Set,每個Task看Cycle-Num是不是0:
(1)如果不是0,說明還需要多移動幾圈,將Cycle-Num減1
(2)如果是0,說明馬上要執行這個Task了,取出Task-Funciton執行(可以用單獨的執行緒來執行Task),並把這個Task從Set中刪除
使用了“延時訊息”方案之後,“訂單48小時後關閉評價”的需求,只需將在訂單關閉時,觸發一個48小時之後的延時訊息即可:
(1)無需再輪詢全部訂單,效率高
(2)一個訂單,任務只執行一次
(3)時效性好,精確到秒(控制timer移動頻率可以控制精度)
四、總結
環形佇列是一個實現“延時訊息”的好方法,開源的MQ好像都不支援延遲訊息,不妨自己實現一個簡易的“延時訊息佇列”,能解決很多業務問題,並減少很多低效掃庫的cron任務。
另外,關於MQ的可達性、冪等性未來撰文另述。
相關文章
- 訂單超時關閉訂單的實現操作
- Laravel實現:待付款訂單,超48小時自動關閉Laravel
- 訂單自動過期實現方案 - 轉
- 怎樣實現關閉connection時自動關閉Statement和ResultSet
- 高效實現銷售出庫單與訂單自動對接的方案介紹
- php+redis實現超時取消訂單功能PHPRedis
- 如何給Infopath表單儲存時自動命名和自動關閉
- hyperf 實現延時佇列,處理超時未支付訂單佇列
- 大廠為什麼不用MQ實現訂單到期關閉?MQ
- HTTP介面自動化經驗總結(五)Okhttp3 關於超時的設定HTTP
- SHELL指令碼實現Oracle自啟動與關閉指令碼Oracle
- MySQL啟動和關閉命令總結MySql
- 訂單30分鐘未支付自動取消怎麼實現?
- 訂單自動生成器的演算法研究與實現薦演算法
- 查詢訂單付款超時的資料
- [實戰]laravel + redis訂閱釋出 +swoole實現實時訂單通知LaravelRedis
- ORACLE AS 自動關閉Oracle
- 微信訂閱號實現AI自動回覆AI
- 領導:誰再用redis過期監聽實現關閉訂單,立馬滾蛋!Redis
- 自動化測試工具分析和總結-實時更新
- 關閉自動收集 for oracleOracle
- 跨域方案總結與實現跨域
- 聯動選單的實現方案探索
- 簡單介紹python函式超時自動退出的實操方法Python函式
- Winform MessageBox訊息彈窗如何實現自動關閉ORM
- 使用Azure CLI實現自動關閉Azure虛擬機器的指令碼虛擬機指令碼
- windows10 自動更新怎麼關閉_關閉windows10 自動更新的方法Windows
- oracle自動啟動和關閉的方法Oracle
- Java自動生成訂單序列號Java
- Java後端長時間無操作自動退出實現方案Java後端
- js閉包簡單總結JS
- 自動駕駛資料閉環:實現高階自動駕駛的必由之路自動駕駛
- 如何關閉Win10自動更新 win10永久關閉自動更新Win10
- 應用例項:VC++實現廣告視窗自動關閉(轉)C++
- 如何關閉win10的自動更新_關閉自動更新win10怎麼操作Win10
- 單元測試內實現屬性自動繫結
- filebeat自動關閉解決
- WebStorm關閉自動拆疊WebORM