自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

數(shù)據(jù)庫(kù):MySQL、HBase、ElasticSearch三者對(duì)比

數(shù)據(jù)庫(kù)
MySQL:關(guān)系型數(shù)據(jù)庫(kù),主要面向OLTP,支持事務(wù),支持二級(jí)索引,支持sql,支持主從、Group Replication架構(gòu)模型(本文全部以Innodb為例,不涉及別的存儲(chǔ)引擎)。

1、概念介紹

MySQL:關(guān)系型數(shù)據(jù)庫(kù),主要面向OLTP,支持事務(wù),支持二級(jí)索引,支持sql,支持主從、Group Replication架構(gòu)模型(本文全部以Innodb為例,不涉及別的存儲(chǔ)引擎)。

HBase:基于HDFS,支持海量數(shù)據(jù)讀寫(尤其是寫),支持上億行、上百萬(wàn)列的,面向列的分布式NoSql數(shù)據(jù)庫(kù)。天然分布式,主從架構(gòu),不支持事務(wù),不支持二級(jí)索引,不支持sql。ElasticSearch:簡(jiǎn)稱ES是一款分布式的全文檢索框架,底層基于Lucene技術(shù)實(shí)現(xiàn),雖然ES也提供存儲(chǔ),檢索功能,但我一直不認(rèn)為ES是一款數(shù)據(jù)庫(kù),但是隨著ES功能越來越強(qiáng)大,與數(shù)據(jù)庫(kù)的界限也越來越模糊。分布式,P2P架構(gòu),但不支持事務(wù),采用倒排索引提供全文檢索。

2、數(shù)據(jù)存儲(chǔ)方式

假設(shè)有這樣一張人員信息表:

 

MySQL數(shù)據(jù)庫(kù)要提前定義表結(jié)構(gòu),數(shù)據(jù)表共有多少列(屬性)需要提前定義好,并且同時(shí)需要定義好每個(gè)列所占用的存儲(chǔ)空間。數(shù)據(jù)以行為單位組織在一起的,假如某一行的某一列沒有數(shù)據(jù),也需要占用存儲(chǔ)空間。

HBase則是以列為單位存儲(chǔ)數(shù)據(jù),每一列就是一個(gè)key-value,HBase的表列(屬性)不需要提前定義,而且列可以動(dòng)態(tài)擴(kuò)展,比如人員信息表中需要添加一個(gè)新的“address”字段,MySQL需要提前alter表增加字段,HBase可以直接插入即可。

ES比較靈活,索引中的field類型可以提前定義(定義mapping),也可以不定義,如果不定義,會(huì)有一個(gè)默認(rèn)類型,不過出于可控性考慮,關(guān)鍵字段建議提前定義好。(Solr中必須提前定義好schema.xml文件)

上圖展示了數(shù)據(jù)在MySQL和HBase中存儲(chǔ)差異(和真實(shí)的情況還有差距),可以看到即使第二條記錄的sex字段為空,MySQL依然會(huì)為該字段保留空間,因?yàn)楹罄m(xù)有可能會(huì)有update語(yǔ)句來更新該記錄,補(bǔ)上sex內(nèi)容。而HBase則是把每一列都看做是一條記錄,row+列名作為key,data作為value,依次存放。假如某一行的某一個(gè)列沒有數(shù)據(jù),則直接跳過該列。針對(duì)稀疏矩陣的大表,HBase能大大節(jié)省存儲(chǔ)空間。

看到這里,大家是否會(huì)有一個(gè)疑問:使用HBase存儲(chǔ)時(shí),假如此時(shí)需要添加第二行的sex內(nèi)容,如何實(shí)現(xiàn)呢,數(shù)據(jù)是否連續(xù)?后面介紹讀寫流程會(huì)解釋。

不一樣的ES

ES的存儲(chǔ)方式和上面兩個(gè)都不一樣,MySQL和HBase是將數(shù)據(jù)按不同的方式進(jìn)行存儲(chǔ),好歹它們存的還是數(shù)據(jù),而ES則存的是倒排索引。我們先來了解一下什么是倒排索引,以及為什么需要倒排索引(Inverted Index):我們肯定都會(huì)這樣的經(jīng)歷:偶然看到一段很好的文字,但是卻不知道出處,這時(shí)候去圖書館,一個(gè)一個(gè)翻找,無(wú)疑是大海撈針,這個(gè)時(shí)候便有了全文檢索這項(xiàng)技術(shù),而它最核心的就是倒排索引。假如有如下文檔:

我們想要知道有哪些文檔含有you這個(gè)關(guān)鍵字,首先可以創(chuàng)建一個(gè)倒排索引,格式如下:

前面的部分叫做dictionary(字典),里面的每個(gè)單詞叫做term,后面的文檔列表叫做psoting-list,list中記錄了所有含有該term的文檔id,兩個(gè)組合起來就是一個(gè)完成的倒排索引(Inverted Index)。能夠看出,假如需要查找含有“you”的文檔時(shí),根據(jù)dictionary然后找到對(duì)應(yīng)的posting-list即可。

而全文檢索中,創(chuàng)建Inverted Index是最關(guān)鍵也是最耗時(shí)的過程,而且真正的Inverted Index結(jié)構(gòu)也遠(yuǎn)比圖中展示的復(fù)雜,不僅需要對(duì)文檔進(jìn)行分詞(ES里中文可以自定義分詞器),還要計(jì)算TF-IDF,方便評(píng)分排序(當(dāng)查找you時(shí),評(píng)分決定哪個(gè)doc顯示在前面,也就是所謂的搜索排名),壓縮等操作。每接收一個(gè)document,ES就會(huì)將其信息更新在倒排索引中。

可以看出ES和MySQL、HBase的存儲(chǔ)還是有很大的區(qū)別。而且ES不僅包含倒排索引,默認(rèn)同時(shí)還會(huì)把文檔doc存儲(chǔ)起來,所以當(dāng)我們使用ES時(shí),也能拿到完整的文檔信息,所以某種程度上,感覺就像在使用數(shù)據(jù)庫(kù)一樣,但是也可以配置不存儲(chǔ)文檔信息,這時(shí)只能根據(jù)查詢條件得到文檔id,并不能拿到完整的文檔內(nèi)容。

總結(jié):

MySQL:行存儲(chǔ)的方式比較適合OLTP業(yè)務(wù)。HBase:列存儲(chǔ)的方式比較適合OLAP業(yè)務(wù),而HBase采用了列族的方式平衡了OLTP和OLAP,支持水平擴(kuò)展,如果數(shù)據(jù)量比較大、對(duì)性能要求沒有那么高、并且對(duì)事務(wù)沒有要求的話,HBase可以考慮。ES:ES默認(rèn)對(duì)所有字段都建了索引,所以比較適合復(fù)雜的檢索或全文檢索。

3、容災(zāi)對(duì)比

3.1 MySQL

單節(jié)點(diǎn):

現(xiàn)在的數(shù)據(jù)庫(kù)普遍采用write ahead log策略來避免數(shù)據(jù)丟失,wal機(jī)制簡(jiǎn)單的解釋就是:在提交CUD操作,數(shù)據(jù)寫入內(nèi)存的同時(shí),也要寫一份到log文件中,而且要保證log數(shù)據(jù)落盤成功后才能向client返回操作成功,假如此時(shí)數(shù)據(jù)庫(kù)宕機(jī),已經(jīng)提交到內(nèi)存的數(shù)據(jù)還沒來得及刷回磁盤,重啟數(shù)據(jù)庫(kù)后可以通過回放log文件來恢復(fù)內(nèi)存中的數(shù)據(jù)。

問題又來了:寫log的話,對(duì)性能影響會(huì)不會(huì)很大?其實(shí)多少還是有點(diǎn)影響的,不過log文件是順序?qū)懭?,相?duì)來說為了保證數(shù)據(jù)完整性,這點(diǎn)性能損失還是可以接受的。

單機(jī)情況下,MySQL的innodb通過redo log和checkpoint機(jī)制來保證數(shù)據(jù)的完整性。因?yàn)榕耹og越寫越大,占用過多磁盤,而且當(dāng)log特別大的時(shí)候,恢復(fù)起來也比較耗時(shí)。而checkpoint的出現(xiàn)就是為了解決這些問題。

checkpoint機(jī)制保證了之前的log數(shù)據(jù)一定已經(jīng)刷回磁盤,當(dāng)數(shù)據(jù)庫(kù)宕機(jī)時(shí),只需要將checkpoint之后的log回放即可,數(shù)據(jù)庫(kù)會(huì)定時(shí)做checkpoint,這樣就保證了數(shù)據(jù)庫(kù)恢復(fù)的效率。

但是考慮到如果硬件故障時(shí)機(jī)器無(wú)法啟動(dòng),或者磁盤故障時(shí)數(shù)據(jù)無(wú)法恢復(fù),checkpoint+redo log方案也就不起作用了,為了防止這種故障,MySQL還提供了master-slave和group replication 集群級(jí)別的容災(zāi)方案。

Master-Slave架構(gòu)主要思路是:master負(fù)責(zé)業(yè)務(wù)的讀寫請(qǐng)求,然后通過binlog復(fù)制到slave節(jié)點(diǎn),這樣如果主庫(kù)因?yàn)椴豢煽咕芤蛩責(zé)o法恢復(fù)時(shí),從庫(kù)可以提供服務(wù),這里我們用了“復(fù)制“這個(gè)詞,而不是”同步“,因?yàn)榛赽inlog復(fù)制的方案并不能做到主從數(shù)據(jù)強(qiáng)一致,這種主從同步方式會(huì)導(dǎo)致主庫(kù)掛掉之后從庫(kù)有可能丟失少量的數(shù)據(jù)。

正是因?yàn)橹鲝募軜?gòu)存在數(shù)據(jù)不一致的問題,所以MySQL5.7出現(xiàn)了Mysql Group Replication方案,mgr采用paxos協(xié)議實(shí)現(xiàn)了數(shù)據(jù)節(jié)點(diǎn)的強(qiáng)同步,保證了所有節(jié)點(diǎn)都可以寫數(shù)據(jù),并且所有節(jié)點(diǎn)讀到的也是最新的數(shù)據(jù)。

3.2 HBase

HBase的容災(zāi)和MySQL的單機(jī)容災(zāi)有些類似,但具體實(shí)現(xiàn)上還是很有自己的特點(diǎn)。

在介紹HBase容災(zāi)前,我們先來了解一下HBase和HDFS的關(guān)系:HBase中的數(shù)據(jù)都是存放在HDFS上,可以簡(jiǎn)單理解HBase分為兩層:

一層為NoSql service(即提供分布式檢索服務(wù))

一層是分布式文件系統(tǒng)(數(shù)據(jù)真正存放的位置,目前采用HDFS)。HBase中region分布在不同的regionserver上,client端通過meta表來定位數(shù)據(jù)在在哪個(gè)regionserver的region上,然后獲取數(shù)據(jù),但是數(shù)據(jù)有可能并不一定在該regionserver本地保存,每個(gè)region都知道自己對(duì)應(yīng)的數(shù)據(jù)在HDFS的哪些數(shù)據(jù)塊上,最后通過訪問HDFS來獲取數(shù)據(jù),尤其當(dāng)HBase和HDFS部署在不同的集群上時(shí),數(shù)據(jù)的讀寫完全是通過RPC來實(shí)現(xiàn),為了減少RPC的開銷,保證服務(wù)穩(wěn)定,往往會(huì)將HBase和HDFS部署在同一個(gè)集群。

同理,當(dāng)一個(gè)regionserver掛了,region可以快速切換到別的regionserver上,因?yàn)橹簧婕暗交胤臠og,并不會(huì)移動(dòng)已經(jīng)落盤的數(shù)據(jù),而且HBase也會(huì)控制log的大小,來減少恢復(fù)時(shí)間。

HBase也是采用寫log的方式防止數(shù)據(jù)丟失,數(shù)據(jù)寫內(nèi)存的同時(shí),同時(shí)也會(huì)寫入HLog,HLog也是存儲(chǔ)在HDFS上,寫入HLog后才會(huì)認(rèn)為數(shù)據(jù)寫成功,某個(gè)regionserver掛掉之后,master將故障機(jī)器上的regions調(diào)度到別的regionserver上,regionserver通過回放HLog來恢復(fù)region的數(shù)據(jù),恢復(fù)成功后,region重新上線,由于log是直接寫在HDFS上,所以不用擔(dān)心單個(gè)節(jié)點(diǎn)掛掉log數(shù)據(jù)丟失的問題。

這里引出一個(gè)問題:回放HLog的時(shí)候,正在被恢復(fù)的region會(huì)短時(shí)間不可用,直到HLog回放成功。HBase1.0版本中加入了region replicas功能,也就是提供一個(gè)slave region,當(dāng)主region掛掉的時(shí)候,依然可以通過slave replicas來讀數(shù)據(jù),但是slave不提供write,而且slave replicas和primary region并不是強(qiáng)同步的,并不一定總能讀到最新的數(shù)據(jù),所以開啟該功能時(shí),也要考慮自己業(yè)務(wù)是否必須要求強(qiáng)一致。

HBase也提供了cluster replication,目的是為了做機(jī)房級(jí)的容災(zāi),boss說現(xiàn)在cluster replication功能還有些bug,目前也在積極優(yōu)化改進(jìn),相信以后會(huì)cluster replication會(huì)越來越完善。

3.3 ES:

ES的容災(zāi)也是采用寫log的方式,與HBase不同的是,ES的節(jié)點(diǎn)保存各自的log,這點(diǎn)跟MySQL類似,log是存放在本地的,這也就存在和MySQL一樣的問題,假如機(jī)器宕機(jī)或硬盤故障,log數(shù)據(jù)也會(huì)丟失,所以index每個(gè)shard也有主備,默認(rèn)配置是一個(gè)primary shard,一個(gè)replica shard,當(dāng)然也可以配置多個(gè)replica。

默認(rèn)情況下:primary shard首先接收client端發(fā)送過來的數(shù)據(jù),然后將數(shù)據(jù)同步到replica shard中,當(dāng)replica shard也寫入成功后,才會(huì)告知client數(shù)據(jù)已正確寫入,這樣就防止數(shù)據(jù)還沒寫入replica shard時(shí),primary掛掉導(dǎo)致的數(shù)據(jù)丟失。

又到了提問環(huán)節(jié),如果有一個(gè)replica節(jié)點(diǎn)出了問題,比如網(wǎng)絡(luò)故障無(wú)法寫入,那豈不是數(shù)據(jù)一直寫入不成功了?所以ES的master維護(hù)了一個(gè)in-sync set,里面保存了目前存活、且與primary同步的replica集合,只要set中的replica同步完成即認(rèn)為數(shù)據(jù)寫入成功??紤]到一種情況:所有的replica因?yàn)榫W(wǎng)絡(luò)故障都下線了,in-sync set此時(shí)為空,數(shù)據(jù)只在primary中保留一份,很有可能因primary故障而導(dǎo)致丟數(shù)據(jù),所以ES新增了wait_for_active_shards參數(shù),只有當(dāng)存活的replica數(shù)大于該參數(shù)時(shí),才能正常寫入,若不滿足,則停止寫服務(wù)。

(這是5.X版本的實(shí)現(xiàn),由于ES版本更新過快,這和2.X之前的版本有些差異,5.X中in-sync set的方式和Kafka的容災(zāi)模式非常類似,但和Kafka有一點(diǎn)區(qū)別:ES的primary負(fù)責(zé)寫服務(wù),但是primary和replica都可以提供讀服務(wù),而Kafka只有primary partition提供讀寫服務(wù),replica只是同步primary上的數(shù)據(jù),并不提供讀。

4、讀寫方式

4.1 Mysql

MySQL的Innodb中的數(shù)據(jù)是按主鍵的順序依次存放,主鍵即為聚簇索引(對(duì)聚簇索引和非聚簇索引不了解同學(xué)可以看看這篇文章),索引采用B+樹結(jié)構(gòu)進(jìn)行組織。

從圖中可以看出,數(shù)據(jù)是按聚簇索引順序依次存放,假設(shè)下面一些場(chǎng)景:

1.查詢

Innodb中主鍵即為聚簇索引,假如根據(jù)主鍵查詢,聚簇索引的葉子節(jié)點(diǎn)存放就是真正的數(shù)據(jù),可以直接查到相應(yīng)的記錄。假如是二級(jí)索引查詢,那么需要先通過二級(jí)索引找到該記錄的主鍵,然后根據(jù)主鍵通過聚簇索引找到對(duì)應(yīng)的記錄,這里多了一個(gè)索引查找的過程。

2.插入

順序插入:因?yàn)镮nnodb的數(shù)據(jù)是按聚簇索引的順序依次存放的,如果是根據(jù)主鍵索引的順序插入,即插入的數(shù)據(jù)的主鍵是連續(xù)的,因?yàn)槭琼樞騣o,所以插入效率會(huì)較高。

隨機(jī)插入:假如每次插入的數(shù)據(jù)主鍵是不連續(xù)的,MySQL需要取出每條記錄對(duì)應(yīng)的物理block,會(huì)引起大量的隨機(jī)io,隨機(jī)io操作和順序io的性能差距很大,尤其是機(jī)械盤。

(Kafka官網(wǎng)提到一個(gè)機(jī)械盤的順序?qū)懩苓_(dá)到600M/s,而隨機(jī)寫可能只有100k/s。As a result the performance of linear writes on aJBODconfiguration with six 7200rpm SATA RAID-5 array is about 600MB/sec but the performance of random writes is only about 100k/sec—a difference of over 6000X.這也是為什么HBase、ES將所有的insert、update、delete操作都統(tǒng)一看成順序?qū)懖僮鳎苊怆S機(jī)io)

note:這也是為什么MySQL的主鍵通常定義為自增id,不涉及業(yè)務(wù)邏輯,這樣新數(shù)據(jù)插入時(shí)能保證是順序io。另外MySQL為了提高隨機(jī)io的性能,提供了insert buffer的功能。

3.更新 & 刪除

update和delete如果不是順序的話,也會(huì)包含大量的隨機(jī)io,當(dāng)然MySQL都針對(duì)隨機(jī)io都進(jìn)行了一些優(yōu)化,盡量減少隨機(jī)io帶來的性能損失。

4.2 HBase

HBase不支持二級(jí)索引,它只有一個(gè)主鍵索引,采用LSM樹。

HBase是一個(gè)分布式系統(tǒng),這點(diǎn)跟MySQL不同,它的數(shù)據(jù)是分散不同的server上,每個(gè)table由一個(gè)或多個(gè)region組成,region分散在集群中的server上,一個(gè)server可以負(fù)責(zé)多個(gè)region。這里有一點(diǎn)需要特別注意:table中各個(gè)region的存放數(shù)據(jù)的rowkey(主鍵)范圍是不會(huì)重疊的,可以認(rèn)為region上數(shù)據(jù)基于rowkey全局有序,每個(gè)region負(fù)責(zé)它自己的那一部分的數(shù)據(jù)。

1.查詢

假如我們要查詢r(jià)owkey=150的這條記錄,首先從zk中獲取hbase:meta表(存放region和key的對(duì)應(yīng)關(guān)系的元數(shù)據(jù)表)的位置,通過查詢meta表得知rowkey=150的數(shù)據(jù)在哪個(gè)server的哪個(gè)region上。

2.插入

上圖粗略的展示了HBase的region的結(jié)構(gòu),region不單單是一個(gè)文件,它是由一個(gè)memstore和多個(gè)storeFile組成(storeFile上的上限可以配置)。插入數(shù)據(jù)時(shí)首先將數(shù)據(jù)寫入memstore,當(dāng)memstore大小達(dá)到一定閾值,將memstore flush到硬盤,變成一個(gè)新的storeFile。flush的時(shí)候會(huì)對(duì)memstore中的數(shù)據(jù)進(jìn)行排序,壓縮等操作??梢钥吹絾蝹€(gè)storeFile中的數(shù)據(jù)是有序的,但是region中的storeFile間的數(shù)據(jù)不是全局有序的。

這樣有的好處就是:不管主鍵是否連續(xù),所有的插入一律變成順序?qū)懀蟠筇岣吡藢懭胄阅堋?/p>

看到這里大家可能會(huì)有一個(gè)疑問:這種寫入方式導(dǎo)致了一條記錄如果不是一次性插入,很可能分散在不同的storeFile中,那在該region上面查詢一條記錄時(shí),怎么知道去找哪個(gè)storeFile呢?答案就是:全部查詢。HBase會(huì)采用多路歸并的方式,對(duì)該region上的所有storeFile進(jìn)行查詢,直到找到符合條件的記錄。所以HBase的擁有很好的寫入性能,但是讀性能較差。

當(dāng)然HBase也做了很多優(yōu)化,比如每個(gè)storeFile都有自己的index、用于過濾的bloom filter、compaction:按可配置的方式將多個(gè)storeFile合并成一個(gè),減少檢索時(shí)打開的文件數(shù)。

3.更新 & 刪除

HBase將更新和刪除也全部看做插入操作,用timestamp和delete marker來區(qū)分該記錄是否是最新記錄、是否需要?jiǎng)h除。也正是因?yàn)檫@樣,除了查詢,其他的操作統(tǒng)一轉(zhuǎn)換成了順序?qū)?,保證了HBase高效的寫性能。

4.3 ES

ES的也是一個(gè)分布式系統(tǒng),與ES類似的還有一個(gè)叫Solr的項(xiàng)目,都是基于Lucene的全文檢索分布式框架,有興趣的可以去Lucene官網(wǎng)了解,這里就不做對(duì)比了。

上如展示了ES和傳統(tǒng)數(shù)據(jù)庫(kù)的概念對(duì)比。下面的介紹中,統(tǒng)一使用index對(duì)應(yīng)DB中table,doc對(duì)應(yīng)table中的記錄,field對(duì)應(yīng)row中的一列。

ES集群由一個(gè)或多個(gè)node組成,一個(gè)node即為一個(gè)ES服務(wù)進(jìn)程。一個(gè)index由多個(gè)分片shard組成,shard分散在各個(gè)node上面,每個(gè)shard都采用Lucene來創(chuàng)建倒排索引,維護(hù)各自的索引數(shù)據(jù)。

圖中的一個(gè)小方框即為一個(gè)shard,出于容災(zāi)考慮,每個(gè)shard都會(huì)有多副本,副本個(gè)數(shù)可以配置,默認(rèn)為2,綠色的即為primary shard,灰色的即為replica shard。

1.插入

先來說說寫入吧,由于有多個(gè)shard,請(qǐng)求過來時(shí),如何判斷寫入到哪個(gè)shard呢,ES中每個(gè)doc都會(huì)有一個(gè)唯一id,默認(rèn)會(huì)對(duì)id取hash值,根據(jù)shard的個(gè)數(shù)mode到對(duì)應(yīng)的shard上,默認(rèn)情況下shard中的數(shù)據(jù)id不是全局有序的,這點(diǎn)和Mysql、HBase有很大區(qū)別。

ES的寫入和HBase有些類似,也是將所有的寫操作變成順序?qū)懀彩窍葘?shù)據(jù)寫入內(nèi)存,然后一段時(shí)間后會(huì)將內(nèi)存數(shù)據(jù)flush到磁盤,磁盤的索引文件會(huì)定時(shí)進(jìn)行merge,保證索引文件不會(huì)過多而影響檢索性能。

另外提一點(diǎn),數(shù)據(jù)存入ES后并不是立馬就能檢索到,這點(diǎn)跟MySQL和HBase,或者說跟數(shù)據(jù)庫(kù)系統(tǒng)是完全不一樣的。主要是因?yàn)橛捎贗nverted Index結(jié)構(gòu)的復(fù)雜,需要一個(gè)專門的indexReader來查詢數(shù)據(jù),但是indexReader是以snapshot的方式打開的索引,也就是說indexReader看不到之后的新數(shù)據(jù)。所以ES提供了一個(gè)refresh功能,refresh會(huì)重新打開indexReader,使其能夠讀到最新的數(shù)據(jù)。默認(rèn)refresh的間隔是1s,所以ES自稱是近實(shí)時(shí)檢索功能。

說到順序?qū)?這時(shí)候大家可能會(huì)想:那ES的寫入速度和HBase差不多嘍?那,其實(shí)不是的,不止不如而且差的還不是一點(diǎn)點(diǎn),因?yàn)镋S多了兩個(gè)最關(guān)鍵的步驟:build index和refresh index!這兩個(gè)過程是很耗時(shí)的: build index時(shí)需要分詞、計(jì)算權(quán)重等復(fù)雜的操作(對(duì)inverted index創(chuàng)建,檢索感興趣的,可以參考《信息檢索導(dǎo)論》)。而refresh會(huì)重新打開index,這兩個(gè)過程加起來導(dǎo)致ES接收文檔的速率并不高(可以通過bulk方式來加快數(shù)據(jù)導(dǎo)入)。但也正是因?yàn)檫@些過程才使ES有強(qiáng)大的檢索功能。(雖然我insert慢,但是我花樣多呀^ ^)

2.讀取

每個(gè)node都可以接收讀request,然后該node會(huì)把request分發(fā)到含有該index的shard的節(jié)點(diǎn)上,對(duì)應(yīng)的節(jié)點(diǎn)會(huì)查詢、并計(jì)算出符合條件的文檔,排序后結(jié)果匯聚到分發(fā)request的node(所以查詢請(qǐng)求默認(rèn)會(huì)輪循的將發(fā)送到各個(gè)節(jié)點(diǎn)上,防止請(qǐng)求全部打到一個(gè)節(jié)點(diǎn)),由該node將數(shù)據(jù)返回給client。(ES也支持指定shard查詢,默認(rèn)是根據(jù)文檔id進(jìn)行路由,相當(dāng)于主鍵查詢,但是假如不能確定數(shù)據(jù)在哪個(gè)shard上時(shí),還是需要查詢所有shard)

這里要強(qiáng)調(diào)一下,由于ES支持全文檢索,根據(jù)Inverted Index的特性,大部分情況下,一個(gè)關(guān)鍵字對(duì)應(yīng)了很多的doc,如果全部返回,數(shù)據(jù)量較大,會(huì)對(duì)集群造成較大壓力,所以ES默認(rèn)只返回權(quán)重最高的前20條記錄(可配置),也可以通過scroll功能獲取全部數(shù)據(jù)。類似的場(chǎng)景跟我們平時(shí)使用baidu、google是一樣的,我們使用搜索引擎時(shí),往往是希望得到關(guān)聯(lián)性最強(qiáng)的top N文檔,并不關(guān)心全部文檔有多少個(gè),這也是為什么要計(jì)算權(quán)重的原因。

現(xiàn)在的ES的功能越來越豐富,不僅僅包含全文檢索的功能,而且還有統(tǒng)計(jì)分析等功能,說它是全文檢索框架吧,它比全文檢索功能要豐富,說它是數(shù)據(jù)庫(kù)吧,但是它不支持事務(wù),只能說現(xiàn)在各個(gè)框架之間的界限越來越模糊了。

3.更新 &刪除

ES的更新和刪除和HBase類似,也是全部看做是插入操作,通過timestamp和delete marker來區(qū)分。

又到了問題環(huán)節(jié) :D :既然這種將更新刪除統(tǒng)一變成順序?qū)懙姆绞侥軌蛱岣邔懶阅埽撬y道沒有什么壞處嗎?

答案是肯定有的呀,這種方式能夠有效的提升寫性能,但是存在一個(gè)很大的問題就是后臺(tái)經(jīng)常會(huì)需要merge,而merge是一個(gè)非常耗資源的過程,對(duì)于某些穩(wěn)定性要求較高的業(yè)務(wù)來說,這是不能接受的,但是不merge的話,又會(huì)降低查詢性能(過多的小文件影響查詢性能)。目前通用的做法是盡量選擇業(yè)務(wù)低峰期進(jìn)行merge操作。

5、使用場(chǎng)景

說了這么多,其實(shí)還是希望對(duì)MySQL,HBase,ES各自的實(shí)現(xiàn)做下對(duì)比,方便我們根據(jù)業(yè)務(wù)特點(diǎn)選擇最合適的存儲(chǔ)、檢索方案。下面說一下筆者在工作中使用的經(jīng)驗(yàn):

5.1 MySQL

MySQL在三款中最為成熟,而且支持事務(wù),支持二級(jí)索引,容災(zāi)備份方案也最為成熟,所以線上核心業(yè)務(wù)Mysql是不二之選(當(dāng)然如果不差錢,Oracle也挺不錯(cuò),而且出問題自己解決不了的話,打電話就可以了,手動(dòng)斜眼)。

5.2 HBase

HBase因?yàn)槠鋸?qiáng)大的寫入能力和水平擴(kuò)展能力,比較適合存儲(chǔ)日志,用戶行為等數(shù)據(jù)量比較大的數(shù)據(jù),這種數(shù)據(jù)一般不涉及事務(wù)級(jí)別的讀寫,對(duì)二級(jí)索引的需求也不是很高。而且HBase的主鍵不像Mysql,往往是涉及到業(yè)務(wù)邏輯的,如果查詢條件單一的話,可以把直接把需要查詢的字段作為主鍵的一部分,類似MySQL的聯(lián)合索引,來提供檢索功能。

5.3 ES

ES現(xiàn)在不僅提供全文檢索,還提供統(tǒng)計(jì)功能,并且提供的Restful接口非常好用,配上Kibana還可以進(jìn)行圖形化展示,第三方插件也很豐富。雖然ES可以水平擴(kuò)展,但是考慮到ES的大部分檢索都會(huì)檢索該index的所有shard,如果單個(gè)index數(shù)據(jù)過大,性能多少也會(huì)受到影響,所以單個(gè)index的大小最好控制在一定的范圍,比如存儲(chǔ)用戶行為日志的index,可以每隔一段時(shí)間歸一次檔,創(chuàng)建新的index,做到冷熱分離。而且ES也可以作為MySQL或HBase的索引來使用,雖然Mysql也有索引功能,但是過多的索引往往會(huì)拖累MySQL的性能,并且線上MySQL數(shù)據(jù)庫(kù)一般也不允許執(zhí)行統(tǒng)計(jì)類的sql,這時(shí)可以用ES輔助實(shí)現(xiàn)統(tǒng)計(jì),HBase因?yàn)橹挥兄麈I檢索,所以更需要二級(jí)索引的功能。

舉一個(gè)筆者前司組合使用的場(chǎng)景:trace系統(tǒng)的log數(shù)據(jù)以HBase作為主要存儲(chǔ),同時(shí)最近三個(gè)月的數(shù)據(jù)也在ES里面保留一份,ES主要用來完成各種復(fù)雜檢索、統(tǒng)計(jì)。但數(shù)據(jù)同步需要業(yè)務(wù)自己實(shí)現(xiàn),當(dāng)然trace業(yè)務(wù)對(duì)一致性要求不那么高,也可以忽略這個(gè)問題。

tip:將數(shù)據(jù)庫(kù)的數(shù)據(jù)向ES中同步的時(shí)候,因?yàn)榫W(wǎng)絡(luò)延遲等問題,到達(dá)的順序可能會(huì)亂序,這時(shí)老數(shù)據(jù)有可能會(huì)覆蓋新的數(shù)據(jù),ES提供了一個(gè)version功能,可以將數(shù)據(jù)的timestamp作為version值,防止舊version的數(shù)據(jù)覆蓋新version的數(shù)據(jù)。

總結(jié)

傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)有著強(qiáng)大的事物處理能力,滿足了大部分線上業(yè)務(wù)需求,但是水平擴(kuò)展性一直是一個(gè)頭疼的問題,NoSql數(shù)據(jù)庫(kù)雖然解決了水平擴(kuò)展問題,但是功能太單一,現(xiàn)在越來越多的公司開始著手研究新一代NewSQL數(shù)據(jù)庫(kù),結(jié)合了關(guān)系型數(shù)據(jù)庫(kù)的優(yōu)點(diǎn)外還擁有水平擴(kuò)展能力,比如淘寶的Oceanbase,PingCAP的TiDB,國(guó)外的CockroachDB,讓我們做好擁抱NewSQL的準(zhǔn)備吧。

 

責(zé)任編輯:姜華 來源: IT技術(shù)分享社區(qū)
相關(guān)推薦

2021-04-27 07:42:35

數(shù)據(jù)庫(kù)MySQLSQLServer

2011-06-15 10:28:37

Qt QWidget QMainWindo

2011-05-20 13:45:30

Java

2013-03-29 09:28:41

2016-11-04 13:56:46

大數(shù)據(jù)物聯(lián)網(wǎng)智慧城市

2017-02-10 09:00:03

HadoopSparkStorm

2021-03-02 11:32:03

云計(jì)算大數(shù)據(jù)人工智能

2021-03-17 10:52:56

云計(jì)算大數(shù)據(jù)人工智能

2011-07-08 16:02:54

HBase

2014-02-27 10:08:33

NoSQL

2019-07-08 10:36:34

數(shù)據(jù)庫(kù)WebNoSQL

2010-09-26 14:32:34

JDKJREJVM

2024-01-07 12:02:55

URLURIURN

2009-12-04 19:23:48

SolarisLinuxFreeBSD

2024-06-26 19:14:53

2011-07-13 09:58:15

HBase

2023-07-06 15:05:34

矢量數(shù)據(jù)庫(kù)數(shù)據(jù)庫(kù)

2010-09-27 11:32:41

JVMJREJDK

2020-02-16 15:20:18

存儲(chǔ)類型比較

2011-04-02 09:33:13

MySQL數(shù)據(jù)庫(kù)查詢效率
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)