定時器實現過程遇到的問題

原文轉自:http://www.tanjp.com/archives/203 (即時修正和更新)

 

定時器實現過程遇到的問題

在服務端的程序裏,時間是一個很常用,幾乎無處不在的變量。如果不正確使用時間,將會導致災難性的數據錯誤。所以,正確使用時間非常重要!

怎樣纔算是正確使用時間?

首先,我們得知道在程序世界裏面,時間有哪些值?

1、協調世界時,又稱世界統一時間,世界標準時間,國際協調時間,簡稱UTC。世界默認以格林威治時間(GMT)爲準。

2、世界各個地區時區的時間。如北京時間GMT+8,就是格林威治時間加8小時。

3、以計算機CPU時鐘結合程序啓動的時間算出的時間戳。

4、時間輪算法每次tick算出的時間。

 

然後,如何算是正確使用時間?那得先想想,怎樣是不正確的?

1、有一種唯一ID生成算法依賴於時間戳,如果時間改小了,就可能導致唯一ID重複,那可就是災難性的邏輯錯誤。

2、有些依賴於系統日期時間的定時器檢測,當系統時間由於某種原因導致時間回退到以前,那將會導致定時器卡死等待。甚至,std::this_thread:sleep_for 也是有BUG的,回退時間會導致該函數掛起等待,與期待的效果相違背。

3、有些時間校驗的算法,如果就在那一瞬間,時間回退了,導致某個非法校驗通過了?那也導致錯誤。

正確使用時間,應該保證時間戳在程序運行過程總是單調遞增,這隱患兩個意思,保持遞增,不能停下,不能倒退。

 

最後,總結一下時間和定時器的問題。

1、把時間戳劃分爲三種:系統日期時間戳(system time),CPU時鐘時間戳(cpu time),時間輪執行後的時間戳(tw time)。

2、底層邏輯相關的必須用CPU時鐘時間戳(cpu time),如網絡心跳,超時檢測,唯一ID算法,等等。

3、業務邏輯層使用時間輪時間戳(tw time)的話,要有一套自動同步機制,保證與CPU時鐘時間戳(cpu time)單調遞增同步。

4、在進程啓動前,儘可能保證各個機器的系統時間戳已同步。

5、在測試時間相關功能時,停掉3中所說的同步機制,通過指令加快時間輪時間戳(tw time),可達到改時間測試的效果。但不能把時間回退來測試。

 

踩過的坑

1、std::this_thread:sleep_for 有BUG,改變系統日期時間會導致 std::this_thread:sleep_for 卡住。改用 boost::this_thread:sleep_for 替代。

2、定時器如果依賴於系統日期時間,很可能由於時間同步問題或者手動改時間導致定時器卡死。

3、唯一ID生成算法依賴於時間,所以要採用CPU時鐘作爲統計的依據,保證時間只會單調遞增。

4、boost::asio::deadline_timer 改變系統的日期時間,會導致定時器卡住,改用 boost::asio::steady_timer 替代。

 

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