開篇
Elasticsearch以下簡(jiǎn)稱ES廉邑,接下來ES將從幾個(gè)方面進(jìn)行解釋:
? ? ? 1.ES是什么靡挥?
? ? ? 2.應(yīng)用場(chǎng)景
? ? ? 3.ES的生態(tài)
? ? ? 4.ES的一些特性
? ? ? 5.ES的一些好用插件
? ? ? 6.ES在PHP Laravel的中實(shí)戰(zhàn)
????? 7.ES在Spark中的實(shí)戰(zhàn)
? ? ? 8.ES調(diào)優(yōu)
? ? ? 9.致謝參考鏈接
1.ES是什么悬荣?
ES是一個(gè)開源的高擴(kuò)展的分布式全文檢索引擎题翰,它可以近乎實(shí)時(shí)的存儲(chǔ)拙泽、檢索數(shù)據(jù)荆烈;本身擴(kuò)展性很好拯勉,可以擴(kuò)展到上百臺(tái)服務(wù)器,處理PB級(jí)別的數(shù)據(jù)憔购。
Elasticsearch也使用Java開發(fā)并使用Lucene作為其核心來實(shí)現(xiàn)所有索引和搜索的功能宫峦,但是它的目的是通過簡(jiǎn)單的RESTful API來隱藏Lucene的復(fù)雜性,從而讓全文搜索變得簡(jiǎn)單玫鸟。
這段話就是對(duì)ES的一個(gè)描述导绷,簡(jiǎn)單概括:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? “高性能全文搜索引擎,RESTful API接口調(diào)用”
ES的內(nèi)部設(shè)計(jì)非常優(yōu)雅屎飘,一切的一切統(tǒng)統(tǒng)都是接口調(diào)用妥曲,針對(duì)ES的開發(fā)維護(hù)會(huì)比較輕松,一般到后續(xù)我們都會(huì)針對(duì)ES進(jìn)行定制開發(fā)钦购,好比ES當(dāng)成一個(gè)數(shù)據(jù)庫(kù)檐盟,通過它定制的查詢語法進(jìn)行交互來完成我們的數(shù)據(jù)分析需求。
2.ES應(yīng)用場(chǎng)景
對(duì)于剛剛接觸ES的人應(yīng)該比較陌生肮雨,我們來直接對(duì)ES使用做一個(gè)定位
那么我們來列舉一下ELK這套使用的應(yīng)用場(chǎng)景:
1.監(jiān)聽網(wǎng)站Nginx的日志時(shí)時(shí)同步到ES,通過Kibana來分型日志是否存在問題箱玷,服務(wù)器層面的監(jiān)控怨规。
2.監(jiān)聽Mysql日志陌宿,對(duì)日志進(jìn)行監(jiān)控檢測(cè),對(duì)于業(yè)務(wù)來說可以進(jìn)行一些輔助分析波丰。
3.用戶行為數(shù)據(jù)埋點(diǎn)收集壳坪,提供大數(shù)據(jù)分析數(shù)據(jù)支持。
4.使用ES來構(gòu)建網(wǎng)站的全文檢索引擎掰烟。
這是一些常見的使用場(chǎng)景爽蝴,還可以繼續(xù)補(bǔ)充。
3.ES的生態(tài)
我們?cè)谶M(jìn)行ES開發(fā)的時(shí)候一般會(huì)選用一整套ES的技術(shù)棧ELK(Elasticsearch+Logstash+Kibana)
我們大部分情況會(huì)接入Flume,Kafka來做數(shù)據(jù)的消息中間件來作為L(zhǎng)ogstash的數(shù)據(jù)源纫骑。
我們還可能使用PHP蝎亚,Spark,Scala等來分析ES中的數(shù)據(jù)提供個(gè)性化服務(wù)先馆。
我們還可能使用Firebeat來替換Logstash发框。
其中ES是可以支持集群橫向拓展來完成對(duì)性能的要求,后續(xù)會(huì)講到關(guān)于ES的調(diào)優(yōu)煤墙。
ELK是同一家公司提供的打包的一組服務(wù)梅惯,其中
E:就是這個(gè)全文檢索引擎了
L:一個(gè)日志收集服務(wù),可以把你的log,kafka等其中的數(shù)據(jù)收集并輸出到ES中
K:一個(gè)可視化圖表工具, 通過接入ES提供直接的頁面來完成數(shù)據(jù)的分析查詢使用
“我們可以通過L來監(jiān)聽一些文件的改動(dòng)仿野,然后把數(shù)據(jù)從文件灌入ES铣减,最后通過K來可視化查看〗抛鳎”
這是一種比較簡(jiǎn)單直接的使用方式葫哗。
我們經(jīng)常會(huì)使用一種架構(gòu):
這里面Filebeat是比較輕量級(jí)的日志收集工具,和Logstash配合可以提升吞吐量鳖枕。
好了魄梯,到這里介紹完了我們常用的生態(tài)組件。
4.ES的一些特性
在使用之前我們還是要先從ES的一些特性進(jìn)行了解宾符,
首先:ES有索引酿秸,分片,文檔等基礎(chǔ)概念魏烫,我們必須先了解這些辣苏。
文檔(Docs)
存儲(chǔ)的一條記錄
索引? (Index)
我們可以先暫時(shí)吧索引比作MySQL中的數(shù)據(jù)庫(kù)的概念。這樣會(huì)比較好理解哄褒。
分片(Shard)
分片是組成索引的單元稀蟋,我們創(chuàng)建索引的時(shí)候可以指定分片的信息,默認(rèn)創(chuàng)建一個(gè)
索引的時(shí)候會(huì)創(chuàng)建5個(gè)主分片呐赡,同時(shí)每個(gè)主分片對(duì)應(yīng)一個(gè)副本分片退客。
這里的對(duì)應(yīng)關(guān)系應(yīng)該是 索引->分片 是 1:N的關(guān)系。
同時(shí)一般一個(gè)分片的最大存儲(chǔ)空間是有限制的,50GB大小通常是一個(gè)上限。其實(shí)主要原因是
每個(gè)分片都是一個(gè)Lucene Index萌狂,一個(gè)分片只能存放Integer.MAX_VALUE-128個(gè)文檔2,147,483,519 個(gè)docs档玻,所以一個(gè)分片能存多少數(shù)據(jù)也要基于單個(gè)文檔的內(nèi)容而定。
在ES集群的環(huán)境下,副本分片會(huì)分散在不同的節(jié)點(diǎn),來實(shí)現(xiàn)高可用茫藏,提升查詢性能误趴。
分片數(shù)量會(huì)影響什么?
ES的查詢?nèi)绻制瑪?shù)量太多务傲,就需要每個(gè)分片都查詢一次凉当,然后聚合結(jié)果,一般建議根據(jù)數(shù)據(jù)量大小來
設(shè)定索引和分片數(shù),后續(xù)關(guān)于ES調(diào)優(yōu)中分片的配置比較重要售葡,不過也不必太擔(dān)心看杭,不管索引和分片設(shè)置的
如何我們都是可以通過API進(jìn)行reindex等操作來完成調(diào)整。
5.ES的一些好用插件
elasticsearch-sql?把sql語句轉(zhuǎn)換成DSL查詢語法天通,或者直接通過sql進(jìn)行查詢ES泊窘。
ES-HEAD?ES集群信息監(jiān)控等(chrome插件)
X-PACK?官方查詢,提供權(quán)限管控像寒,性能跟蹤等烘豹。
6.ES在PHP Laravel中的實(shí)戰(zhàn)
其實(shí)上面介紹了那么多,很多時(shí)候大家在搭建好一整套ELK的時(shí)候直接訪問K的服務(wù)就能可視化的進(jìn)行交互了诺祸,但是如果有一天携悯,你想通過代碼來拉取數(shù)據(jù)并且執(zhí)行一定的邏輯功能,那么你可能就需要進(jìn)行開發(fā)了筷笨。
那我們先使用PHP來對(duì)接ES吧憔鬼。
為了方便使用Laravel來做一個(gè)ES的接入
先引入一些依賴包在composer.json中添加
"ruflin/elastica": "dev-master"
引入了包之后我們先初始化一個(gè)Client
$this->es = new \Elastica\Client([ 'host' => 'x.x.x.x', 'port' => 9200 ]);
#ES默認(rèn)端口9200
拿到了ES對(duì)象,構(gòu)建一個(gè)基于DSL語法的數(shù)組或JSON
$query = [ "query" => [ "bool" => [ "must" => ["match" => ["@fields.ctxt_event" => "打開"]], "must_not" => ["match" => ["@fields.ctxt_event" => "more"]], ], ], "aggs" => [ "toptap" => [ "terms" => [ "field" => "@fields.ctxt_event", "order" => ["_count" => "desc"], "size" => 50 ] ], ]];
#接口中index是索引名稱,doc是文檔的type
$response = $this->es->request(?'index/doc/_search', Request::GET, $query);
此時(shí)就是完成一次接口調(diào)用胃夏,關(guān)于DSL的語法需要進(jìn)行另外的學(xué)習(xí)轴或。
當(dāng)然這一步中是有問題的,因?yàn)檫@是由于聚合查詢中fielddata是在ES5.x默認(rèn)關(guān)閉的,需要手動(dòng)指定開啟仰禀。?
(因?yàn)槲覀兊恼Z句中含有“aggs”參數(shù)表示要聚合結(jié)果)
開啟需要的字段方式:“@fields.ctxt_event“為我們需要聚合字段
$enable = [ "properties" => [ “@fields.ctxt_event”=> [ "type" => "text", "fielddata" => true, "norms" => false ] ]];
$this->es->request("index/_mapping/doc", Request::PUT, $enable);
#index 表示索引名照雁,支持通配符,逗號(hào)分隔比如(logstash2018.*或者logstash2018.01,logstash2018.02)
#doc是記錄的類型對(duì)應(yīng)_type字段的值答恶,一般默認(rèn)是doc
至此完成一次基礎(chǔ)的查詢饺蚊,關(guān)于DSL語法的一些問題請(qǐng)讀者根據(jù)實(shí)際的文檔內(nèi)容進(jìn)行調(diào)整。
那么我們是否可以通過更加簡(jiǎn)單的方式悬嗓?
我們可以安裝elasticsearch-sql插件污呼,之后我們可以調(diào)整查詢方式為
$sql = "SELECT * FROM indexname WHERE? @fields.ctxt_event ='分享作品' OR @fields.ctxt_event ='下載作品' OR @fields.ctxt_event ='收藏點(diǎn)擊' OR @fields.ctxt_event ='分享點(diǎn)擊' OR @fields.ctxt_event ='下載點(diǎn)擊')";?
$url =?'http://' . $this->host . ':' . $this->port . "/_sql";
$ret = $http_client->post($url,[
'body' => $sql
])
這里的http_client只要能發(fā)起post請(qǐng)求的網(wǎng)絡(luò)對(duì)象即可。
此時(shí)的調(diào)用方式就不在需要使用DSL語法,而是轉(zhuǎn)變成sql查詢包竹。
當(dāng)然前提是需要預(yù)先安裝好插件燕酷。
7.ES在Spark中的實(shí)戰(zhàn)
本段內(nèi)容是在Spark中如何對(duì)接ES的數(shù)據(jù)
項(xiàng)目基于sbt構(gòu)建平臺(tái)籍凝,scala語言。
首先我們需要在sbt配置中引入必須的依賴包
libraryDependencies += "org.apache.hadoop" % "hadoop-client" % "2.7.5"libraryDependencies += "org.apache.hadoop" % "hadoop-hdfs" % "2.7.5"
libraryDependencies += "org.apache.hadoop" % "hadoop-common" % "2.7.5"
libraryDependencies += "org.apache.spark" %% "spark-streaming" % "2.2.1"
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.2.1"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.2.1"
libraryDependencies += "org.elasticsearch" % "elasticsearch-hadoop" % "6.1.1"
根據(jù)各自需求可能還需要引入其他的包苗缩,但是這幾個(gè)包是必須引入的静浴。
之后我們開始構(gòu)建Spark
val config = PropertiesUtils.fetchProperties("es.properties")
val host = config.getProperty("es.host")
val port = config.getProperty("es.port")// 生成spark session對(duì)象
val spark = SparkSession .builder() .appName("es") .master("local[4]") //本地調(diào)試打開 .config("es.index.auto.create", "true") .config("pushdown", "true").config("es.nodes", host) .config("es.port", port) .config("es.nodes.wan.only", "true") .config("es.read.field.as.array.include", "tags") .getOrCreate()
val df = spark.sqlContext.read.format("org.elasticsearch.spark.sql").load("index")
df.show(false)
這其中包含了從創(chuàng)建Spark Session,然后從ES中l(wèi)oad需要的index給dataframe挤渐。
至此我們已經(jīng)完全拿到了ES的數(shù)據(jù),關(guān)于后續(xù)的增刪改查另外補(bǔ)充。
8.ES調(diào)優(yōu)
目前根據(jù)使用情況大概介紹一下双絮。
分片優(yōu)化
首先看數(shù)據(jù)每天的增量來確定索引的數(shù)量浴麻,比如我預(yù)估每天的數(shù)據(jù)增量是1GB,那么我一個(gè)索引如果設(shè)置成5個(gè)分片囤攀,基本上這個(gè)索引可以支撐我接近250天的數(shù)據(jù)软免。單節(jié)點(diǎn)中的分片數(shù)量和節(jié)點(diǎn)數(shù)的關(guān)系官方推薦是一個(gè)節(jié)點(diǎn)不要超過三個(gè)分片。
副本分片
主分片的備份焚挠,在分布式查詢中可以提升性能
集群高可用膏萧,高性能
ES提供了自動(dòng)的感知節(jié)點(diǎn),同時(shí)會(huì)通過自動(dòng)將所有主副分片進(jìn)行分配轉(zhuǎn)移蝌衔。
如果是有三個(gè)p0,p1,p2主節(jié)點(diǎn),r0,r1,r2三個(gè)副節(jié)點(diǎn)的自動(dòng)分布噩斟,支持自動(dòng)擴(kuò)容和縮容曹锨。
由于每個(gè)分片都是獨(dú)立的搜索引擎單元,因此水平擴(kuò)容的時(shí)候每個(gè)分片同樣也能獲取更多的硬件資源剃允。
如果我們將每個(gè)主節(jié)點(diǎn)增加更多的副本節(jié)點(diǎn)沛简,在節(jié)點(diǎn)數(shù)夠多的情況下能更加提升查詢性能!
內(nèi)存調(diào)優(yōu)
根據(jù)服務(wù)器內(nèi)存調(diào)整ES最大堆內(nèi)存斥废,不要超過服務(wù)器內(nèi)存60%椒楣,最大不要超過32G。
索引優(yōu)化
增加文件描述符
9.致謝參考鏈接
????ELK + Kafka + Filebeat架構(gòu) :https://blog.csdn.net/remoa_dengqinyi/article/details/77902391