1.Lucene解析 - IndexWriter
2.Elasticsearchä¹åå¨åç
3.Elasticsearch学习总结之二:lucene的源码segment
4.lucene 全文检索原理和流程
5.Lucene SegmentReader:深入分析 I
6.Elasticsearch为å¥è¿ä¹å¿«
Lucene解析 - IndexWriter
在上篇文章我们介绍了Lucene的基本概念,接下来本文将深入探讨Lucene的源码核心组件之一,即IndexWriter,源码让我们一起来探索数据写入和索引构建的源码过程。
IndexWriter作为Lucene中用于数据写入的源码核心类,提供了数据写入的源码二元期权源码简洁流程,主要分为三个步骤。源码通过这个类,源码我们可以轻松地将数据写入并构建索引,源码其设计理念在于为普通用户提供了低门槛的源码使用体验,同时高级用户也能通过配置参数实现性能优化和功能定制。源码
IndexWriter配置提供了关键参数,源码供高级用户进行性能调优和功能定制。源码这些核心参数包括但不限于缓存大小、源码分段策略、源码写入模式等,为用户提供灵活性。
为了更深入理解IndexWriter,本节将介绍其提供的主要操作接口。这些接口包括添加文档、jsp源码输出更新文档、删除文档和提交操作,它们构成IndexWriter的核心功能。接下来,我们将通过一系列图示和解释,解析IndexWriter的内部数据处理流程。
在IndexWriter内部,数据处理流程被高度优化,以支持多线程并发写入。通过引入DocumentsWriterPerThread(DWPT)机制,每个线程都有独立的空间进行数据处理,这大大提高了并发性能。DWPT内部包含一个内存缓冲区,缓冲区内的数据最终会被flush到不同的独立segment文件中。
并发模型的设计使得多线程写入性能显著提升,尤其是针对新增文档的场景,提高了数据写入效率。对于删除文档操作,Lucene采用了一种特殊的360卫士源码交互方式来降低锁的开销,使得整个流程更加高效。
在搜索场景中,全量构建索引时,数据写入主要为新增文档;而在增量索引阶段,会涉及大量更新和删除操作。最佳实践是将具有相同唯一主键Term的文档分配给相同的线程进行处理,以避免跨线程冲突。
添加和更新操作涉及将文档写入内存缓冲区,随后通过特定流程进行处理。删除操作则通过构建全局和独立的删除队列,以及更新live docs位图来实现,确保数据的有效管理和回收。
flush操作用于将内存缓冲区中的数据持久化到文件,该过程由FlushPolicy自动触发或通过IndexWriter手动执行。commit动作则强制执行数据flush,并生成commit点,确保在搜索时可以访问已提交的数据。
merge操作则用于合并segment文件,提高查询效率和回收已被删除的游资持仓源码文档。此过程在segment flush时自动触发或通过IndexWriter强制执行。
IndexingChain概念揭示了Lucene内部索引构建的链式流程。它涉及多个不同类型的索引构建,如倒排、store fields、doc values和point values。这些索引类型根据其功能和需求,使用不同的数据结构和存储方式。
通过Codec配置,用户可以为不同类型的索引选择不同的编码和解码实现,支持了索引构建的灵活性和可扩展性。Codec参数的配置允许用户优化索引构建性能,满足特定应用需求。
总结而言,本文从全局视角深入探讨了IndexWriter的配置、接口、并发模型、核心操作的数据路径以及索引链的概念。接下来的edusoho 直播源码文章将继续深入研究索引链中每种不同类型索引的构建流程,包括memory-buffer的实现、索引算法以及数据存储格式等。
Elasticsearchä¹åå¨åç
åæç´¢å¼è¢«åå ¥ç£çåæ¯ä¸å¯åçï¼ES解å³ä¸åæ§åæ´æ°ç´¢å¼çæ¹å¼æ¯ä½¿ç¨å¤ä¸ªç´¢å¼ï¼å©ç¨æ°å¢çç´¢å¼æ¥åæ ä¿®æ¹ï¼å¨æ¥è¯¢æ¶ä»æ§çå°æ°çä¾æ¬¡æ¥è¯¢ï¼æåæ¥ä¸ä¸ªç»æå并ãESåºå±æ¯åºäºLuceneï¼ææ ¸å¿çæ¦å¿µå°±æ¯Segment(段)ï¼æ¯ä¸ªæ®µæ¬èº«å°±æ¯ä¸ä¸ªåæç´¢å¼ã
ESä¸çIndexç±å¤ä¸ªæ®µçéååcommit point(æ交ç¹)æ件ç»æã
æ交ç¹æ件ä¸æä¸ä¸ªå表åæ¾çææå·²ç¥ç段ï¼ä¸é¢æ¯ä¸ä¸ªå¸¦æ1个æ交ç¹å3个段çIndex示æå¾ï¼
Docä¼å 被æéå°å åä¸çBufferå ï¼è¿ä¸ªæ¶åè¿æ æ³è¢«æç´¢å°ï¼å¦ä¸å¾æ示ï¼
æ¯éä¸æ®µæ¶é´ï¼ä¼å°bufferæ交ï¼å¨flushç£çåæå¼æ°æ®µä½¿å¾æç´¢å¯è§ï¼è¯¦ç»è¿ç¨å¦ä¸ï¼
ä¸é¢å±ç¤ºäºè¿ä¸ªè¿ç¨å®æåç段åæ交ç¹çç¶æï¼
éè¿è¿ç§æ¹å¼ï¼å¯ä»¥ä½¿å¾æ°ææ¡£ä»è¢«ç´¢å¼å°å¯è¢«æç´¢é´çæ¶é´é´éå¨æ°åéï¼ä½æ¯è¿ä¸å¤å¿«ãå 为ç£çéè¦ fsync ï¼è¿ä¸ªå°±æ为æ§è½ç¶é¢ãæ们åé¢æå°è¿Docä¼å 被ä»bufferå·å ¥æ®µåå ¥æ件系ç»ç¼åï¼å¾å¿«ï¼ï¼é£ä¹å°±èªç¶æ³å°å¨è¿ä¸ªé¶æ®µå°±è®©æ档对æç´¢å¯è§ï¼éåå被å·å ¥ç£çï¼è¾æ ¢ï¼ã
Luceneæ¯æ对æ°æ®µåå ¥åæå¼ï¼å¯ä»¥ä½¿ææ¡£å¨æ²¡æå®å ¨å·å ¥ç¡¬ççç¶æä¸å°±è½å¯¹æç´¢å¯è§ï¼èä¸æ¯ä¸ä¸ªå¼éè¾å°çæä½ï¼å¯ä»¥é¢ç¹è¿è¡ã
ä¸é¢æ¯ä¸ä¸ªå·²ç»å°Docså·å ¥æ®µï¼ä½è¿æ²¡æå®å ¨æ交ç示æå¾ï¼
æ们å¯ä»¥çå°ï¼æ°æ®µè½ç¶è¿æ²¡æ被å®å ¨æ交ï¼ä½æ¯å·²ç»å¯¹æç´¢å¯è§äºã
å¼å ¥refreshæä½çç®çæ¯æé«ESçå®æ¶æ§ï¼ä½¿æ·»å æ档尽å¯è½å¿«ç被æç´¢å°ï¼åæ¶åé¿å é¢ç¹fsync带æ¥æ§è½å¼éï¼ä¾é çå°±æ¯æ件系ç»ç¼åOS cacheéç¼åçæ件å¯ä»¥è¢«æå¼(open/reopen)å读åï¼èè¿ä¸ªos cacheå®é æ¯ä¸åå ååºåï¼èéç£çï¼æ以æä½æ¯å¾å¿«çï¼è¿å°±æ¯ES被称为è¿å®æ¶æç´¢çåå ã
refreshé»è®¤æ§è¡çé´éæ¯1ç§ï¼å¯ä»¥ä½¿ç¨ refreshAPI è¿è¡æå¨æä½ï¼ä½ä¸è¬ä¸å»ºè®®è¿ä¹åãè¿å¯ä»¥éè¿åç设置 refresh_interval å¨è¿å®æ¶æç´¢åç´¢å¼é度é´åæè¡¡ã
index segmentå·å ¥å°os cacheåå°±å¯ä»¥æå¼ä¾æ¥è¯¢ï¼è¿ä¸ªæä½æ¯ææ½å¨é£é©çï¼å 为os cacheä¸çæ°æ®æå¯è½å¨æå¤çæ éä¸ä¸¢å¤±ï¼èæ¤æ¶æ°æ®å¿ å¤å¹¶æªå·å ¥å°os diskï¼æ¤æ¶æ°æ®ä¸¢å¤±å°æ¯ä¸å¯éçï¼è¿ä¸ªæ¶åå°±éè¦ä¸ç§æºå¶ï¼å¯ä»¥å°å¯¹esçæä½è®°å½ä¸æ¥ï¼æ¥ç¡®ä¿å½åºç°æ éçæ¶åï¼å·²ç»è½å°å°ç£ççæ°æ®ä¸ä¼ä¸¢å¤±ï¼å¹¶å¨éå¯çæ¶åå¯ä»¥ä»æä½è®°å½ä¸å°æ°æ®æ¢å¤è¿æ¥ãelasticsearchæä¾äºtranslogæ¥è®°å½è¿äºæä½ï¼ç»åos cached segmentsæ°æ®å®æ¶è½çæ¥å®ç°æ°æ®å¯é æ§ä¿è¯ï¼flushï¼ã
æ档被添å å°bufferåæ¶è¿½å å°translogï¼
è¿è¡ refresh æä½ï¼æ¸ 空bufferï¼ææ¡£å¯è¢«æç´¢ä½å°æª flush å°ç£çãtranslogä¸ä¼æ¸ 空ï¼
æ¯éä¸æ®µæ¶é´ï¼ä¾å¦translogåå¾å¤ªå¤§ï¼ï¼indexä¼è¢«flushå°ç£çï¼æ°çtranslogæ件被å建ï¼commitæ§è¡ç»æåï¼ä¼åç以ä¸äºä»¶ï¼
ä¸é¢ç¤ºæå¾å±ç¤ºäºè¿ä¸ªç¶æï¼
translogè®°å½çæ¯å·²ç»å¨å åçæ(segments)并åå¨å°os cacheä½æ¯è¿æ²¡åå°ç£ççé£äºç´¢å¼æä½ï¼æ³¨æï¼æä¸ç§è§£é说ï¼æ·»å å°bufferä¸ä½æ¯æ²¡æ被åå ¥segmentä¸çæ°æ®æ²¡æ被记å½å°translogä¸ï¼è¿ä¾èµäºåtranslogçæ¶æºï¼ä¸åçæ¬å¯è½æååï¼ä¸å½±åç解ï¼ï¼æ¤æ¶è¿äºæ°åå ¥çæ°æ®å¯ä»¥è¢«æç´¢å°ï¼ä½æ¯å½èç¹ææåè¿äºæªæ¥å¾åè½å ¥ç£ççæ°æ®å°±ä¼ä¸¢å¤±ï¼å¯ä»¥éè¿trangslogæ¢å¤ã
å½ç¶translogæ¬èº«ä¹æ¯ç£çæ件ï¼é¢ç¹çåå ¥ç£çä¼å¸¦æ¥å·¨å¤§çIOå¼éï¼å æ¤å¯¹translogç追å åå ¥æä½çåæ ·æä½çæ¯os cacheï¼å æ¤ä¹éè¦å®æ¶è½çï¼fsyncï¼ãtranslogè½ççæ¶é´é´éç´æ¥å³å®äºESçå¯é æ§ï¼å 为å®æºå¯è½å¯¼è´è¿ä¸ªæ¶é´é´éå ææçESæä½æ¢æ²¡æçæsegmentç£çæ件ï¼å没æè®°å½å°Translogç£çæ件ä¸ï¼å¯¼è´è¿æé´çæææä½é½ä¸¢å¤±ä¸æ æ³æ¢å¤ã
translogçfsyncæ¯ESå¨åå°èªå¨æ§è¡çï¼é»è®¤æ¯æ¯5ç§é主å¨è¿è¡ä¸æ¬¡translog fsyncï¼æè å½translogæ件大å°å¤§äºMB主å¨è¿è¡ä¸æ¬¡fsyncï¼å¯¹åºçé ç½®æ¯ index.translog.flush_threshold_period å index.translog.flush_threshold_size ã
å½ Elasticsearch å¯å¨çæ¶åï¼ å®ä¼ä»ç£çä¸ä½¿ç¨æåä¸ä¸ªæ交ç¹å»æ¢å¤å·²ç¥ç段ï¼å¹¶ä¸ä¼éæ¾ translog ä¸ææå¨æåä¸æ¬¡æ交ååççåæ´æä½ã
translog ä¹è¢«ç¨æ¥æä¾å®æ¶ CRUD ãå½ä½ è¯çéè¿IDæ¥RUDä¸ä¸ªDocï¼å®ä¼å¨ä»ç¸å ³ç段æ£ç´¢ä¹åå æ£æ¥ translog ä¸ææ°çåæ´ã
é»è®¤ translog æ¯æ¯5ç§ææ¯æ¯æ¬¡è¯·æ±å®æå被 fsync å°ç£çï¼å¨ä¸»åçåå¯æ¬åçé½ä¼ï¼ãä¹å°±æ¯è¯´ï¼å¦æä½ åèµ·ä¸ä¸ªindex, delete, update, bulk请æ±åå ¥translog并被fsyncå°ä¸»åçåå¯æ¬åççç£çåä¸ä¼ååç¶æã
è¿æ ·ä¼å¸¦æ¥ä¸äºæ§è½æ失ï¼å¯ä»¥éè¿è®¾ä¸ºå¼æ¥fsyncï¼ä½æ¯å¿ é¡»æ¥åç±æ¤å¸¦æ¥ç丢失å°éæ°æ®çé£é©ï¼
flush å°±æ¯æ§è¡commitæ¸ ç©ºãå¹²æètranslogçè¿ç¨ãé»è®¤æ¯ä¸ªåçåéæè æ¯translogè¿äºå¤§çæ¶åèªå¨flushä¸æ¬¡ãå¯ä»¥éè¿flush APIæå¨è§¦åï¼ä½æ¯åªä¼å¨éå¯èç¹æå ³éæ个索å¼çæ¶åè¿æ ·åï¼å 为è¿å¯ä»¥è®©æªæ¥ESæ¢å¤çé度æ´å¿«(translogæ件æ´å°)ã
满足ä¸åæ¡ä»¶ä¹ä¸å°±ä¼è§¦åå²å·æä½ï¼
æ´ä½æµç¨ï¼
å é¤ä¸ä¸ªESææ¡£ä¸ä¼ç«å³ä»ç£çä¸ç§»é¤ï¼å®åªæ¯è¢«æ è®°æå·²å é¤ãå 为段æ¯ä¸å¯åçï¼æ以ææ¡£æ¢ä¸è½ä»æ§ç段ä¸ç§»é¤ï¼æ§ç段ä¹ä¸è½æ´æ°ä»¥åæ ææ¡£ææ°ççæ¬ã
ESçåæ³æ¯ï¼æ¯ä¸ä¸ªæ交ç¹å æ¬ä¸ä¸ª .del æ件ï¼è¿å æ¬æ°æ®µï¼ï¼å å«äºæ®µä¸å·²ç»è¢«æ 记为å é¤ç¶æçææ¡£ãæ以ï¼å½ä¸ä¸ªæ档被åå é¤æä½ï¼å®é ä¸åªæ¯å¨ .del æ件ä¸å°è¯¥ææ¡£æ 记为å é¤ï¼ä¾ç¶ä¼å¨æ¥è¯¢æ¶è¢«å¹é å°ï¼åªä¸è¿å¨æç»è¿åç»æä¹åä¼è¢«ä»ç»æä¸å é¤ãESå°ä¼å¨ç¨æ·ä¹åæ·»å æ´å¤ç´¢å¼çæ¶åï¼å¨åå°è¿è¡è¦å é¤å 容çæ¸ çã
ææ¡£çæ´æ°æä½åå é¤æ¯ç±»ä¼¼çï¼å½ä¸ä¸ªæ档被æ´æ°ï¼æ§çæ¬çæ档被æ 记为å é¤ï¼æ°çæ¬çææ¡£å¨æ°ç段ä¸ç´¢å¼ã
该ææ¡£çä¸åçæ¬é½ä¼å¹é ä¸ä¸ªæ¥è¯¢ï¼ä½æ¯è¾æ§ççæ¬ä¼ä»ç»æä¸å é¤ã
éè¿æ¯ç§èªå¨å·æ°å建æ°ç段ï¼ç¨ä¸äºå¤ä¹ 段çæ°éå°±çç¸äºï¼æ¯ä¸ªæ®µæ¶è´¹å¤§éæ件å¥æï¼å åï¼cpuèµæºãæ´éè¦çæ¯ï¼æ¯æ¬¡æ索请æ±é½éè¦ä¾æ¬¡æ£æ¥æ¯ä¸ªæ®µã段è¶å¤ï¼æ¥è¯¢è¶æ ¢ã
ESéè¿åå°å并段解å³è¿ä¸ªé®é¢ãESå©ç¨æ®µå并çæ¶æºæ¥çæ£ä»æ件系ç»å é¤é£äºversionè¾èæè æ¯è¢«æ 记为å é¤çææ¡£ã被å é¤çææ¡£ï¼æè æ¯versionè¾èçï¼ä¸ä¼å被å并å°æ°çæ´å¤§ç段ä¸ã
å¯è§ï¼æ®µå并主è¦æ两个ç®çï¼
ES对ä¸ä¸ªä¸æææ°æ®åå ¥çç´¢å¼å¤çæµç¨å¦ä¸ï¼
å并è¿ç¨å¦å¾ï¼
ä»ä¸å¾å¯ä»¥çå°ï¼æ®µå并ä¹åï¼æ§æçCommitå没Commitçå°æ®µçå¯è¢«æç´¢ã
段å并åçæä½:
å并å®æåæ°ç段å¯è¢«æç´¢ï¼æ§ç段被å é¤ï¼å¦ä¸å¾æ示ï¼
注æï¼æ®µå并è¿ç¨è½ç¶çèµ·æ¥å¾ç½ï¼ä½æ¯å¤§æ®µçå并å¯è½ä¼å ç¨å¤§éçIOåCPUï¼å¦æä¸å 以æ§å¶ï¼å¯è½ä¼å¤§å¤§éä½æç´¢æ§è½ã段å并çoptimize API ä¸æ¯é常ç¹æ®çæ åµä¸åä¸ä¸è¦ä½¿ç¨ï¼é»è®¤çç¥å·²ç»è¶³å¤å¥½äºãä¸æ°å½ç使ç¨å¯è½ä¼å°ä½ æºå¨çèµæºå ¨é¨èå°½å¨æ®µå并ä¸ï¼å¯¼è´æ æ³æç´¢ãæ æ³ååºã
Elasticsearch学习总结之二:lucene的segment
在深入学习Elasticsearch之后,我们继续探讨其底层关键技术之一:lucene的segment。首先,我们要理解LSM(Log Structured Merge Trees)的原理,它是一种被广泛应用在HBase、Cassandra等产品中的文件结构策略,旨在提高写操作的吞吐量,通过消除随机更新来优化性能。
LSM的核心思想在于将数据写入过程转化为顺序操作,避免随机写入的性能瓶颈。LSM树包含三个关键组件:内存中的MemTable,它有序存储最近更新的数据,通过WAL保证数据可靠性;当MemTable达到一定大小,会变为Immutable MemTable,继续写操作并为持久化做准备;最后是SSTable(Sorted String Table),磁盘上的有序数据结构,通过索引和布隆过滤器提高查找效率。
LSM树的设计虽然极大地提高了写性能,但可能导致冗余存储和读取时的复杂性。为此,Elasticsearch中的Segment借鉴了LSM的思想,但对查询性能有所妥协。Segment是Lucene中独立的索引单元,包含完整的正向和反向索引,可以独立搜索,但数据一旦写入就不可更改,提供的是近实时而非实时查询。
Elasticsearch的Segment设计是为了平衡数据处理和搜索速度,它将数据缓冲在内存中,直到达到刷新周期才写入Segment。这样可以减少IO操作,但可能导致数据丢失。为保证数据可靠性,Elasticsearch使用Translog记录所有操作,但只有在配置的条件满足时才将数据同步到磁盘,因此需要理解Translog和fsync参数的配置以确保数据持久性。
lucene 全文检索原理和流程
Lucene, 作为Java的高效全文检索库,其核心原理是通过创建索引和搜索索引两个流程,实现对非结构化数据的快速查找。在大数据背景下,索引技术至关重要,它将数据结构化,通过分词、语言处理和索引构建,提高查找效率。
索引创建流程包括:将文档导入Lucene,分词器对文档进行处理,去除停用词并生成词元;接着,词元通过语言处理组件进行词形还原等操作,形成词(Term)。这些词(Term)被传给索引组件,构建字典并进行排序,形成倒排索引。
存储方面,Lucene支持将索引数据存储在本地,且具有层次结构,包含正向信息(文档中的词频)和反向信息(词与文档的关系)。段(Segment)控制策略通过设置MaxMergeDocs和MinMergeDocs影响性能,而搜索过程则涉及查询分析、语言处理、在倒排索引中查找相关文档、权重计算和向量空间模型的应用,以找出与查询语句最相关的结果。
具体来说,搜索流程包括:解析用户输入的查询语句,通过词法分析和语法处理转化为搜索请求;在索引中找到与查询词相关的文档链表,合并并排除无关文档;根据词的权重和向量空间模型计算文档间的相关性,最后按照相关性排序返回结果。
Lucene SegmentReader:深入分析 I
Lucene的SegmentReader深入解析中,核心是理解和管理索引的多个段(segment_N文件)及其元数据(segments.gen)。索引通常由多个小段组成,这些段会在后台通过merge操作合并成大段以优化查询效率。每个段文件(如segment_3)代表了某个索引提交时刻的状态,其内容由SegmentInfo中的文件列表定义。
在IndexWriter#flush后,新的文档会被添加到一个新的segment_N文件中,并将所有相关段的元信息写入该文件。同时,segments.gen文件会更新最大段号。选择哪个段进行查询时,通常会选择包含最多文档的段,且其元信息中包含了其他段的信息。
SegmentReader的创建流程分为两种情况:如果只有一个段,会直接实例化SegmentReader;若有多段,则会创建MultiSegmentReader,内部包含多个SegmentReader实例。每个SegmentInfo都会生成一个SegmentReader对象,负责读取段的文件信息。SegmentReader的初始化过程虽然对于大索引可能耗时,因此建议尽量减少索引的频繁打开和关闭。下面是这部分的详细过程:
Lucene索引通过segments.gen和segment_N文件管理多个段,每个段文件记录一个提交时刻的状态。flush操作时,新文档会增加到新的segment_N,同时更新元信息和最大段号。选择段时,倾向于选择包含最多文档的。
SegmentReader的创建涉及单段或多段场景:单段直接实例化,多段则用MultiSegmentReader聚合。每个SegmentInfo对应一个SegmentReader,负责读取文件信息。SegmentReader初始化是耗时操作,应避免频繁打开关闭索引。
Elasticsearch为å¥è¿ä¹å¿«
æèå 个é®é¢ï¼
è¿éæç¯ æç« è®²è§£çå¾å½¢è±¡ï¼
è¿æ¯é群clusterã
è¿æ¯èç¹Nodeï¼å°±æ¯ä¸ªæºå¨ã
ç±ä¸ä¸ªæè å¤ä¸ªèç¹ï¼å¤ä¸ªç»¿è²å°æ¹åç»åå¨ä¸èµ·å½¢æä¸ä¸ªElasticSearchçç´¢å¼ã
å¨ä¸ä¸ªç´¢å¼ä¸ï¼åå¸å¨å¤ä¸ªèç¹éç绿è²å°æ¹å称为åçï¼Shardã
ä¸ä¸ªåçå°±æ¯ä¸ä¸ªLucene Indexã
å¨Luceneéé¢æå¾å¤å°çSegmentï¼å³ä¸ºåå¨çæå°ç®¡çåå ã
æ们åå«ä»Node维度ãShard维度ãSegment维度æ¥éæ为å¥Elasticsearchè¿ä¹å¿«ã
å¤èç¹çé群æ¹æ¡ï¼æé«äºæ´ä¸ªç³»ç»ç并åå¤çè½åã
è·¯ç±ä¸ä¸ªææ¡£å°ä¸ä¸ªåçä¸ï¼å½ç´¢å¼ä¸ä¸ªææ¡£çæ¶åï¼ææ¡£ä¼è¢«åå¨å°ä¸ä¸ªä¸»åçä¸ã Elasticsearch å¦ä½ç¥éä¸ä¸ªææ¡£åºè¯¥åæ¾å°åªä¸ªåçä¸å¢ï¼å®é ä¸ï¼è¿ä¸ªè¿ç¨æ¯æ ¹æ®ä¸é¢è¿ä¸ªå ¬å¼å³å®çï¼
routing æ¯ä¸ä¸ªå¯åå¼ï¼é»è®¤æ¯ææ¡£ç _id ï¼ä¹å¯ä»¥è®¾ç½®æä¸ä¸ªèªå®ä¹çå¼ãè¿å°±è§£éäºä¸ºä»ä¹æ们è¦å¨å建索å¼çæ¶å就确å®å¥½ä¸»åççæ°éï¼å¹¶ä¸æ°¸è¿ä¸ä¼æ¹åè¿ä¸ªæ°éï¼å 为å¦ææ°éååäºï¼é£ä¹ææä¹åè·¯ç±çå¼é½ä¼æ æï¼ææ¡£ä¹åä¹æ¾ä¸å°äºã
ç¡®å®äºå¨åªä¸ªåçä¸ï¼ç»§èå¯ä»¥å¤å®å ¶å¨åªä¸ªèç¹ä¸ã
é£ä¹ä¸»åçæ°ç¡®å®çæ åµä¸ï¼å¦æåé群æ©å®¹å¢ï¼ä¸å¾æ¯ä¸ç§ä¸»åççæ©å®¹åæ³ï¼å¼å§è®¾ç½®ä¸º5个åçï¼å¨å个èç¹ä¸ï¼åæ¥æ©å®¹å°5个èç¹ï¼æ¯ä¸ªèç¹æä¸ä¸ªåçãä¹å°±æ¯è¯´å个åçç容éå大äºï¼ä½æ¯æ°é并ä¸å¢å ã
èç¹å为主èç¹ Master Nodeãæ°æ®èç¹ Data Nodeå客æ·ç«¯èç¹ Client Nodeï¼å纯为äºå请æ±çåååæ±æ»ï¼ãæ¯ä¸ªèç¹é½å¯ä»¥æ¥å客æ·ç«¯ç请æ±ï¼æ¯ä¸ªèç¹é½ç¥éé群ä¸ä»»ä¸ææ¡£ä½ç½®ï¼æ以å¯ä»¥ç´æ¥å°è¯·æ±è½¬åå°éè¦çèç¹ä¸ãå½æ¥å请æ±åï¼èç¹å为ãåè°èç¹ããä»è¿ä¸ªè§åº¦ï¼æ´ä¸ªç³»ç»å¯ä»¥æ¥åæ´é«ç并å请æ±ï¼å½ç¶æç´¢çå°±æ´å¿«äºã
以æ´æ°æ档为ä¾ï¼
Elasticsearch ä¸ä½¿ç¨çè¿ç§æ¹æ³åå®å²çªæ¯ä¸å¯è½åççï¼å¹¶ä¸ä¸ä¼é»å¡æ£å¨å°è¯çæä½ãå 为没æé»å¡ï¼æ以æåäºç´¢å¼çé度ï¼åæ¶å¯ä»¥éè¿ _version å段æ¥ä¿è¯å¹¶åæ åµä¸çæ£ç¡®æ§ï¼
æ§å¶å¨æ们索å¼ä¸çææ¡£åªæç°å¨ç _version 为 1 æ¶ï¼æ¬æ¬¡æ´æ°æè½æåã
å¯ä»¥è®¾ç½®åççå¯æ¬æ°éæ¥æåé«å¹¶ååºæ¯ä¸çæç´¢é度ï¼ä½æ¯åæ¶ä¼éä½ç´¢å¼çæçã
å¨åºå±éç¨äºå段çåå¨æ¨¡å¼ï¼ä½¿å®å¨è¯»åæ¶å ä¹å®å ¨é¿å äºéçåºç°ï¼å¤§å¤§æåäºè¯»åæ§è½ã
ææ ·å¨ä¿çä¸åæ§çåæä¸å®ç°åæç´¢å¼çæ´æ°ï¼å³ç¨ä¸ææå°ç _version ï¼å建æ´å¤çç´¢å¼ææ¡£ãå®é ä¸ä¸ä¸ª UPDATE æä½å å«äºä¸æ¬¡ DELETE æä½ï¼ä» è®°å½æ å¿å¾ Segment Merge çæ¶åæçæ£å é¤ï¼åä¸æ¬¡ CREATE æä½ã
为äºæååç´¢å¼é度ï¼å¹¶ä¸åæ¶ä¿è¯å¯é æ§ï¼Elasticsearch å¨å段çåºç¡ä¸ï¼å¢å äºä¸ä¸ª translog ï¼æè å«äºå¡æ¥å¿ï¼å¨æ¯ä¸æ¬¡å¯¹ Elasticsearch è¿è¡æä½æ¶åè¿è¡äºæ¥å¿è®°å½ã
Segmentå¨è¢«refreshä¹åï¼æ°æ®ä¿åå¨å åä¸ï¼æ¯ä¸å¯è¢«æç´¢çï¼è¿ä¹å°±æ¯ä¸ºä»ä¹ Lucene 被称为æä¾è¿å®æ¶èéå®æ¶æ¥è¯¢çåå ã
ä½æ¯å¦ä¸è¿ç§æºå¶é¿å äºéæºåï¼æ°æ®åå ¥é½æ¯ Batch å Appendï¼è½è¾¾å°å¾é«çååéãåæ¶ä¸ºäºæé«åå ¥çæçï¼å©ç¨äºæ件ç¼åç³»ç»åå åæ¥å éåå ¥æ¶çæ§è½ï¼å¹¶ä½¿ç¨æ¥å¿æ¥é²æ¢æ°æ®ç丢失ã
LSM-Tree 示æå¾å¦ä¸ï¼å¯è§ Lucene çåå ¥ææ³å LSM-Tree æ¯ä¸è´çï¼
ç»äºè¯´å°åæç´¢å¼äºï¼é½è¯´åæç´¢å¼æåäºæç´¢çé度ï¼é£ä¹å ·ä½éç¨äºåªäºæ¶ææè æ°æ®ç»ææ¥è¾¾æè¿ä¸ç®æ ï¼
å¦ä¸æ¯Luceneä¸å®é çç´¢å¼ç»æãç¨ä¾åæ¥è¯´æä¸è¿°ä¸ä¸ªæ¦å¿µï¼
IDæ¯ææ¡£idï¼é£ä¹å»ºç«çç´¢å¼å¦ä¸:
Nameï¼
Ageï¼
Sexï¼
å¯è§ä¸ºæ¯ä¸ª field é½å»ºç«äºä¸ä¸ªåæç´¢å¼ãPosting listå°±æ¯ä¸ä¸ªintçæ°ç»ï¼åå¨äºææ符åæ个termçææ¡£idãå®é ä¸ï¼é¤æ¤ä¹å¤è¿å å«ï¼ææ¡£çæ°éãè¯æ¡å¨æ¯ä¸ªææ¡£ä¸åºç°ç次æ°ãåºç°çä½ç½®ãæ¯ä¸ªææ¡£çé¿åº¦ãææææ¡£çå¹³åé¿åº¦çï¼å¨è®¡ç®ç¸å ³åº¦æ¶ä½¿ç¨ã
å设æ们æå¾å¤ä¸ª termï¼æ¯å¦ï¼
å¦ææç §è¿æ ·ç顺åºæåï¼æ¾åºæ个ç¹å®ç term ä¸å®å¾æ ¢ï¼å 为 term 没ææåºï¼éè¦å ¨é¨è¿æ»¤ä¸éæè½æ¾åºç¹å®ç termãæåºä¹åå°±åæäºï¼
è¿æ ·æ们å¯ä»¥ç¨äºåæ¥æ¾çæ¹å¼ï¼æ¯å ¨éåæ´å¿«å°æ¾åºç®æ ç termãè¿ä¸ªå°±æ¯ term dictionaryãæäº term dictionary ä¹åï¼å¯ä»¥ç¨ logN 次ç£çæ¥æ¾å¾å°ç®æ ã
ä½æ¯ç£ççéæºè¯»æä½ä»ç¶æ¯é常æè´µçï¼ä¸æ¬¡ random access 大æ¦éè¦ ms çæ¶é´ï¼ãæ以尽éå°ç读ç£çï¼æå¿ è¦æä¸äºæ°æ®ç¼åå°å åéãä½æ¯æ´ä¸ª term dictionary æ¬èº«å太大äºï¼æ æ³å®æ´å°æ¾å°å åéãäºæ¯å°±æäº term indexãterm index æç¹åä¸æ¬åå ¸ç大çç« è表ãæ¯å¦ï¼
A å¼å¤´ç term â¦â¦â¦â¦â¦. Xxx 页
C å¼å¤´ç term â¦â¦â¦â¦â¦. Yyy 页
E å¼å¤´ç term â¦â¦â¦â¦â¦. Zzz 页
å¦æææç term é½æ¯è±æå符çè¯ï¼å¯è½è¿ä¸ª term index å°±ççæ¯ ä¸ªè±æå符表ææçäºãä½æ¯å®é çæ åµæ¯ï¼term æªå¿ é½æ¯è±æå符ï¼term å¯ä»¥æ¯ä»»æç byte æ°ç»ãèä¸ ä¸ªè±æå符ä¹æªå¿ æ¯æ¯ä¸ä¸ªå符é½æåçç termï¼æ¯å¦ x å符å¼å¤´ç term å¯è½ä¸ä¸ªé½æ²¡æï¼è s å¼å¤´ç term åç¹å«å¤ãå®é ç term index æ¯ä¸æ£µ trie æ ï¼
ä¾åæ¯ä¸ä¸ªå å« "A", "to", "tea", "ted", "ten", "i", "in", å "inn" ç trie æ ãè¿æ£µæ ä¸ä¼å å«ææç termï¼å®å å«çæ¯ term çä¸äºåç¼ãéè¿ term index å¯ä»¥å¿«éå°å®ä½å° term dictionary çæ个 offsetï¼ç¶åä»è¿ä¸ªä½ç½®åå¾å顺åºæ¥æ¾ã
ç°å¨æ们å¯ä»¥åçâ为ä»ä¹ Elasticsearch/Lucene æ£ç´¢å¯ä»¥æ¯ mysql å¿«äºãMysql åªæ term dictionary è¿ä¸å±ï¼æ¯ä»¥ b-tree æåºçæ¹å¼åå¨å¨ç£çä¸çãæ£ç´¢ä¸ä¸ª term éè¦è¥å¹²æ¬¡ç random access çç£çæä½ãè Lucene å¨ term dictionary çåºç¡ä¸æ·»å äº term index æ¥å éæ£ç´¢ï¼term index 以æ çå½¢å¼ç¼åå¨å åä¸ãä» term index æ¥å°å¯¹åºç term dictionary ç block ä½ç½®ä¹åï¼åå»ç£çä¸æ¾ termï¼å¤§å¤§åå°äºç£çç random access 次æ°ã
å®é ä¸ï¼Lucene å é¨ç Term Index æ¯ç¨çãåç§çãtrieæ ï¼å³ FST ãFST æ¯ trieæ 好å¨åªï¼trieæ åªå ±äº«äºåç¼ï¼è FST æ¢å ±äº«åç¼ä¹å ±äº«åç¼ï¼æ´å çèç空é´ã
ä¸ä¸ªFSTæ¯ä¸ä¸ª6å ç» (Q, I, O, S, E, f):
ä¾å¦æä¸é¢ä¸ç»æ å°å ³ç³»ï¼
å¯ä»¥ç¨ä¸å¾ä¸çFSTæ¥è¡¨ç¤ºï¼
è¿ç¯æç« è®²çå¾å¥½ï¼ å ³äºLuceneçè¯å ¸FSTæ·±å ¥åæ
æ³æ³ä¸ºå¥ä¸ç¨ HashMapï¼HashMap ä¹è½å®ç°æåºMapï¼èå ååï¼çºç²äºä¸ç¹æ§è½æ¥è约å åï¼æ¨å¨æææTerm Indexé½æ¾å¨å åéé¢ï¼æç»çæææ¯æåäºé度ãå¦ä¸å¯ç¥ï¼FSTæ¯å缩åå ¸æ åç¼çå¾ç»æï¼å¥¹æ¥æTrieé«ææç´¢è½åï¼åæ¶è¿é常å°ãè¿æ ·çè¯æ们çæç´¢æ¶ï¼è½ææ´ä¸ªFSTå è½½å°å åã
æ»ç»ä¸ä¸ï¼FSTææ´é«çæ°æ®å缩çåæ¥è¯¢æçï¼å 为è¯å ¸æ¯å¸¸é©»å åçï¼è FST æå¾å¥½çå缩çï¼æ以 FST å¨ Lucene çææ°çæ¬ä¸æé常å¤ç使ç¨åºæ¯ï¼ä¹æ¯é»è®¤çè¯å ¸æ°æ®ç»æã
Lucene çtipæ件å³ä¸º Term Index ç»æï¼timæ件å³ä¸º Term Dictionary ç»æãç±å¾å¯è§ï¼tipä¸åå¨çå°±æ¯å¤ä¸ªFSTï¼
FSTä¸åå¨çæ¯<åè¯åç¼ï¼ä»¥è¯¥åç¼å¼å¤´çææTermçå缩åå¨ç£çä¸çä½ç½®>ãå³ä¸ºåææå°çä» term index æ¥å°å¯¹åºç term dictionary ç block ä½ç½®ä¹åï¼åå»ç£çä¸æ¾ termï¼å¤§å¤§åå°äºç£çç random access 次æ°ã
å¯ä»¥å½¢è±¡å°ç解为ï¼Term Dictionary å°±æ¯æ°ååå ¸çæ£æé¨åå å«äºææçè¯æ±ï¼Term Index å°±æ¯æ°ååå ¸åé¢çç´¢å¼é¡µï¼ç¨äºè¡¨æè¯æ±å¨åªä¸é¡µã
ä½æ¯ FST å³ä¸è½ç¥éæ个Termå¨Dictionary(.tim)æ件ä¸å ·ä½çä½ç½®ï¼ä¹ä¸è½ä» éè¿FSTå°±è½ç¡®åçç¥éTermæ¯å¦çå®åå¨ãå®åªè½åè¯ä½ ï¼æ¥è¯¢çTermå¯è½å¨è¿äºBlocksä¸ï¼å°åºåä¸åå¨FST并ä¸è½ç»åºç¡®åççæ¡ï¼å 为FSTæ¯éè¿Dictionaryçæ¯ä¸ªBlockçåç¼ææï¼æ以éè¿FSTåªå¯ä»¥ç´æ¥æ¾å°è¿ä¸ªBlockå¨.timæ件ä¸å ·ä½çFile Pointerï¼å¹¶æ æ³ç´æ¥æ¾å°Termsã
åå°ä¸é¢çä¾åï¼ç»å®æ¥è¯¢è¿æ»¤æ¡ä»¶ age= çè¿ç¨å°±æ¯å ä» term index æ¾å° å¨ term dictionary ç大æ¦ä½ç½®ï¼ç¶ååä» term dictionary é精确å°æ¾å° è¿ä¸ª termï¼ç¶åå¾å°ä¸ä¸ª posting list æè ä¸ä¸ªæå posting list ä½ç½®çæéãç¶ååæ¥è¯¢ sex=Female çè¿ç¨ä¹æ¯ç±»ä¼¼çãæåå¾åº age= AND sex=Female å°±æ¯æ两个 posting list åä¸ä¸ªâä¸âçå并ã
è¿ä¸ªç论ä¸çâä¸âå并çæä½å¯ä¸å®¹æãå¯¹äº mysql æ¥è¯´ï¼å¦æä½ ç» age å gender 两个å段é½å»ºç«äºç´¢å¼ï¼æ¥è¯¢çæ¶ååªä¼éæ©å ¶ä¸æ selective çæ¥ç¨ï¼ç¶åå¦å¤ä¸ä¸ªæ¡ä»¶æ¯å¨éåè¡çè¿ç¨ä¸å¨å åä¸è®¡ç®ä¹åè¿æ»¤æãé£ä¹è¦å¦ä½æè½èå使ç¨ä¸¤ä¸ªç´¢å¼å¢ï¼æ两ç§åæ³ï¼
Elasticsearch æ¯æ以ä¸ä¸¤ç§çèåç´¢å¼æ¹å¼ï¼å¦ææ¥è¯¢ç filter ç¼åå°äºå åä¸ï¼ä»¥ bitset çå½¢å¼ï¼ï¼é£ä¹å并就æ¯ä¸¤ä¸ª bitset ç ANDãå¦ææ¥è¯¢ç filter 没æç¼åï¼é£ä¹å°±ç¨ skip list çæ¹å¼å»éå两个 on disk ç posting listã
ç¨ä¸ä¸ªä¾åæ¥è¯´æå¦ä½ä½¿ç¨ skip list çæè·¯æ¥åå并ï¼åè Luceneå¦ä¹ æ»ç»ä¹ä¸ï¼Luceneæç´¢è¿ç¨è§£æ(5) ï¼ï¼
Advanceæä½æ¯ä»ä¹ï¼å°±æ¯ skip list æä¾çå¿«éè·³è·çç¹æ§ã
å¦å¤ä¸æ¹é¢ï¼å¯¹äºä¸ä¸ªå¾é¿ç posting listï¼æ¯å¦ï¼
[1,3,,,,,,,]
æ们å¯ä»¥æè¿ä¸ª list åæä¸ä¸ª blockï¼
[1,3,] [,,] [,,]
ç¶åå¯ä»¥æå»ºåº skip list ç第äºå±ï¼
[1,,]
1,, åå«æåèªå·±å¯¹åºç blockãè¿æ ·å°±å¯ä»¥å¾å¿«å°è·¨ block ç移å¨æåä½ç½®äºã
Lucene èªç¶ä¼å¯¹è¿ä¸ª block å次è¿è¡å缩ãå ¶å缩æ¹å¼å«å Frame Of Reference ç¼ç ã示ä¾å¦ä¸ï¼
èèå°é¢ç¹åºç°ç termï¼æè° low cardinality çå¼ï¼ï¼æ¯å¦ gender éçç·æè 女ãå¦ææ 1 ç¾ä¸ä¸ªææ¡£ï¼é£ä¹æ§å«ä¸ºç·ç posting list éå°±ä¼æ ä¸ä¸ª int å¼ãç¨ Frame of Reference ç¼ç è¿è¡å缩å¯ä»¥æ大åå°ç£çå ç¨ãè¿ä¸ªä¼å对äºåå°ç´¢å¼å°ºå¯¸æé常éè¦çæä¹ãå½ç¶ mysql b-tree éä¹æä¸ä¸ªç±»ä¼¼ç posting list çä¸è¥¿ï¼æ¯æªç»è¿è¿æ ·å缩çã
å 为è¿ä¸ª Frame of Reference çç¼ç æ¯æ解å缩ææ¬çãå©ç¨ skip listï¼é¤äºè·³è¿äºéåçææ¬ï¼ä¹è·³è¿äºè§£å缩è¿äºå缩è¿ç block çè¿ç¨ï¼ä»èèçäº cpuã
è¿ä¹å¯ä»¥çå°ï¼Lucene 为äºçå åçæ¯åå°äºæè´ã
Bitset æ¯ä¸ç§å¾ç´è§çæ°æ®ç»æï¼å¯¹åº posting list å¦ï¼
[1,3,4,7,]
对åºç bitset å°±æ¯ï¼
[1,0,1,1,0,0,1,0,0,1]
æ¯ä¸ªææ¡£æç §ææ¡£ id æåºå¯¹åºå ¶ä¸çä¸ä¸ª bitãBitset èªèº«å°±æå缩çç¹ç¹ï¼å ¶ç¨ä¸ä¸ª byte å°±å¯ä»¥ä»£è¡¨ 8 个ææ¡£ãæ以 ä¸ä¸ªææ¡£åªéè¦ .5 ä¸ä¸ª byteãä½æ¯èèå°ææ¡£å¯è½ææ°å亿ä¹å¤ï¼å¨å åéä¿å bitset ä»ç¶æ¯å¾å¥¢ä¾çäºæ ãèä¸å¯¹äºä¸ªæ¯ä¸ä¸ª filter é½è¦æ¶èä¸ä¸ª bitsetï¼æ¯å¦ age= ç¼åèµ·æ¥çè¯æ¯ä¸ä¸ª bitsetï¼<=age< æ¯å¦å¤ä¸ä¸ª filter ç¼åèµ·æ¥ä¹è¦ä¸ä¸ª bitsetã
æ以ç§è¯å°±å¨äºéè¦æä¸ä¸ªæ°æ®ç»æï¼
å¯ä»¥å¾å缩å°ä¿åä¸äº¿ä¸ª bit 代表对åºçææ¡£æ¯å¦å¹é filterï¼
è¿ä¸ªå缩ç bitset ä»ç¶å¯ä»¥å¾å¿«å°è¿è¡ AND å OR çé»è¾æä½ã
Lucene 使ç¨çè¿ä¸ªæ°æ®ç»æå«å Roaring Bitmapã
å ¶å缩çæè·¯å ¶å®å¾ç®åãä¸å ¶ä¿å 个 0ï¼å ç¨ ä¸ª bitãè¿ä¸å¦ä¿å 0 ä¸æ¬¡ï¼ç¶å声æè¿ä¸ª 0 éå¤äº éã
为ä»ä¹æ¯ä»¥ä¸ºçéï¼ç¨åºåçä¸çéé¤äºå¤ï¼ä¹æ¯ä¸ä¸ªç»å ¸å¼ï¼å 为å®=2^-1ï¼æ£å¥½æ¯ç¨2个åèè½è¡¨ç¤ºçæ大æ°ï¼ä¸ä¸ªshortçåå¨åä½ï¼æ³¨æå°ä¸å¾éçæåä¸è¡âIf a block has more than values, encode as a bit set, and otherwise as a simple array using 2 bytes per valueâï¼å¦ææ¯å¤§åï¼ç¨èçç¹ç¨bitsetåï¼å°å就豪ç½ç¹ï¼2个åèæä¹ä¸è®¡è¾äºï¼ç¨ä¸ä¸ªshort[]åçæ¹ä¾¿ã
å¨ Lucene 7.0ä¹åï¼Lucene é对 bitsetçç¨ ç¨æ§ï¼éç¨ä¸åçåå¨æ¹å¼ï¼å½ bitsetæ¯è¾ç¨çæ¶ï¼ç´æ¥åå¨DocIDï¼å½ bitset ç¨ å¯æ¶ï¼åç´æ¥åå¨ bitset çBitsæ°æ®ãæ ¹æ®æ°æ®çåå¸æ åµä¸åï¼éç¨éå½çç»æä¸ä» å¯ä»¥æé«ç©ºé´çå©ç¨çï¼è¿è½æé«éåçæçã
Elasticsearch/Lucene 为äºæåç´¢å¼åæç´¢çæçï¼ä»ä¸å±å°åºå±ï¼ä½¿ç¨äºåç§å·§å¦çæ°æ®ç»æå设计ï¼é ä¼ç§çç论å æè´çä¼åï¼åå°æ¥è¯¢æ§è½ä¸çæè´ã