(點選上方公眾號,可快速關註)
來源:Ambitor ,
my.oschina.net/ambitor/blog/522227
之前面試淘點點的時候被問倒得一個問題至今牽掛,由於工作環境的限制,我沒能接觸到一些大資料量的併發工作,也沒能有機遇參與複雜系統的設計,而我學習複雜或高併發系統的唯一途徑就是閱讀原始碼,慚愧的是,至今也只閱讀了Tomcat的部分原始碼
從事開發工作兩年來,從未寫過隻言片語,俗話說的好”好記性不如爛筆頭“,最近心血來潮開始想慢慢寫點博文,不僅是知識的積累還是為了若干年後回頭看看當年努力的過程,希望把這個養成習慣並堅持下去,囉嗦了這麼久 來點乾貨把。
之前面試淘點點的時候被問倒得一個問題至今牽掛,由於工作環境的限制,我沒能接觸到一些大資料量的併發工作,也沒能有機遇參與複雜系統的設計,而我學習複雜或高併發系統的唯一途徑就是閱讀原始碼,慚愧的是,至今也只閱讀了Tomcat的部分原始碼,於是我在oschina上貼出問題與網際網路猿一同分析(大家可以先看看問題:關於淘點點面試中碰到的架構問題),非常感謝大家的意見,尤其是@林中漫步 @JerryLin 兩位先生 最終確定兩鐘實現思路:
http://www.oschina.net/question/926166_2137672
1、具有排序功能的佇列
2、Redis+定時器
思路 1
原理:第一種思路也就是大家推薦的延遲佇列實現的原理,其就是一個按時間排好序的佇列,每次put的時候排序,然後take的時候就計算時間是否過期,如果過期則傳回佇列第一個元素,否則當前執行緒阻塞X秒,這個也是JDK 自帶 DelayQueue 的思路。詳細可看原始碼
程式碼實現:待實現後補充
思路 2
原理:第二種思路需要利用Redis的有序集合,說到使用 Redis 就不得不考慮Score的設計,因為它直接決定你程式碼的複雜度,你思路的清晰性,在這我並沒有採用 林中漫步 先生的設計,而是透過精確到秒的時間做Score(去掉毫秒),然後使用執行緒每一秒掃一次,使用當前時間作為zrangeBysocre命令的Score去查詢。詳細請看程式碼。
業務場景:按京東一天500萬的成交量,一天主要成交時間為8小時,計算得出每秒173個訂單,當然實際上訂單不能均勻分佈在每秒,但我們主要為了論證思想的可行性。
程式碼實現:這裡首先我簡單的利用Spring Scheduled作為訂單的生產者,每一秒製造170個訂單,放入Redis,註意Score的生成,為當前時間的後60秒,removeMillis()生成去掉毫秒的時間戳作為Rredis的Zadd方法的 Score(不瞭解的可以百度下)。
第二步:同樣利用Spring Scheduled 一秒鐘心跳一次,每次利用當前時間作為Key 從Redis 取資料。
經過測試,沒有出現漏單的情況,這隻是簡單的實現,很多地方可以最佳化,在實際中用也可能會出現很多問題,需要不斷完善,此案例只是提供思路,另外我覺得JDK的 DelayQueue 相對於Redis來說沒有那麼好,因為Queue畢竟每次取一個,如果同一時間的比較多可能不能符合當前這種時間嚴謹的需求,另外他是單機的,有時間我去研究下kafka、Rabbit的延遲佇列再來補充。
終於寫完了,因為公司的程式碼是加密的,所以不能上傳原始碼了(其實也沒得什麼上的,哈哈),另外本人技術有限難免會有紕漏或者錯誤,歡迎拍磚,另外希望自己以後能夠堅持寫技術日誌。
看完本文有收穫?請轉發分享給更多人
關註「ImportNew」,提升Java技能