2014-05-08 29 views
1

我在Go中有一個小型項目,它們通過tcp接收文本行進行處理。然而,爲確保健壯性,我希望創建某種日誌,以便在斷電情況下不會丟失任何內容(例如,我的應用收到一幀數據,但尚未處理)。在golang中製作日誌文件

我已經搜索了應該如何實現日誌文件的任何指南,但搜索結果受到Oracle RDBMS文檔等的嚴重污染。

我的收穫是這樣的:在收到一行後立即將它寫入帶有「未處理標誌」的文件。處理完成後,更新文件以便清除該標誌,並打開覆蓋。在該標誌被清除的同時,向數據發送者發送「已處理的確認」。也許最容易處理期刊中固定大小的「插槽」,以確保我可以重複使用已釋放的插槽,而不是擁有不斷增加的文件並保留未使用插槽的「空閒列表」。

是否有任何「最佳實踐」在自定義代碼中實現這樣的文件,例如關於文件結構,填充和鎖定的文件? Go有沒有擔心這樣做,因爲它是跨平臺的,而不是使用本地文件系統API?

+0

關於需要多少一致性,是否可以在錯誤情況下兩次處理消息等等,會影響針對這種情況的最佳期刊設計有很多細節。沒有更多的細節,很難提供有用的答案。 'os'包提供了跨平臺的'sync'和'rename'調用,它們應該足以實現大多數期刊。 – Evan

回答

5

您不應該重寫日記。只需將操作追加到它,以便您可以重新創建它們,然後控制所需的嚴格級別。

的邏輯應該僅僅是:

  1. 收到消息

  2. 將其寫入日誌

  3. 可選做雜誌的FSYNC現在 - 根據您的一致性要求。

  4. (可選)然後發送「收到確認」 - 取決於您的需求。

  5. 處理該消息。

  6. 可選地將另一個「已處理」記錄寫入具有該記錄的標識的文件。你並不總是需要這個,但是你不要重寫舊記錄。或者,您可以使用您已處理的「頂級交易ID」編寫單獨的文件,以便在出現故障時自動知道從何處開始處理。這將減少日記的大小。

  7. 發送「已處理的確認」或「處理失敗」 - 再次取決於您的要求。

數據庫通常會讓你控制FSYNC行爲 - 每次寫入,每隔N秒,當OS決定 - 它的速度與耐用性的問題。

關於這個問題的一個很好的閱讀可能是這個職位上的Redis持久性: http://oldblog.antirez.com/post/redis-persistence-demystified.html

[編輯]關於這個問題的另一個偉大的閱讀 - http://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying

至於它的圍棋方面 - 有一個很少有寫入文件的選項,從低級文件處理程序到緩衝寫入程序。當然,一個文件處理程序會讓你控制引擎蓋下發生的事情。我不確定Go在一個正常的文件編寫器背後有多少緩存,如果您打算使用它,我建議您閱讀代碼。

+0

但是隻有追加纔會最終填滿磁盤,所以我重新考慮了一些需要一些旋轉功能,其中文件被歸檔並且另一個被創建,以便前一個可以被刪除? – agnsaft

+0

@invictus是的,當然 - 例如,MySQL會輪轉日誌文件,您可以配置輪換的大小。然後你可以使用logrotate來報廢舊文件。這取決於您是否需要重新創建延遲事務,或者是否能夠重新創建整個事務日誌 - 就像redis一樣。 –