在一個完整的項目中,不僅僅是要完成正常的業(yè)務開發(fā)。同時為了提高一些開發(fā)效率、系統(tǒng)異常的追蹤、系統(tǒng)功能的擴展等等因素,往往會用到系統(tǒng)在開發(fā)、運行過程中所產(chǎn)生的日志。這就需要我們有一個完善的日志系統(tǒng)來存儲這些數(shù)據(jù)。本文將分享如何設計一個高可用、可擴展的分布式日志系統(tǒng)。
本文是一種理論性的方案探索,當然各種方案也是在實際的生產(chǎn)環(huán)境中經(jīng)過實踐總結(jié)而來的。
本文是分布式日志存儲系列的理論篇。也有實戰(zhàn)篇,將會分享從0到1的整個過程,從0環(huán)境的搭建到真正的實踐落地。文章會定期的完善,最終文章地址。
文章中相應的試題,整理在小程序中,點擊獲取。
日志的重要性
在一個系統(tǒng)中,日志常常在下面的一些場景中占著非常大的作用:
項目開發(fā)階段的調(diào)試、線上服務異常排查。
系統(tǒng)異常的監(jiān)控。
系統(tǒng)數(shù)據(jù)分析。
對應日志,主要分為下面三大類型:
?

日志服務的演進
通過上面幾點,大致明白了一個日志系統(tǒng)的重要性。接下來,我們將進一步了解如何設計一個日志系統(tǒng)。
單節(jié)點部署
在項目早期,由于項目用戶量小、業(yè)務數(shù)據(jù)少等特點,一般項目都會采用單節(jié)點的方式進行部署。此時的日志,一般會以文件的方式存儲在對應服務器上。如下圖:
?

Snipaste_2022-05-05_16-37-38
當客戶端向服務端發(fā)送請求,對應的服務器處理業(yè)務并將日志記錄到日志文件中。這也是傳統(tǒng)的日志記錄方式,很多的后端框架默認的日志記錄方式也如此。如下面PHP的Hyperf框架,默認將MySQL的操作日志記錄到日志文件中。
?

優(yōu)點
按照這種傳統(tǒng)的單節(jié)點部署,有什么好處呢?
系統(tǒng)架構單一、部署簡單。不用擔心各種服務之間調(diào)用問題。
技術成本低、易維護。直接使用開發(fā)語言的文件操作函數(shù),寫人即可。
性能高、穩(wěn)定。不需要調(diào)用其他的服務組件,直接調(diào)用系統(tǒng)接口寫入磁盤即可。
缺點
當日志文件過大時,需要對日志文件做切割,避免寫入性能降低。
不便于日志排查。對應開發(fā)人員來說,可以直接分析日志內(nèi)容。如果對于非開發(fā)人員來說,對日志存儲的就有一定的要求。
存在安全問題。對應服務器一般都有設置權限,需要對服務器用戶設置嚴格的權限。
分布式部署(文件)
這里的分布式部署(文件)指的是,系統(tǒng)服務采用分布式部署時,日志存儲還是采用文件存儲。大致的邏輯圖如下:
?

優(yōu)點
這樣的部署方案有什么好處,和上面提到的單節(jié)點部署一樣。
缺點
在分布式部署中,還是同樣的會遇到單節(jié)點部署所遇到的問題。
不便于系統(tǒng)排查。當系統(tǒng)出現(xiàn)異常時,由于是分布式部署,我們不知道最終的日志存儲在那一臺服務器上,就需要挨個服務器的排查。降低了問題排查效率。
分布式部署(日志系統(tǒng))
上面提到了分布式系統(tǒng),使用文件存儲日志的幾個弊端。因此這里推出使用獨立的日志系統(tǒng),存儲系統(tǒng)日志。大致邏輯圖如下:
?

當客戶單發(fā)送請求到服務器,服務器處理對應的業(yè)務邏輯和記錄日志服務。
為了提高系統(tǒng)的響應速度、高可用,在記錄日志時,先將日志寫入到MQ消息隊列中,開啟獨立的線程將隊列中的日志寫入到磁盤中。常見的MQ消息隊列有,RabbitMQ,RocketMQ,ActiveMQ,ZeroMQ,Kafka,IBM WebSphere等??梢愿鶕?jù)系統(tǒng)的實際需要選擇合適的MQ服務。
寫入對應的日志系統(tǒng)之后,可以獨立開發(fā)一套系統(tǒng),來做日志的顯示、查詢、刪除等操作。
優(yōu)點
解決了分布式部署中采用文件存儲的弊端。
提高了系統(tǒng)的可用性。在寫日志時,開發(fā)人員只需要將日志寫入到對應的MQ消息隊列中即可。做持久化直接讓單獨的線程執(zhí)行。
提高了系統(tǒng)的擴展性。如果團隊中,其他的項目需要增加日志功能,我們不需要單獨的增加服務器,直接寫入原有的MQ消息隊列系統(tǒng)即可。
缺點
系統(tǒng)部署復雜。增加了MQ服務,也意味著在項目前期增加了運維成本。
對開發(fā)人員要求高。需要熟悉MQ消息服務技術棧。
系統(tǒng)架構要求高。在項目前期一定要搭建一個高可用、高擴展的架構,當業(yè)務變得越來越復雜時以及各種服務之間的調(diào)用,影響正常的業(yè)務邏輯。
日志系統(tǒng)
上面針對日志服務做了一個架構演進的總結(jié)。接下來,就來具體的探討如何設計一個高可用、高擴展的日志系統(tǒng)。對應日志系統(tǒng),我個人如下幾個觀點:
可用性強,不能影響正常業(yè)務的執(zhí)行。日志的作用最大的意義在于我們排查問題、分析問題以及解決問題。要保證在這個過程中,即使日志服務不可用的狀態(tài)下,仍然不能影響到正常業(yè)務的日志。
擴展性強。在設計日志系統(tǒng)時,不能只針對當前的系統(tǒng)做設計,還需要考慮到后期其他項目日志的接入。
針對日志系統(tǒng),我們可以采用自研的方式,也可以采用開源系統(tǒng)部署。在本文總,分享兩種較為簡單的日志服務系統(tǒng)。大致的邏輯圖如下:
?

MongoDB存儲
系統(tǒng)日志最終的落地,肯定是磁盤。因此,第一種方案我們使用MongoDB來記錄日志。為什么采用MongoDB作為日志存儲服務器呢?
MongoDB嚴格來說是一個非關系型的數(shù)據(jù)庫系統(tǒng)。它支持的數(shù)據(jù)結(jié)構非常松散,類似json格式的bson格式,因此可以存儲比較復雜的數(shù)據(jù)類型。如果采用MySQL、SQLserver、oracle這樣的具有嚴格數(shù)據(jù)結(jié)構要求的數(shù)據(jù)庫,在日志統(tǒng)計緯度變化時,對應的數(shù)據(jù)表結(jié)構也會隨著變化。
查詢效率高。MongoDB最大的特點是它支持的查詢語言非常強大,其語法有點類似于面向?qū)ο蟮牟樵冋Z言,幾乎可以實現(xiàn)類似關系數(shù)據(jù)庫單表查詢的絕大部分功能,而且還支持對數(shù)據(jù)建立索引。
業(yè)務拆分、提高業(yè)務數(shù)據(jù)庫性能。如果把日志也存儲在MySQL中,必然會降低MySQL的高并發(fā)性能問題。一個系統(tǒng)中,日志內(nèi)容肯定非常的多,日志的讀寫搶占了對應的操作必然是會降低業(yè)務讀寫的操作。
使用MongoDB作為日志存儲服務,大致的邏輯可以采用如下結(jié)構:
?

業(yè)務系統(tǒng)處理日志,再調(diào)用MQ消息服務,先將日志數(shù)據(jù)存在MQ消息服務中。
開啟異步線程,將MQ服務的消息同步到MongoDB服務中,以達到持久化的目的。
Web頁面則是用于日志數(shù)據(jù)的展示。
ELK存儲
ELK是Elasticsearch+Logstash +Kibana 這種架構的簡寫。這是一種開源日志分析平臺的架構。ELK是開源的,社區(qū)活躍,用戶眾多,這樣的架構也得到廣泛的使用。大致的邏輯圖如下:
?

ELK常用架構
Elasticsearch + Logstash + Kibana 這是一種最簡單的架構。這種架構,通過logstash收集日志,Elasticsearch分析日志,然后在Kibana(web界面)中展示。這種架構雖然是官網(wǎng)介紹里的方式,但是往往在生產(chǎn)中很少使用。
Elasticsearch + Logstash + filebeat + Kibana 與上一種架構相比,這種架構增加了一個filebeat模塊。filebeat是一個輕量的日志收集代理,用來部署在客戶端,優(yōu)勢是消耗非常少的資源(較logstash), 所以生產(chǎn)中,往往會采取這種架構方式,但是這種架構有一個缺點,當logstash出現(xiàn)故障, 會造成日志的丟失。
Elasticsearch + Logstash + filebeat + redis(也可以是其他中間件,比如kafka(集群化)) + Kibana這種架構是上面那個架構的完善版,通過增加中間件,來避免數(shù)據(jù)的丟失。當Logstash出現(xiàn)故障,日志還是存在中間件中,當Logstash再次啟動,則會讀取中間件中積壓的日志。目前我司使用的就是這種架構,我個人也比較推薦這種方式。
總結(jié)
對于上面提高的幾種方案,在實際過程中,還需要結(jié)合自身的項目情況,選擇合適的架構,而不是為了追求技術的復雜度而忽略了自身的實際情況。
電子發(fā)燒友App




























評論