日誌就是按照時間順序追加的、徹底有序的記錄序列,其實就是一種特殊的文件格式,文件是一個字節數組,而這裏日誌是一個記錄數據,只是相對於文件來講,這裏每條記錄都是按照時間的相對順序排列的,能夠說日誌是最簡單的一種存儲模型,讀取通常都是從左到右,例如消息隊列,通常是線性寫入log文件,消費者順序從offset開始讀取。數據庫
日誌在數據庫中的應用因爲日誌自己固有的特性,記錄從左向右開始順序插入,也就意味着左邊的記錄相較於右邊的記錄「更老」, 也就是說咱們能夠不用依賴於系統時鐘,這個特性對於分佈式系統來講至關重要。數組
日誌是何時出現已經無從得知,多是概念上來說太簡單。在數據庫領域中日誌更多的是用於在系統crash的時候同步數據以及索引等,例如MySQL中的redo log,redo log是一種基於磁盤的數據結構,用於在系統掛掉的時候保證數據的正確性、完整性,也叫預寫日誌,例如在一個事物的執行過程當中,首先會寫redo log,而後纔會應用實際的更改,這樣當系統crash後恢復時就可以根據redo log進行重放從而恢復數據(在初始化的過程當中,這個時候不會尚未客戶端的鏈接)。日誌也能夠用於數據庫主從之間的同步,由於本質上,數據庫全部的操做記錄都已經寫入到了日誌中,咱們只要將日誌同步到slave,並在slave重放就可以實現主從同步,這裏也能夠實現不少其餘須要的組件,咱們能夠經過訂閱redo log 從而拿到數據庫全部的變動,從而實現個性化的業務邏輯,例如審計、緩存同步等等。緩存
日誌在分佈式系統中的應用性能優化
分佈式系統服務本質上就是關於狀態的變動,這裏能夠理解爲狀態機,兩個獨立的進程(不依賴於外部環境,例如系統時鐘、外部接口等)給定一致的輸入將會產生一致的輸出並最終保持一致的狀態,而日誌因爲其固有的順序性並不依賴系統時鐘,正好能夠用來解決變動有序性的問題。
咱們利用這個特性實現解決分佈式系統中遇到的不少問題。例如RocketMQ中的備節點,主broker接收客戶端的請求,並記錄日誌,而後實時同步到salve中,slave在本地重放,當master掛掉的時候,slave能夠繼續處理請求,例如拒絕寫請求並繼續處理讀請求。日誌中不只僅能夠記錄數據,也能夠直接記錄操做,例如SQL語句。服務器
日誌是解決一致性問題的關鍵數據結構,日誌就像是操做序列,每一條記錄表明一條指令,例如應用普遍的Paxos、Raft協議,都是基於日誌構建起來的一致性協議。數據結構
日誌在Message Queue中的應用併發
日誌能夠很方便的用於處理數據之間的流入流出,每個數據源均可以產生本身的日誌,這裏數據源能夠來自各個方面,例如某個事件流(頁面點擊、緩存刷新提醒、數據庫binlog變動),咱們能夠將日誌集中存儲到一個集羣中,訂閱者能夠根據offset來讀取日誌的每條記錄,根據每條記錄中的數據、操做應用本身的變動。
這裏的日誌能夠理解爲消息隊列,消息隊列能夠起到異步解耦、限流的做用。爲何說解耦呢?由於對於消費者、生產者來講,兩個角色的職責都很清晰,就負責生產消息、消費消息,而不用關心下游、上游是誰,不論是來數據庫的變動日誌、某個事件也好,對於某一方來講我根本不須要關心,我只須要關注本身感興趣的日誌以及日誌中的每條記錄。異步
咱們知道數據庫的QPS是必定的,而上層應用通常能夠橫向擴容,這個時候若是到了雙11這種請求忽然的場景,數據庫會吃不消,那麼咱們就能夠引入消息隊列,將每一個隊數據庫的操做寫到日誌中,由另一個應用專門負責消費這些日誌記錄並應用到數據庫中,並且就算數據庫掛了,當恢復的時候也能夠從上次消息的位置繼續處理(RocketMQ和Kafka都支持Exactly Once語義),這裏即便生產者的速度異於消費者的速度也不會有影響,日誌在這裏起到了緩衝的做用,它能夠將全部的記錄存儲到日誌中,並定時同步到slave節點,這樣消息的積壓能力可以獲得很好的提高,由於寫日誌都是有master節點處理,讀請求這裏分爲兩種,一種是tail-read,就是說消費速度可以跟得上寫入速度的,這種讀能夠直接走緩存,而另外一種也就是落後於寫入請求的消費者,這種能夠從slave節點讀取,這樣經過IO隔離以及操做系統自帶的一些文件策略,例如pagecache、緩存預讀等,性能能夠獲得很大的提高。分佈式
分佈式系統中可橫向擴展是一個至關重要的特性,加機器能解決的問題都不是問題。那麼如何實現一個可以實現橫向擴展的消息隊列呢? 假如咱們有一個單機的消息隊列,隨着topic數目的上升,IO、CPU、帶寬等都會逐漸成爲瓶頸,性能會慢慢降低,那麼這裏如何進行性能優化呢?性能
topic/日誌分片,本質上topic寫入的消息就是日誌的記錄,那麼隨着寫入的數量越多,單機會慢慢的成爲瓶頸,這個時候咱們能夠將單個topic分爲多個子topic,並將每一個topic分配到不一樣的機器上,經過這種方式,對於那些消息量極大的topic就能夠經過加機器解決,而對於一些消息量較少的能夠分到到同一臺機器或不進行分區
group commit,例如Kafka的producer客戶端,寫入消息的時候,是先寫入一個本地內存隊列,而後將消息按照每一個分區、節點彙總,進行批量提交,對於服務器端或者broker端,也能夠利用這種方式,先寫入pagecache,再定時刷盤,刷盤的方式能夠根據業務決定,例如金融業務可能會採起同步刷盤的方式。
規避無用的數據拷貝
IO隔離
日誌在分佈式系統中扮演了很重要的角色,是理解分佈式系統各個組件的關鍵,隨着理解的深刻,咱們發現不少分佈式中間件都是基於日誌進行構建的,例如Zookeeper、HDFS、Kafka、RocketMQ、Google Spanner等等,甚至於數據庫,例如Redis、MySQL等等,其master-slave都是基於日誌同步的方式,依賴共享的日誌系統,咱們能夠實現不少系統: 節點間數據同步、併發更新數據順序問題(一致性問題)、持久性(系統crash時可以經過其餘節點繼續提供服務)、分佈式鎖服務等等,相信慢慢的經過實踐、以及大量的論文閱讀以後,必定會有更深層次的理解。
連接:
CentOS系統中經常使用查看日誌命令 :http://blog.51cto.com/xiaogongju/2062908