ElasticSearch index 剖析
ElasticSearch index 剖析
在看ElasticSearch權(quán)威指南基礎(chǔ)入門中關(guān)于:分片內(nèi)部原理這一小節(jié)內(nèi)容后,大致對ElasticSearch的索引、搜索底層實(shí)現(xiàn)有了一個(gè)初步的認(rèn)識。記錄一下在看文檔的過程中碰到的問題以及我的理解。此外,在文章的末尾,還討論分布式系統(tǒng)中的主從復(fù)制原理,以及采用這種副本復(fù)制方案帶來的數(shù)據(jù)一致性問題。
ElasticSearch index 操作背后發(fā)生了什么?
更具體地,就是執(zhí)行PUT操作向ElasticSearch添加一篇文檔時(shí),底層發(fā)生的一系列操作。
PUT user/profile/10 {"content":"向user索引中添加一篇id為10的文檔" }通過PUT請求發(fā)起了索引新文檔的操作,該操作能夠執(zhí)行的前提是:集群中有“一定數(shù)量”的活躍 shards。這個(gè)配置由wait_for_active_shards指定。ElasticSearch關(guān)于分片有2個(gè)重要的概念:primary shard 和 replica。在定義索引的時(shí)候指定索引有幾個(gè)主分片,以及每個(gè)主分片有多少個(gè)副本。比如:
PUT user {"settings": {"number_of_shards": 3,"number_of_replicas": 2},介紹一下集群的環(huán)境:ElasticSearch6.3.2三節(jié)點(diǎn)集群。定義了一個(gè)user索引,該索引有三個(gè)主分片,每個(gè)主分片2個(gè)副本。如圖,每個(gè)節(jié)點(diǎn)上有三個(gè)shards:一個(gè) primary shard,二個(gè)replica
wait_for_active_shards
To improve the resiliency of writes to the system, indexing operations can be configured to wait for a certain number of active shard copies before proceeding with the operation. If the requisite number of active shard copies are not available, then the write operation must wait and retry, until either the requisite shard copies have started or a timeout occurs.
在索引一篇文檔時(shí),通過wait_for_active_shards指定有多少個(gè)活躍的shards時(shí),才能執(zhí)行索引文檔的操作。默認(rèn)情況下,只要primary shard 是活躍的就可以索引文檔。即wait_for_active_shards值為1
By default, write operations only wait for the primary shards to be active before proceeding (i.e.?wait_for_active_shards=1)
來驗(yàn)證一下:在只有一臺節(jié)點(diǎn)的ElasticSearch上:三個(gè)primary shard 全部分配在一臺節(jié)點(diǎn)中,并且存在著未分配的replica
執(zhí)行:
PUT user/profile/10 {"content":"向user索引中添加一篇id為10的文檔" }返回結(jié)果:
{"_index": "user","_type": "profile","_id": "10","_version": 1,"result": "created","_shards": {"total": 3,"successful": 1,"failed": 0},"_seq_no": 0,"_primary_term": 1 }在_shards 中,total 為3,說明該索引操作應(yīng)該在3個(gè)(一個(gè)primary shard,二個(gè)replica)分片中執(zhí)行成功;但是successful為1 說明 PUT操作 在其中一個(gè)分片中執(zhí)行成功了,就返回給client索引成功的確認(rèn)。這個(gè)分片就是primary shard,因?yàn)橹挥幸慌_節(jié)點(diǎn),另外2個(gè)replica 屬于 unassigned shards,不可能在2個(gè)replica 中執(zhí)行成功。總之,默認(rèn)情況下,只要primary shard 是活躍的,就能索引文檔(index操作)
現(xiàn)在在單節(jié)點(diǎn)的集群上,修改索引配置為:wait_for_active_shards=2,這意味著一個(gè)索引操作至少要在2個(gè)分片上執(zhí)行成功,才能返回給client acknowledge。
"settings": {"index.write.wait_for_active_shards": "2"}再次向user索引中PUT 一篇文檔:
PUT user/profile/10 {"content":"向user索引中添加一篇id為10的文檔" }返回結(jié)果:
{"statusCode": 504,"error": "Gateway Time-out","message": "Client request timeout" }由于是單節(jié)點(diǎn)的ElasticSearch,另外的2個(gè)replica無法分配,因此不可能是活躍的。而我們指定的wait_for_active_shards為2,但現(xiàn)在只有primary shard是活躍的,還差一個(gè)replica,因此無法進(jìn)行索引操作了。
The primary shard assigned to perform the index operation might not be available when the index operation is executed. Some reasons for this might be that the primary shard is currently recovering from a gateway or undergoing relocation.?By default, the index operation will wait on the primary shard to become available for up to 1 minute before failing and responding with an error.
索引操作會在1分鐘之后超時(shí)。再看創(chuàng)建索引的org.elasticsearch.cluster.metadata.MetaDataCreateIndexService源代碼涉及到兩個(gè)參數(shù):一個(gè)是wait_for_active_shards,另一個(gè)是ackTimeout,就好理解了。
public void createIndex(final CreateIndexClusterStateUpdateRequest request,final ActionListener<CreateIndexClusterStateUpdateResponse> listener) {onlyCreateIndex(request, ActionListener.wrap(response -> {if (response.isAcknowledged()) {activeShardsObserver.waitForActiveShards(new String[]{request.index()}, request.waitForActiveShards(), request.ackTimeout(),shardsAcknowledged -> {if (shardsAcknowledged == false) {logger.debug("[{}] index created, but the operation timed out while waiting for " +"enough shards to be started.", request.index());}總結(jié)一下:由于文檔最終是存在在某個(gè)ElasticSearch shard下面的,而每個(gè)shard又設(shè)置了副本數(shù)。默認(rèn)情況下,在進(jìn)行索引文檔操作時(shí),ElasticSearch會檢查活躍的分片數(shù)量是否達(dá)到wait_for_active_shards設(shè)置的值。若未達(dá)到,則索引操作會超時(shí),超時(shí)時(shí)間為1分鐘。另外,值得注意的是:檢查活躍分片數(shù)量只是在開始索引數(shù)據(jù)的時(shí)候檢查,若檢查通過后,在索引文檔的過程中,集群中又有分片因?yàn)槟承┰驋斓袅?#xff0c;那索引文檔操作還是會繼續(xù)進(jìn)行。
因?yàn)樗饕臋n操作(也即寫操作)發(fā)生在 檢查活躍分片數(shù)量 操作之后。試想以下幾個(gè)問題:
- 問題1:檢查活躍分片數(shù)量滿足?wait_for_active_shards?設(shè)置的值之后,在持續(xù) bulk index 文檔過程中有 shard 失效了(這里的shard是replica),那 難道不能繼續(xù)索引文檔了?
- 問題2:在什么時(shí)候檢查集群中的活躍分片數(shù)量?難道要 每次client發(fā)送索引文檔請求時(shí)就要檢查一次嗎?還是說周期性地隔多久檢查一次?
- 問題3:這里的 check-then-act 并不是原子操作,因此wait_for_active_shards這個(gè)配置參數(shù)又有多大的意義?
因此,官方文檔中是這么說的:
It is important to note that?this setting greatly reduces the chances of the write operation not writing to the requisite number of shard copies, but it does not completely eliminate the possibility, because this check occurs before the write operation commences. Once the write operation is underway, it is still possible for replication to fail on any number of shard copies but?still succeed on the primary.
- 該參數(shù)只是盡可能地保證新文檔能夠?qū)懭氲轿覀兯蟮膕hard數(shù)量中(reduce the chance of ....)。比如:wait_for_active_shards設(shè)置為2,那也只是盡可能地保證將新文檔寫入了2個(gè)shard中,當(dāng)然一個(gè)是primary shard,另外就是某一個(gè)replica
- check 操作發(fā)生在 write操作之前,在寫操作正在進(jìn)行過程中,有可能某些shard出了問題,只要不是primary shard,那寫操作還是會繼續(xù)進(jìn)行。
最后,說一下wait_for_active_shards參數(shù)的取值:可以設(shè)置成 all 或者是 1到 number_of_replicas+1 之間的任何一個(gè)整數(shù)。
Valid values are?all?or any positive integer up to the total number of configured copies per shard in the index (which is?number_of_replicas+1)
number_of_replicas 為索引指定的副本的數(shù)量,加1是指:再算上primary shard。比如前面user索引的副本數(shù)量為2,那么wait_for_active_shards最多設(shè)置為3。
好,前面討論完了ElasticSearch能夠執(zhí)行索引操作(寫操作)了,接下來是在寫操作過程中發(fā)生了什么?比如說ElasticSearch是如何做到近實(shí)時(shí)搜索的?在將文檔寫入ElasticSearch時(shí)候發(fā)生了故障,那文檔會不會丟失?
由于ElasticSearch底層是Lucene,在將一篇文檔寫入ElasticSearch,并最終能被Client查詢到,涉及到以下幾個(gè)概念:倒排索引、Lucene段、提交點(diǎn)、translog、ElasticSearch分片。這里概念都是參考《ElasticSearch definitive guide》中相關(guān)的描述。
In Elasticsearch, the most basic unit of storage of data is a shard. But, looking through the Lucene lens makes things a bit different. Here,?each Elasticsearch shard is a Lucene index, and each Lucene index consists of several Lucene segments. A segment is an inverted index of the mapping of terms to the documents containing those terms.
它們之間的關(guān)系示意圖如下:
一個(gè)ElasticSearch 索引可由多個(gè) primary shard組成,每個(gè)primary shard相當(dāng)于一個(gè)Lucene Index;一個(gè)Lucene index 由多個(gè)Segment組成,每個(gè)Segment是一個(gè)倒排索引結(jié)構(gòu)表
從文檔的角度來看:文章會被analyze(比如分詞),然后放到倒排索引(posting list)中。倒排索引之于ElasticSearch就相當(dāng)于B+樹之于Mysql,是存儲引擎底層的存儲結(jié)構(gòu)。
當(dāng)文檔寫入ElasticSearch時(shí),文檔首先被保存在內(nèi)存索引緩存中(in-memeory indexing buffer)。而in-memory buffer是每隔1秒鐘刷新一次,刷新成一個(gè)個(gè)的可搜索的段--下圖中的綠色圓柱表示(segment),然后這些段是每隔30分鐘同步到磁盤中持久化存儲,段同步到磁盤的過程稱為 提交 commit。
在這里涉及到了兩個(gè)過程:① In-memory buffer中的文檔被刷新成段;②段提交 同步到磁盤 持久化存儲。
過程①默認(rèn)是1秒鐘1次,這也能理解為什么ElasticSearch中還有段合并操作。另外ElasticSearch提供了 refresh API 來控制過程①。refresh操作強(qiáng)制把In-memory buffer中的內(nèi)容刷新成段。refresh示意圖如下:
比如說,你可以在每次index一篇文檔之后就調(diào)用一次refresh API,也即:每索引一篇文檔就強(qiáng)制刷新生成一個(gè)段,這會導(dǎo)致系統(tǒng)中存在大量的小段,是有性能開銷的。而我們所說的ElasticSearch是提供了近實(shí)時(shí)搜索,指的是:文檔的變化并不是立即對搜索可見,但會在一秒之后變?yōu)榭梢?#xff0c;一秒鐘之后,我們寫入的文檔就可以被搜索到了。
對于過程②,就是將段刷新到磁盤中去,默認(rèn)是每隔30分鐘一次,這個(gè)刷新過程稱為提交。如果還未來得及提交時(shí),發(fā)生了故障,那豈不是會丟失大量的文檔數(shù)據(jù)?這個(gè)時(shí)候,就引入了translog
每篇文檔寫入到In-memroy buffer中時(shí),同時(shí)也會向 translog中寫一條記錄。In-memory buffer 每秒刷新一次,刷新后生成新段,in-memory被清空,文檔可以被搜索。
而translog 默認(rèn)是每5秒鐘刷新一次到磁盤,或者是在每次請求(index、delete、update、bulk)之后就刷新到磁盤。每5秒鐘刷新一次就是異步刷新,可以通過如下方式開啟:
PUT /my_index/_settings {"index.translog.durability": "async","index.translog.sync_interval": "5s" }這種方式的話,還是有可能會丟失文檔數(shù)據(jù),比如Client發(fā)起index操作之后,ElasticSearch返回了200響應(yīng),但是由于translog要等5秒鐘之后才刷新到磁盤,如果在5秒內(nèi)系統(tǒng)宕機(jī)了,那么這幾秒鐘內(nèi)寫入的文檔數(shù)據(jù)就丟失了。
而在每次請求操作(index、delete、update、bulk)執(zhí)行后就刷新translog到磁盤,則是translog同步刷新,比如說:當(dāng)Client PUT一個(gè)文檔:
PUT user/profile/10 {"content":"向user索引中添加一篇id為10的文檔" }在前面提到的三節(jié)點(diǎn)ElasticSearch集群中,該user索引有三個(gè)primary shard,每個(gè)primary shard2個(gè)replica,那么translog需要在某個(gè)primary shard中刷新成功,并且在該primary shard的兩個(gè)replica中也刷新成功,才會給Client返回 200 PUT成功響應(yīng)。這種方式就保證了,只要Client接收到的響應(yīng)是200,就意味著該文檔一定是成功索引到ElasticSearch中去了。因?yàn)閠ranslog是成功持久化到磁盤之后,再給Client響應(yīng)的,系統(tǒng)宕機(jī)后在下一次重啟ElasticSearch時(shí),就會讀取translog進(jìn)行恢復(fù)。
By default, Elasticsearch?fsyncs and commits the translog every 5 seconds if?index.translog.durability?is set to?async?or if set to?request?(default) at the end of every?index,?delete,?update, or?bulk?request. More precisely, if set to?request, Elasticsearch will only report success of an index, delete, update, or bulk request to the client after the translog has been successfully?fsynced and committed on the primary and on every allocated replica.
這也是為什么,在我們關(guān)閉ElasticSearch時(shí)最好進(jìn)行一次flush操作,將段刷新到磁盤中。因?yàn)檫@樣會清空translog,那么在重啟ElasticSearch就會很快(不需要恢復(fù)大量的translog了)
translog 也被用來提供實(shí)時(shí) CRUD 。當(dāng)你試著通過ID查詢、更新、刪除一個(gè)文檔,它會在嘗試從相應(yīng)的段中檢索之前, 首先檢查 translog 任何最近的變更。這意味著它總是能夠?qū)崟r(shí)地獲取到文檔的最新版本。
放一張總結(jié)性的圖,如下:
有個(gè)問題是:為什么translog可以在每次請求之后刷新到磁盤?難道不會影響性能嗎?相比于將 段(segment)刷新到磁盤,刷新translog的代價(jià)是要小得多的,因?yàn)閠ranslog是經(jīng)過精心設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu),而段(segment)是倒排索引,我們無法做到每次將段刷新到磁盤;而translog相比于段要輕量級簡單得多,因此通過translog機(jī)制來保證數(shù)據(jù)不丟失又不影響查詢性能。
Changes to Lucene are only persisted to disk during a Lucene commit, which is a relatively expensive operation and so cannot be performed after every index or delete operation. ...... All index and delete operations are written to the translog after being processed by the internal Lucene index but before they are acknowledged. In the event of a crash, recent transactions that have been acknowledged but not yet included in the last Lucene commit can instead be recovered from the translog when the shard recovers.總結(jié)一下:
這里一共有三個(gè)地方有“刷新操作”:
in-memory buffer 刷新 生成segment
每秒一次,文檔刷新成segment就可以被搜索到了,ElasticSearch提供了refresh API 來控制這個(gè)過程
translog 刷新到磁盤
由index.translog.durability來設(shè)置,或者由index.translog.flush_threshold_size來設(shè)置當(dāng)translog達(dá)到一定大小之后刷新到磁盤(默認(rèn)512MB)
段(segment) 刷新到磁盤
每30分鐘一次,ElasticSearch提供了flush API 來控制這個(gè)過程。在段被刷新到磁盤(就是通常所說的commit操作)中時(shí),也會清空刷新translog。
存在的一些問題
這個(gè)?issue?和 這個(gè)?issue?討論了index.write.wait_for_active_shards參數(shù)的來龍去脈。
以三節(jié)點(diǎn)ElasticSearch6.3.2集群,索引設(shè)置為3個(gè)primary shard,每個(gè)primary shard 有2個(gè)replica 來討論:
- client向其中一個(gè)節(jié)點(diǎn)發(fā)起Index操作索引文檔,這個(gè)寫操作請求當(dāng)然是發(fā)送到primary shard上,但是當(dāng)Client收到200響應(yīng)時(shí),該文檔是否已經(jīng)復(fù)制到另外2個(gè)replica上?
- Client將一篇文檔成功寫入到ElasticSearch了(收到了200響應(yīng)),它能在replica所在的節(jié)點(diǎn)上 GET 到這篇文檔嗎?Client發(fā)起查詢請求,又能查詢到這篇文檔嗎?(注意:GET 和 Query 是不一樣的)
- 前面提到,當(dāng) index 一篇文檔時(shí),primary shard 和2個(gè)replica 上的translog 要?都刷新?到磁盤,才返回 200 響應(yīng),那它是否與參數(shù)?index.write.wait_for_active_shards默認(rèn)值 矛盾?因?yàn)閕ndex.write.wait_for_active_shards默認(rèn)值為1,即:只要primary shard 是活躍的,就可以進(jìn)行 index 操作。也就是說:當(dāng)Client收到200的index成功響應(yīng),此時(shí)primary shard 已經(jīng)將文檔?復(fù)制?到2個(gè)replica 上了嗎?這兩個(gè) replica 已經(jīng)將文檔刷新成 segment了嗎?還是說這兩個(gè) replica 僅僅只是 將索引該文檔的 translog 刷新到磁盤上了?
ElasticSearch副本復(fù)制方式討論
ElasticSearch索引是一個(gè)邏輯概念,囊括現(xiàn)實(shí)世界中的數(shù)據(jù)。比如 定義一個(gè) user 索引存儲所有的用戶資料信息。索引由若干個(gè)primary shard組成,就相當(dāng)于把用戶資料信息 分開成 若干個(gè)部分存儲,每個(gè)primary shard存儲user索引中的一部分?jǐn)?shù)據(jù)。為了保證數(shù)據(jù)可靠性不丟失,可以為每個(gè)primary shard配置副本(replica)。顯然,primary shard 和它對應(yīng)的replica 是不會存儲在同一臺機(jī)器(node)上的,因?yàn)槿绻摍C(jī)器宕機(jī)了,那么primary shard 和 副本(replica) 都會丟失,那整個(gè)系統(tǒng)就丟失一部分?jǐn)?shù)據(jù)了。
primary shard 和 replica 這種副本備份方案,稱為主從備份。primary shard是主(single leader),replica 是 從 (multiple replica)。由于是分布式環(huán)境,可能存在多個(gè)Client同時(shí)向ElasticSearch發(fā)起索引文檔的請求,這篇文檔會根據(jù) 文檔id 哈希到某個(gè) primary shard,primary shard寫入該文檔 并分發(fā)給 replica 進(jìn)行存儲。由于采用了哈希,這也是為什么 在定義索引的時(shí)候,需要指定primary shard個(gè)數(shù),并且 primary shard個(gè)數(shù)一經(jīng)指定后不可修改的原因。因?yàn)閜rimary shard個(gè)數(shù)一旦改變,哈希映射 結(jié)果就變了。而采用這種主從副本備份方案,這也是為什么 索引操作(寫操作、update操作) 只能由 primary shard處理,而讀操作既可以從 primary shard讀取,也可以從 replica 讀取的原因。相對于文檔而言,primary shard是single leader,所有的文檔修改操作都統(tǒng)一由primary shard處理,能避免一些 并發(fā)修改 沖突。但是默認(rèn)情況下,ElasticSearch 副本復(fù)制方式 是異步的,也正如前面?index.write.wait_for_active_shards討論,只要primary shard 是活躍的就可以進(jìn)行索引操作,primary shard 將文檔 “ 存儲 ” 之后,就返回給client 響應(yīng),然后primary shard 再將該文檔同步給replicas,而這就是異步副本復(fù)制方式。在ElasticSearch官方討論論壇里面,也有關(guān)于副本復(fù)制方式的討論:這篇文章提出了一個(gè)問題:Client向primary shard寫入文檔成功,primary shard 是通過何種方式將該文檔同步到 replica的?
關(guān)于primary shard 將文檔同步給各個(gè)replica,涉及到 in-sync replica概念,在master節(jié)點(diǎn)中維護(hù)了一個(gè) in-sync 副本列表。
Since replicas can be offline, the primary is not required to replicate to all replicas. Instead, Elasticsearch maintains a list of shard copies that should receive the operation. This list is called the in-sync copies and is maintained by the master node.
當(dāng)index操作發(fā)送到 primary shard時(shí),primary shard 并行轉(zhuǎn)發(fā)給 in-sync副本,等待各個(gè)in-sync副本給primary 響應(yīng)。primary shard收到所有in-sync副本響應(yīng)后,再給Client響應(yīng)說:Index操作成功。由于副本可能會出故障,當(dāng)沒有in-sync副本,只有primary shard在正常工作時(shí),此時(shí)的index操作只在primary shard上執(zhí)行成功就返回給Client了,這里就存在了所謂的“單點(diǎn)故障”,因?yàn)閜rimary shard所在的節(jié)點(diǎn)掛了,那 就會丟失 index 操作的文檔了。這個(gè)時(shí)候,?index.write.wait_for_active_shards?參數(shù)就起作用了,如果將?index.write.wait_for_active_shards?設(shè)置為2,那么 當(dāng)沒有in-sync副本,只有primary shard在正常工作時(shí),index 操作就會被拒絕。所以,在這里,index.write.wait_for_active_shards參數(shù)起到一個(gè)避免單點(diǎn)故障的功能。更具體的細(xì)節(jié)可參考data-replication model
采用異步副本復(fù)制方式帶來的一個(gè)問題是:讀操作能讀取最新寫入的文檔嗎?如果我們指定讀請求去讀primary shard(通過ElasticSearch 的路由機(jī)制),那么是能讀到最新數(shù)據(jù)的。但是如果讀請求是由某個(gè) replica 接收處理,那也許就不能讀取到剛才最新寫入的文檔了。因此,從剛才Client 讀請求的角度來看,ElasticSearch能提供 哪種程度的 一致性呢?而出現(xiàn)這種一致性問題的原因在于:為了保證數(shù)據(jù)可靠性,采用了副本備份,引入了副本,導(dǎo)致副本和primary shard上的數(shù)據(jù)不一致,即:存在 replication lag 問題。由于這種副本復(fù)制延遲帶來的問題,系統(tǒng)需要給Client 某種數(shù)據(jù)一致性的 保證,比如說:
-
read your own write
Client能夠讀取到它自己最新寫入的數(shù)據(jù)。比如用戶修改了昵稱,那TA訪問自己的主頁時(shí),能看到自己修改了的昵稱,但是TA的好友 可能 并不能立即看到 TA 修改后的昵稱。好友請求的是某個(gè) replica 上的數(shù)據(jù),而 primary shard還未來得及把剛才修改的昵稱 同步 到 replica上。
-
Monotonic reads
單調(diào)讀。每次Client讀取的值,是越來越新的值(站在Client角度來看的)。比如說NBA籃球比賽,Client每10分鐘讀一次比賽結(jié)果。第10分鐘讀取到的是 1:1,第20分鐘讀到的是2:2,第30分鐘讀到的是3:3,假設(shè)在第40分鐘時(shí),實(shí)際比賽結(jié)果是4:4,Cleint在第40分鐘讀取的時(shí)候,讀到的值可以是3:3 這意味著未讀取到最新結(jié)果而已,讀到的值也可以是4:4, 但是不能是2:2 。
-
consistent prefix reads
符合因果關(guān)系的一種讀操作。比如說,用戶1 和 用戶2 對話:
用戶1:你現(xiàn)在干嘛?
用戶2:寫代碼對于Client讀:應(yīng)該是先讀取到“你現(xiàn)在干嘛?”,然后再讀取到 “寫代碼。如果讀取結(jié)果順序亂了,Client就會莫名其妙。
正是由于Client 有了系統(tǒng)給予的這種 一致性 保證,那么Client(或者說應(yīng)用程序)就能基于這種保證 來開發(fā)功能,為用戶提供服務(wù)。
那系統(tǒng)又是如何提供這種一致性保證的呢?或者說ElasticSearch集群又提供了何種一致性保證?經(jīng)常聽到的有:強(qiáng)一致性(linearizability)、弱一致性、最終一致性。對于強(qiáng)一致性,通俗的理解就是:實(shí)際上數(shù)據(jù)有多份(primary shard 以及多個(gè) replica),但在Client看來,表現(xiàn)得就只有一份數(shù)據(jù)。在多個(gè) client 并發(fā)讀寫情形下,某個(gè)Client在修改數(shù)據(jù)A,而又有多個(gè)Client在同時(shí)讀數(shù)據(jù)A,linearizability 就要保證:如果某個(gè)Client讀取到了數(shù)據(jù)A,那在該Client之后的讀取請求返回的結(jié)果都不能比數(shù)據(jù)A要 舊,至少是數(shù)據(jù)A的當(dāng)前值(不能是數(shù)據(jù)A的舊值)。不說了,再說,我自己都不明白了。
至于系統(tǒng)如何提供這種一致性,會用到一些分布式共識算法,我也沒有深入地去研究過。關(guān)于副本復(fù)制方式的討論,也可參考這篇文章:分布式系統(tǒng)理論之Quorum機(jī)制
參考資料
-
ElasticSearch關(guān)于translog的官方文檔解釋:https://www.elastic.co/guide/en/elasticsearch/reference/master/index-modules-translog.html#_translog_settings
- ElasticSearch權(quán)威指南中文版 基礎(chǔ)入門小節(jié)中的:分片內(nèi)部原理(再結(jié)合英文原文閱讀一遍):https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/translog.html
- 分布式中的 transaction log
- refresh-flush-operations-elasticsearch-guide
-
Elasticsearch分布式一致性原理剖析(三)-Data篇
原文:https://www.cnblogs.com/hapjin/p/9821073.html
總結(jié)
以上是生活随笔為你收集整理的ElasticSearch index 剖析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ElasticSearch评分分析 ex
- 下一篇: Lamport Logical Cloc