快狗打車訂單完成後,如果使用者一直不評價,48小時後會將自動評價為5星。
怎麼實現這類「48小時後自動評價為5星」需求呢?
畫外音:這類「一段時間之後,完成乙個任務」的需求很常見。
cron是不是最容易想到的方案?
啟動乙個cron定時任務,每小時跑一次,將完成時間超過48小時,且仍未評價的訂單取出,置為5星,並把評價狀態置為已評價。
假設訂單表的結構為:
order(oid, finish_time, stars, status, …)
更具體的,定時任務每隔乙個小時會這麼做一次:
select oid from order where finish_time > 48 and status=0;
update order set stars=5 and status=1 where oid in[…];
如果資料量很大,需要分頁查詢,分頁update,這將會是乙個for迴圈。
cron方案有什麼不足?
(1)輪詢效率比較低;
(2)每次掃庫,已經被執行過記錄,仍然會被掃瞄(只是不會出現在結果集中),有重複計算的嫌疑;
(3)時效性不夠好,如果每小時輪詢一次,最差的情況下,時間誤差會達到1小時;
(4)如果通過增加cron輪詢頻率來減少時間誤差,則輪詢低效和重複計算的問題會進一步凸顯;
對於這類需要延時執行的任務,如何保證效率的同時,又保證實時性呢?
答案是:高效延時訊息。
高效延時訊息,包含兩個重要的資料結構:
(1)環形佇列,例如可以建立乙個包含3600個slot的環形佇列(本質是個陣列);
(2)任務集合,環上每乙個slot是乙個set;
同時,啟動乙個timer:
(1)此timer每隔1s,在環形佇列中移動一格;
(2)用乙個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從set中刪除;
畫外音:注意,不要用timer來執行任務,否則timer會越來越不准。
使用了「延時訊息」方案之後,「訂單48小時後關閉評價」的需求,只需將在訂單關閉時,觸發乙個48小時之後的延時訊息即可:
(1)無需再輪詢全部訂單,效率高;
(2)乙個訂單,任務只執行一次;
(3)時效性好,精確到秒;
畫外音:控制timer移動頻率可以控制精度。
微控制器實現軟體濾波
1 限幅濾波法 又稱程式判斷濾波法 a 方法 根據經驗判斷,確定兩次取樣允許的最大偏差值 設為a 每次檢測到新值時判斷 如果本次值與上次值之差 a,則本次值有效 如果本次值與上次值之差 a,則本次值無效,放棄本次值,用上次值代替本次值 b 優點 能有效克服因偶然因素引起的脈衝干擾 c 缺點 無法抑制...
微控制器流星燈 51微控制器拖尾燈實現
這個拖尾燈,或者掃瞄燈,或者流星燈,不管怎麼叫,原理上估計都是一樣的。這玩意困擾了我好長的時間。我知道用pwm可以做出明暗效果。但是無法做到實現多路控制。在網上有種叫 霹靂遊俠掃瞄燈 的東西。好像是用專用的ic做的。找不到相關的原始碼。自己想啊想。一直想了乙個月。直到昨天,上課的時候靈光一閃,突然想...
微控制器藍芽燒錄 用微控制器實現藍芽功能
下面的文字只是關於藍芽技術的調製演算法方面,我認為只需要將藍芽模組加 在微控制器上就可以了,而不必通過微控制器程式設計來實現具體的演算法,只需要編 寫使兩個模組的介面就可以,也就是微控制器傳送訊號時的激勵程式,接受外 來訊號後的處理程式。置於其餘就由作為硬體裝置的藍芽來自行處理。不過 我並不確定,我...