智慧停車(六) 怎麼最優實現免費停車時間方案

業務場景如下:車位擋板默認爲下降狀態,車子初次入場的時候,數據庫記錄入場時間,這個時間就是免費時間的開始,各個城市各個路段的免費時間策略也不一樣,比如在某個地段設置免費時間爲10分鐘,後臺計算當到了10分鐘後,會發送指令讓擋板上升,這個時間就是收費時間的開始。

後臺怎麼來監控每個車位的免費時間是否到點,有如下方案:

方案1:定時調度輪詢數據庫

數據庫表會記錄開始時間,隔一段時間就輪詢一次,計算當前時間和開始時間的差,來確定是否免費時間到點,這種方式數據量小,對時間精準度底的情況下可以使用,針對數據量大的情況,拆分多個定時調度各輪詢自己的一部分,甚至可以將數據庫數據放入到redis裏面加快輪詢速度,也只能這樣了,考慮到實現和維護以及效率差,有時間差,暫不考慮。

方案2:使用spring + quartz定時任務

使用spring + quartz定時任務(支持任務信息寫入mysql,多節點分佈式執行任務),每次車主入場開始生成一個某某時間後運行的任務。查閱了相關文檔也嘗試使用了一把,中途放棄了,受不了那麼多數據庫表的配置,實現起來有點複雜。

方案3:使用Java的線程休眠或定時器

此方案直接被PASS掉,不支持高可用,節點掛掉或者重啓,任務失效。最差的實現方式,切勿使用。

方案4:使用redis的空間鍵通知

redis的空間鍵通知是在2.8.0版本以後加入的,客戶端通過發佈訂閱的方式,訂閱某個頻道,接收通過某種方式影響redis中數據的事件。簡單來說,就是設置了Key的過期時間,當過期的時候redis會有通知功能。花了幾個小時嘗試了一把,感覺也挺複雜的,最主要的是目前這項功能有些缺陷,比如文檔有提到:redis key的失效通知機制是基於其pub/sub模式的,這個模式有個致命的缺陷是,消息通知不能持久化,假如監聽服務宕機期間,有key過期,那麼這個失效通知就被忽略了。此方案應該比前面幾種要好,但是經過再三考慮放棄。

方案5:使用apache ignite

有人推薦用ignite,問之原因,說和redis差不多,也是內存數據庫,但是支持設置過期時間有通知功能,感興趣的朋友可以自己去看相關資料。

方案6:使用rocketmq延時消息

rocketmq提供一種延時消息的解決方案,就是在特定的時間到了,消息纔會被投遞出去供consumer消費。 此種方案應該比前面任何一種方案都比較適合目前業務場景,而且rocketMQ開箱即用,使用簡單,不用多說,就是它了。先來張阿里雲官方提供的功能概覽圖。

重點關注下定時(延時)消息:允許消息生產者指定消息進行定時(延時)投遞,最長支持 40 天。本來以爲定時消息和延時消息是一碼事,但是仔細翻看文檔,眼睛一亮。  

1.概念介紹:

定時消息:Producer 將消息發送到消息隊列 RocketMQ 服務端,但並不期望這條消息立馬投遞,而是推遲到在當前時間點之後的某一個時間投遞到 Consumer 進行消費,該消息即定時消息。 

延時消息:Producer 將消息發送到消息隊列 RocketMQ 服務端,但並不期望這條消息立馬投遞,而是延遲一定時間後才投遞到 Consumer 進行消費,該消息即延時消息。 

定時消息與延時消息在代碼配置上存在一些差異,但是最終達到的效果相同:消息在發送到消息隊列 RocketMQ 服務端後並不會立馬投遞,而是根據消息中的屬性延遲固定時間後才投遞給消費者。  

2.適用場景:

定時消息和延時消息適用於以下一些場景:  

消息生產和消費有時間窗口要求:比如在電商交易中超時未支付關閉訂單的場景,在訂單創建時會發送一條 延時消息。這條消息將會在 30 分鐘以後投遞給消費者,消費者收到此消息後需要判斷對應的訂單是否已完成支付。 如支付未完成,則關閉訂單。如已完成支付則忽略。 

通過消息觸發一些定時任務,比如在某一固定時間點向用戶發送提醒消息。  

3.使用方式:

定時消息和延時消息的使用在代碼編寫上存在略微的區別:  

發送定時消息需要明確指定消息發送時間點之後的某一時間點作爲消息投遞的時間點。  

發送延時消息時需要設定一個延時時間長度,消息將從當前發送時間點開始延遲固定時間之後纔開始投遞。

關於使用rocketmq定時消息和延時消息詳情後面在實際項目中再補充。

 

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