我們有很多的手段保證數據的安全,但是要保證100%安全這是不可能的。畢竟在系統運行的過程中,服務器可以出的問題千奇百怪,只能說盡可能的讓數據盡可能的出出現丟失。
單純的保證數據庫本身的數據不丟失的話,最直接的方式就是通過建立主從庫,實現數據的熱備一般情況下,小的系統我們并不會考慮數據的熱備,一般只是在每天定時進行冷備而已,也就是設置一個定時器,然后到時間就同步數據。不過這樣做的話,一單系統的數據庫出現異常,那么我們的數據就會回滾到上一個備份的時間點,影響范圍就會比較大。
因此,對于數據量大一點的系統,我們就會進行主從庫的設置,不過通常情況下,我們做了主從庫都會做讀寫分離。
現在不管是哪種數據庫,都提供了數據庫之間訂閱同步的機制。以Mysql為例,我們先設置一個Master主庫,然后在基于這個主庫設置1個到多個Salve從主,從庫通過在主庫的SQLLog日志進行監聽,一旦有SQL執行,就會記錄一個二進制的Log,從庫發現了這個Log,也會同時執行同樣的操作,這樣就實現了數據的熱備。
但是,這種熱備的機制并不能100%保證數據不丟失。因為,我們在寫入主庫的時候如果出現異常,導致SQLLog還沒有記錄,那么從庫是不可能有數據記錄的。當然,此后的數據不會有影響,因為這是從庫會變為主庫來記錄后續數據。同樣,如果主從庫一起宕機,那也只有涼涼。
那么,為了讓數據庫的數據更加安全,就需要把數據保證的機制提前,不能單純的依靠數據庫來實現,那么我們可以加入隊列來試試。隊列并不是針對于數據的,隊列其實是用來保證消息的安全穩定的。自然,當請求沒有被寫入到數據庫是,都是以消息的形態存在,我們就可以考慮隊列來保證數據安全。
在數據庫訪問層,或者再靠前,到服務層,我們都可以加入MQ,讓每一個請求都通過MQ來順序的處理,一但數據庫宕機了,MQ的執行就會失敗,這時,失敗的記錄會被保存在MQ里面,并不會丟失,一但數據庫重啟,我們可以再次執行MQ中的消息,保證數據被成功的寫入到數據庫中。
具體怎么做呢?
首先,我們在插入數據庫前,把插入的操作變為向隊列對添加一個消息,然后,我們不同隊列建立不同的消費者,消費者對隊列的消息進行執行,再往數據庫里面插入數據。
對于我們的服務層,我們只要把消息插入到了隊列中,即視為成功,返回成功的消息。這樣,雖然我們的數據處理會有一點點的延時,并且在事務的控制上難度會變大,可能需要建立補償機制,但是我們的數據安全就更加高了。
這樣是不是就安全了呢?
并不是的。消息服務器也可能會宕機,消息也有可能出現丟失的情況,所以并不能保證100%的安全。
如果我們還需要做的更好,我們還可以加上MongoDB來做日志MongoDB是一個非關系型數據庫,在我們現在的系統中應用非常廣。最多的應用場景就是用來記錄日志。那么,日志就是一個幫助我們避免消息丟失的有效方式了。
我們對服務層的每個請求報文,都用MongoDB記錄請求的報文,再在請求處理完成返回結果的時候,記錄一個消息的處理結果(成功或失敗),這樣,我們就能夠很直觀的看到每天發生的請求,處理的請求情況了。
當有服務處理失敗了,不管是數據庫的問題還是其他的問題,我們都可以對異常進行排查,然后再根據報文進行消息的重推。這樣,我們的數據就會更加的安全了。
當然,即使如此,也不可能100%安全的,我們只能說盡可能的讓系統更安全,只不過,安全的同時,付出的成功也是高昂的,我們需要來衡量是否有這個必要,當我們的系統確實足夠大,用戶量很大時,這么處理是有價值的,否則,那就是一種資源的浪費。