關於海量數據存儲與查詢的思考


前段時間我做了一個SCA日志分析服務,該功能主要是從多台生產服務器上下載當天的日志數據,並且存在數據庫中。日志數據主要用於支持維護組查詢異常信息以及進行一些統計工作。

開始方案是通過ORACLE+Spring JDBCTemplate來實現,代碼實現后發現一個可怕的問題,日志解析入庫耗費的時間非常大,查看了一下數據庫數據解析1w條日志 用時10min左右 數據庫就有將近20w條數據,但是一般一個日志文件一天就是3w-4w條數據,所以數據庫中有應該有將近 20w *4 =80w條數據左右,這還是一台服務器的當天日志,如果是3台服務器 那么一天將近240w條日志 4天左右就有近1000w條數據,那么一個月將近上億條日志數據,但是我們最少數據庫中要保存2-3個月的日志數據,所以這種方案入庫是根本行不通的,服務器也會被卡死,性能消耗可想而知。

繼續思考上面的問題,想什么辦法可以提高日志入庫的時間呢,主要考慮過三種方式:第一種,用Oracle自帶的大數據導入工具sqlldr,將數據導入到一張臨時表中,在數據庫中解析日志后在分別插入到相關表中,這種方案可以行吧,效率肯定非常高,因為是在數據庫中直接操作,摒棄了jdbctemplate操作數據庫。第二種,減少jdbctemplate建立連接的次數,因為用的存儲過程,我們可以把參數改成數組的形式,可以提高上百倍的效率,但是這種方式有個問題,我們數據庫中對大對象用到了CLOB參數類型,這種類型會超出varchar2 4000字節的長度,我們在對字符串數組進行分離的時候可能會導致數據丟失,而且CLOB類型也不能轉換為varchar2類型,所以這種方式也不太可行。第三種,去掉存儲過程,直接對表進行操作,采用一些ORM框架,用事務提交,這種方式還沒有驗證過是否可以大幅的提高日志入庫的效率。既然Oracle都提供了一個工具專門解決大數據入庫的性能問題,我想這個應該會起其它兩種方式都更簡便,效率也更可觀一些。當然口說無憑,這些方式都需要我們手動去驗證了才能證明它才是真理。

通過上面的分析,好像sqlldr可以解決我們數據入庫的問題,但是問題又來了,上億的數據量,按照我們傳統的方式進行模糊查詢只能接近龜速,這也是關系型數據庫的一大弊端,不支持全文索引,數據庫的索引不是為全文索引設計的,在使用Like查詢時,搜索過程又變成類似一頁一頁翻書的過程,所以使用Like對關系型數據來說是一個性能殺手。這時Lucene上場了,Lucence最核心的特征是通過特殊的索引結構實現了傳統數據庫不擅長的全文索引機制,請提供了擴展接口,以方便針對不同應用的定制。據我了解,Lucence主要用到了倒排索引和折半查找,所以Lucence無疑是全文索引的一個好幫手。

綜合上面的觀點,好像目前最佳的解決方案是sqlldr+Lucence。由於主要是日志入庫和查詢,所以這種方案理論上應該是可行的。我們衍生一下,假如是一個海量數據,且存在上萬次並發請求情況呢?關系數據庫應付上萬次SQL查詢還勉強頂得住,但是應付上萬次SQL寫數據請求,硬盤IO就已經無法承受了。其實對於普通的BBS網站,往往也存在對高並發寫請求的需求。 當一個應用系統的用戶量和訪問量與日俱增的時候,你的數據庫卻沒有辦法像web server和app server那樣簡單的通過添加更多的硬件和服務節點來擴展性能和負載能力,數據庫是最難橫向擴展的。這時候我們可以考慮用NoSQL。

Nosql有很多優點,可以運行在便宜的PC集群上,NoSQL架構可以省去將Web或Java應用和數據轉換成SQL格式的時間,使執行速度變得更快,具有靈活的數據模型,可以非常方便的添加字段等。我們常用的一些NOSQL主要有:CouchDB、Redis、MongoDB、Hbase等,可能MongoDB是我們最好理解的nosql,UACD時主要用到了JSON格式。所以我們在處理高並發+海量數據時一般采用的是NOSQL存儲架構。

當然我們不能殺雞用牛刀,應具體應用具體分析。歡迎大家來指正~,提更多更好的觀點。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM