elasticsearch+hadoop項目

系統核心架構設計

 

1、數據首先存入HDFS,可以通過Spark SQL直接導入到ES中,

HDFS中的數據量與ES中數據量大致相當。

2、Spark SQL可以直接通過建立Dataframe或者臨時表連接ES,達到搜尋優化、減少數據量和篩選的目的,此時數據只在ES內存中而不在Spark SQL中。

3、篩選後的數據重新導入到Spark SQL中進行查詢。

(整體流程代碼見附錄)

 

一、數據流程

1、數據在HDFS

   數據存儲在HDFS上每個DataNodeblock塊上。

 

 

2、數據加載到Spark SQL

1)數據從HDFS加載到Spark SQL中,以RDD形式存儲。

 

2)添加數據結構信息轉換爲新的RDD

 

 

3)根據新的RDD創建DataFrame也即Dataset<Row>

 


 

 

 

左側的RDD[Person]雖然以Person爲類型參數,但Spark框架本身不瞭解Person類的內部結構。而右側的DataFrame卻提供了詳細的結構信息,使得Spark SQL可以清楚地知道該數據集中包含哪些列,每列的名稱和類型各是什麼。DataFrame多了數據的結構信息,即schemaRDD是分佈式的Java對象的集合。

 

DataFrame是分佈式的Row對象的集合。

DataFrame引入了schemaoff-heap

schema : RDD每一行的數據, 結構都是一樣的,這個結構就存儲在schema中。 Spark通過schema就能夠讀懂數據, 因此在通信和IO時就只需要序列化和反序列化數據, 而結構的部分就可以省略了。

 

off-heap: 意味着JVM堆以外的內存, 這些內存直接受操作系統管理(而不是JVM)。Spark能夠以二進制的形式序列化數據(不包括結構)off-heap中, 當要操作數據時,就直接操作off-heap內存。由於Spark理解schema,所以知道該如何操作。

 

DataSet結合了RDDDataFrame的優點,並帶來的一個新的概念Encoder

當序列化數據時,Encoder產生字節碼與off-heap進行交互,能夠達到按需訪問數據的效果,而不用反序列化整個對象。

 

4)由Dataset<Row>創建索引,並寫入ES

 

3、數據在ES中建立索引

   

 

分片與副本:

一個ES索引由多個分片與副本組成,數據均勻分配到每個分片中,分片數多,則每個分片的數據量小;分片數少,則每個分片的數據量大。(具體分片和副本策略見ES優化

 

Document:

   ES中數據以Document爲基本單位存儲,Dataset<Row>中每條記錄對應一個DocumentDocument隨機存在於分片中。

(1)index: Document歸屬於哪個索引。

(2)type: Document歸屬於哪個類型。

(3)id:  Document的標識符(自動生成)。

(4)Version:版本號,系統默認。

4Spark SQL通過索引對ES中數據進行查詢

 

Spark SQL通過pushdown機制將查詢下推到ES數據源,由ES完成查詢優化,再將結果返回SparkSQL中。

 

Push-Down operations

An important hidden feature of using elasticsearch-hadoop as a Spark source is that the connector understand the operations performed within the DataFrame/SQL and, by default, will translate them into the appropriate Elasticsearch Query DSL. In other words, the connector pushes down the operations directly at the source, where the data is efficiently filtered out so that only the required data is streamed back to Spark.

 

二、Spark SQLES優化

 

1Spark SQL優化

Spark SQL的性能調優選項主要有以下:

(1)spark.sql.codegen 默認值爲false,當它設置爲true時,Spark SQL會把每條查詢的語句在運行時編譯爲java的二進制代碼。這有什麼作用呢?它可以提高大型查詢的性能,但是如果進行小規模的查詢的時候反而會變慢,就是說直接用查詢反而比將它編譯成爲java的二進制代碼快。所以在優化這個選項的時候要視情況而定。

 

(2)spark.sql.inMemoryColumnStorage.compressed 默認值爲false 它的作用是自動對內存中的列式存儲進行壓縮。

 

3spark.sql.inMemoryColumnStorage.batchSize 默認值爲1000 這個參數代表的是列式緩存時的每個批處理的大小。SaprkSQL會按照這個選項制定的大小把記錄(每條記錄即爲一個Row對象)分組,然後分批壓縮。如果將這個值調大可能會導致內存不夠的異常,所以在設置這個的參數的時候得注意你的內存大小,一般情況下默認的1000就可以了。

 

 

 

 

 

2、ES優化

1.1分片策略

   主分片,副本和節點最大數之間數量存在以下關係:

節點數<=主分片數*(副本數+1

分片數等於節點數時,搜索效率最大。

 

1.2避免索引稀疏

1)避免把無關聯的數據放在同一個index

      不要把完全不同的數據結構 document 放在同一個 index 裏面。最好是將這些 document 放到不同的index裏面,可以考慮創建一些較小的index, 用較少的shard去存儲。

2)對於不同的字段禁用 norms doc_values

       通常只用於過濾而不需要進行打分(匹配度打分)的字段,可以直接禁用 norms 。不用於排序或者聚合的字段可以禁用 doc_values

1.3調優索引速度

1)增加 refresh_interval 刷新的間隔時間

        index.refresh_interval的默認值是 1s,這迫使Elasticsearch集羣每秒創建一個新的 segment (可以理解爲Lucene 的索引文件)。增加這個值,例如30s,可以允許更大的segment寫入,減後以後的segment合併壓力。

 

2)在初始化索引時,可以禁用 refresh replicas 數量

        如果需要一次加載較大的數據量進 index 裏面時,可以先禁用 refresh ,把 index.refresh_interval 設置成爲 -1 ,把 index.number_of_replicas 設置成 0。暫時把多個shard副本關閉(即如果當前index發生損壞便用丟失數據),但是這樣做可以大大加快索引速度。當初始化索引完成,可以將 index.refresh_interval  index.number_of_replicas 設置回原來的值。

 

3)禁用 swapping

       把操作系統的虛擬內存交換區關閉。sysctl 裏面添加 vm.swappiness = 1 .

 

 

 

1、測試的部分代碼

   1)根據實例數據創建JavaBean

 

 

2SparkSQLHDFS上讀取數據,並加載數據,在ES中創建索引。

 

3SaprkSQL讀取索引,進行SQL查詢。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章