作為Java開發人員,我們對垃圾收集的概念并不陌生。我們的應用程序一直在產生垃圾,這些垃圾被CMS、G1、Azul C4 和其他類型的收集器精心清理。基本上,我們的應用程序生來就是為了給這個世界帶來價值,但是,沒有什么是完美的——包括我們在Java堆中留下垃圾的應用程序。想學習java技術,建議考慮報名參加Java培訓,有明確的學習路線和全面系統的課程,能獲得較快提升。
然而,故事并沒有以Java堆結束。事實上,它只是從那里開始。讓我們以一個基本的Java應用程序為例,該應用程序使用PostgreSQL等關系數據庫和固態驅動器 (SSD) 作為存儲設備。從這里,我們將探索我們的應用程序如何在Java運行時邊界之外生成垃圾。
用Dead Tuples填充 PostgreSQL
當你的Java應用程序對 PostgreSQL數據庫執行DELETE或UPDATE語句時,不會立即刪除已刪除的記錄,也不會在其位置更新現有記錄。相反,刪除的記錄被標記為Dead Tuples并將保留在存儲中。更新的記錄實際上是PostgreSQL通過復制先前版本的記錄并更新請求的列來插入的全新記錄。該更新記錄的先前版本被視為已刪除,并且與DELETE操作一樣,被標記Dead Tuples。
數據庫引擎在其存儲中保留舊版本的已刪除和更新記錄是有充分理由的。對于初學者,你的應用程序可以針對PostgreSQL并行運行一堆事務。其中一些交易確實比其他交易更早開始。但是,如果一個事務刪除了一條記錄,而該記錄可能對一些較早開始的事務仍然感興趣,那么該記錄需要保存在數據庫中(至少直到所有較早開始的事務完成的時間點)。這就是 PostgreSQL實現MVCC(多版本并發協議)的方式。在java培訓中,有理論知識+實踐項目,雙管齊下,學以致用,讓你深入淺出地學習java。
很明顯,PostgreSQL不能也不想永遠保留Dead Tuples。這就是為什么數據庫有自己的垃圾收集過程,稱為清理。有兩種類型的VACUUM——普通的和完整的。普通的VACUUM與你的應用程序工作負載并行工作,不會阻止你的查詢。這種類型的清理將Dead Tuples占用的空間標記為空閑,使其可用于你的應用稍后將添加到同一個表中的新數據。普通的VACUUM不會將空間返回給操作系統,以便它可以被其他表或 第三方應用程序重用(在某些極端情況下,當頁面僅包含Dead Tuples并且頁面位于表的末尾時)。
相比之下,完整的VACUUM確實將可用空間回收給操作系統,但它會阻止應用程序工作負載。你可以將其視為Java的“stop-the-world”垃圾收集暫停。只有在PostgreSQL中,這樣的暫停才能持續數小時(或數天)。因此,數據庫管理員盡最大努力防止完全VACUUM發生。
在SSD中生成陳舊數據
如果你認為垃圾收集只是為了軟件,那就錯了!一些硬件設備也需要執行垃圾收集例程。SSD一直在做垃圾收集!
每當你的Java應用程序刪除或更新磁盤上的任何數據時——通過上面討論的PostgreSQL或直接通過Java文件 API——應用程序就會在SSD上生成垃圾。通過java培訓,你可以學習更多java編碼技巧,以提高java技能。
SSD將數據存儲在頁面中(通常大小在4KB和16KB之間),后者按塊分組。雖然你的數據可以在頁面級別寫入或讀取,但陳舊(已刪除)的數據只能在塊級別擦除。擦除需要比讀/寫操作更多的電壓,并且很難在不影響相鄰單元的情況下將電壓定位在頁面級別。
因此,如果你的Java應用程序更新了文件,那么事實上,更新的段將被寫入可能位于不同塊中的空頁面。帶有舊數據的段將被標記為過時,稍后將被垃圾收集。首先,SSD中的垃圾收集器遍歷具有陳舊數據的頁面塊,并將好的數據移動到其他塊(類似于Java的G1收集器中的壓縮階段)。其次,收集器擦除只剩下陳舊數據的塊,并使這些塊可用于未來的數據。
好奇SSD制造商如何防止或盡量減少“stop-the-world”暫停的次數? 有一個SSD過度配置的概念,即每臺設備都有一個額外的空間供你的應用程序使用。該空間是一種安全緩沖區,允許應用程序繼續寫入或修改數據,同時垃圾收集器同時擦除陳舊數據。
總結
嚴肅地說,垃圾收集是一種廣泛使用的技術,其使用范圍遠遠超出Java生態系統。如果實施得當,垃圾收集可以在不影響性能的情況下簡化軟件和硬件的架構。Java、PostgreSQL和SSD都是成功利用gar的產品的好例子。想要學習java更多知識和技能,可以考慮參加java培訓,有經驗豐富的專業講師指導教學,有緊跟市場需求的實時課程,可以讓你快速掌握這門技術,節約時間,少走彎路。