ES能為你解決什么問題,又會(huì)帶來什么問題?
本文轉(zhuǎn)載自微信公眾號(hào)「 寫PHP的老王」,轉(zhuǎn)載本文請(qǐng)聯(lián)系 寫PHP的老王公眾號(hào)。
業(yè)務(wù)需求痛點(diǎn)
- 業(yè)務(wù)增長,查詢條件越來越多,索引越來越多
業(yè)務(wù)發(fā)展初期,數(shù)據(jù)量不多。查詢,寫入都很快。隨著業(yè)務(wù)的發(fā)展,數(shù)據(jù)量增大,出現(xiàn)慢查詢,開始往表里不斷的加索引,保證數(shù)據(jù)查詢效率。但是當(dāng)數(shù)據(jù)量繼續(xù)增大,業(yè)務(wù)查詢?cè)絹碓綇?fù)雜。程序員天天想著這個(gè)表怎么加索引。索引的增加,寫入數(shù)據(jù)的時(shí)間成本越來越高。
- 表數(shù)據(jù)增加,數(shù)據(jù)拆分越來越復(fù)雜
數(shù)據(jù)量增大,開始進(jìn)行分表處理。慢慢的發(fā)現(xiàn),尼瑪,分的表越來越多。再這么下去,這臺(tái)數(shù)據(jù)庫服務(wù)器上都容不下他了,這是要做數(shù)據(jù)分片的操作啊。分表已經(jīng)夠費(fèi)勁了,還要分片?
- 全文檢索功能
嗨,哥們,給我加個(gè)全文搜索的功能。簡單的一句話,你心里十萬個(gè)草泥馬。這么多的數(shù)據(jù)量你讓我搞全文搜索。
上面業(yè)務(wù)通點(diǎn)總結(jié)起來就是要查的快,要分布式,要全文搜。
ES 能解決什么問題
S主要運(yùn)用于全文搜索、數(shù)據(jù)分析, 底層使用開源庫Lucene,擁有豐富的REST API。內(nèi)部分布式的數(shù)據(jù)存儲(chǔ)、倒排索引等設(shè)計(jì),使其可以快速存儲(chǔ)、搜索、分析海量數(shù)據(jù)。典型的使用方和應(yīng)用場(chǎng)景,如github,StackOverflow,elasticsearch+logstash+kibana 一體化的日志分析。
ES 搜索為什么快的原因
對(duì)于mysql中如上的數(shù)據(jù)表,ES會(huì)對(duì)每個(gè)字段的值建立索引,通過索引的值去找數(shù)據(jù),而且這些索引都是在內(nèi)存里面的。
name段索引:
age字段索引
address 字段索引
這樣,當(dāng)我們要找上海市,年齡為21歲的數(shù)據(jù)就能夠通過address,age索引快遞定位到數(shù)據(jù)id=2的是我們需要查找的。
然后在從磁盤中把數(shù)據(jù)id=2的數(shù)據(jù)讀取出來。
上面的其實(shí)就是ES中倒排索引的一個(gè)簡化版本。
實(shí)際上的ES的倒排序使用的是前綴作為索引,同時(shí)會(huì)使用*FST*對(duì)索引數(shù)據(jù)進(jìn)行壓縮,以保證在內(nèi)存的數(shù)據(jù)量不會(huì)因?yàn)樗饕喽鴰肀容^大的內(nèi)存消耗。
對(duì)于上面的數(shù)據(jù)表,如果采用HashMap的方式對(duì)name字段索引的話,索引所占用內(nèi)存20個(gè)字節(jié)。
但是如果轉(zhuǎn)換成FST結(jié)構(gòu)的話,可以用四個(gè)字節(jié)表示name,總共占用內(nèi)存為4+4*3=16。(假設(shè)數(shù)據(jù)范圍只有M,i,e,c) 四個(gè)字符。
ES 分布式數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
- 數(shù)據(jù)分片均衡
分片是 Elasticsearch 在集群中分發(fā)數(shù)據(jù)的關(guān)鍵。文檔存儲(chǔ)在分片中,然后分片分配到集群中的節(jié)點(diǎn)上。當(dāng)集群擴(kuò)容或縮小,Elasticsearch 將會(huì)自動(dòng)在節(jié)點(diǎn)間遷移分片,以使集群保持平衡。
- 數(shù)據(jù)可靠
分片有主分片,復(fù)制分片。復(fù)制分片只是主分片的一個(gè)副本,它可以防止硬件故障導(dǎo)致的數(shù)據(jù)丟失,同時(shí)可以提供讀請(qǐng)求,比如搜索或者從別的 shard 取回文檔。
每個(gè)主分片都有一個(gè)或多個(gè)副本分片,當(dāng)主分片異常時(shí),副本可以提供數(shù)據(jù)的查詢等操作。主分片和對(duì)應(yīng)的副本分片是不會(huì)在同一個(gè)節(jié)點(diǎn)上的 。
- 分布式搜索
分片本身就是一個(gè)完整的搜索引擎,它可以使用單一節(jié)點(diǎn)的所有資源。主分片或者復(fù)制分片都可以處理讀請(qǐng)求——搜索或文檔檢索,所以數(shù)據(jù)的冗余越多,能處理的搜索吞吐量就越大
ES 集群中每個(gè)節(jié)點(diǎn)通過路由都知道集群中的文檔的存放位置,所以每個(gè)節(jié)點(diǎn)都有處理讀寫請(qǐng)求的能力。
在一個(gè)寫請(qǐng)求被發(fā)送到某個(gè)節(jié)點(diǎn)后,該節(jié)點(diǎn)即為協(xié)調(diào)節(jié)點(diǎn),協(xié)調(diào)節(jié)點(diǎn)會(huì)根據(jù)路由公式計(jì)算出需要寫到哪個(gè)分片上,再將請(qǐng)求轉(zhuǎn)發(fā)到該分片的主分片節(jié)點(diǎn)上。如果是查詢操作,則協(xié)調(diào)節(jié)點(diǎn)會(huì)將請(qǐng)求分發(fā)到其他分片上,其他分片查詢結(jié)果之后再由協(xié)調(diào)節(jié)點(diǎn)將數(shù)據(jù)組裝返回。
所以,引入ES,能夠?qū)崿F(xiàn)幫你解決數(shù)據(jù)量多,分布式查詢問題。同時(shí)ES會(huì)自動(dòng)的替你對(duì)所有字段建立索引,以實(shí)現(xiàn)高性能的復(fù)雜聚合查詢,因此只要是存入ES的數(shù)據(jù),無論再復(fù)雜的聚合查詢也可以得到不錯(cuò)的性能,而且你再也不用為如何建立各種復(fù)雜索引而頭痛了。另外,ES支持多種分詞器,對(duì)全文搜索支持更加高效。
ES引入會(huì)有什么樣的問題
- 字段類型無法修改、寫入性能較低和高硬件資源消耗
ES需要在創(chuàng)建字段前要預(yù)先建立Mapping,Mapping中包含每個(gè)字段的類型信息,ES需要根據(jù)Mapping為字段建立合適的索引。由于這個(gè)Mapping的存在,ES中的字段一但建立就不能再修改類型了。ES在數(shù)據(jù)結(jié)構(gòu)靈活度上高于MySQL但遠(yuǎn)不如MongoDB
- 不支持事務(wù),JOIN
- 吃硬件
ES的排序和聚合(Aggregation)操作會(huì)把幾乎所有相關(guān)不相關(guān)的文檔都加載到內(nèi)存中,一個(gè)Query就可以很神奇地吃光所有內(nèi)存,現(xiàn)在新的Lucene版本優(yōu)化了基于硬盤的排序,但也僅當(dāng)你使用SSD的情況下,才不會(huì)犧牲過多的搜索性能。其他的問題還包括,大量的增量寫操作會(huì)導(dǎo)致大量的后臺(tái)Merge,CPU和硬盤讀寫都會(huì)很容易達(dá)到瓶頸。ES確實(shí)在橫向Scale方面做的很出色,但前提是有足夠的預(yù)算買硬件。
- 數(shù)據(jù)實(shí)時(shí)性
每當(dāng)有新增的數(shù)據(jù)時(shí),就將其先寫入到內(nèi)存中,在內(nèi)存和磁盤之間是文件系統(tǒng)緩存,當(dāng)達(dá)到默認(rèn)的時(shí)間(1秒鐘)或者內(nèi)存的數(shù)據(jù)達(dá)到一定量時(shí),會(huì)觸發(fā)一次刷新(Refresh),將內(nèi)存中的數(shù)據(jù)生成到一個(gè)新的段上并緩存到文件緩存系統(tǒng) 上,稍后再被刷新到磁盤中并生成提交點(diǎn)。因此,從Index請(qǐng)求到對(duì)外可見能夠被搜到,最少要1秒鐘的數(shù)據(jù)延時(shí)。
- 不支持?jǐn)?shù)據(jù)的權(quán)限管理
總結(jié)
ES香不香看你怎么用。有人用的很爽,有人用的很痛苦。用好了就少加班調(diào)索引,調(diào)sql。用不好就常加班調(diào)ES。
優(yōu)點(diǎn):
- 1.高并發(fā)
- 2.容錯(cuò)能力比mg強(qiáng)。比如1主多從,主片掛了從片會(huì)自動(dòng)頂上
- 3.滿足大數(shù)據(jù)下實(shí)時(shí)讀寫需求,無需分庫(不存在庫的概念)。
- 4.易擴(kuò)展。分片數(shù)據(jù)自動(dòng)均衡
- 5.支持較復(fù)雜的條件查詢,group by、排序都不是問題
缺點(diǎn):
- 1.不支持事務(wù)
- 2.讀寫有一定延時(shí)
- 3.無權(quán)限管理
- 4.吃硬件