起源-Lucene
- 基于Java语言开发的搜索引擎
- Lucene具有高性能、易扩展的优点
- Lucene的局限性:只能基于Java语言开发、类库的接口学习曲线陡峭、原生并不支持水平扩展
ElasticSearch主要功能
- 海量数据的分布式存储及集群管理
- 近实时搜索(新增到ES的数据在1s内就能查到)、性能卓越
- 海量数据的近实时分析
索引
文档
- ElasticSearch是面向文档的,文档可以是一封邮件、日志等可以结构化的数据。
- 文档会被序列化成JSON格式,保存在ElasticSearch
- 每个文档都有一个Unque ID
索引结构
元数据:用于标注文档的相关信息
- _index:文档所属的索引名
- _type:文档所属的类型名,一个index可以对应多个type
- _id:文档的唯一ID
- _source:文档的原始Json数据
- _all:整合所有字段内容到该字段,以被废除
- _version:文档的版本信息
- _score:相关性打分
目前使用中,大多数都是一个index,对应一个type,在ES 6.x版本中,一个索引只允许存在一个_type,后续版本会删掉这个type的概念。
- Index:索引是文档的容器,是一类文档的结合。
- Index体现了逻辑空间的概念,每个索引都有自己的Mapping定义,用于定义包含文档的字段名和字段类型
- Shard体现了物理空间的概念,索引中的数据分散在Shard上
- 索引的Mapping和Settings
- Mapping定义了文档字段的类型
- Settings定义不同的数据分布
索引的不同语义
索引(动词)文档到Elasticsearch的索引(名词)中
- 名词:一个ElasticSearch集群中,可以创建很多不同的索引
- 动词:保存一个文档到Elasticsearch的过程也叫索引,ES创建倒排索引的过程
分片
单机存储达到瓶颈的时候,需要通过增加机器来达到水平扩展的能力,同时通过路由算法找到相应的数据。
增加分片的副本有利于提高系统的可用性,但是多副本会带来写入的一致性问题。
ES数据分片分为 主和副 分片,主数据为权威数据。
分片是底层的基本读写的单元,目的是去分割巨大的索引,让读写可以并行操作,多台机器共同完成。
数据的容器是分片,分片被分配到集群的各个节点里,集群扩容或缩容的时候,会对集群节点中的分片进行迁移。
索引与分片的关系如下:
- 一个索引有很多分片,一个分片是一个Lucene的索引,是一个独立的搜索引擎,可以独立执行建立索引和搜索的任务。
- Lucene索引有很多分段组成,每个分段都是一个倒排索引。
- 每个分段内部文档的不同字段被单独建立索引。
- 每个字段右若干个词(Term)组成,Term是原文本经过分析处理后的最终结果。
分片数不够的时候,可以考虑新建索引,搜索一个有着50个分片的索引和搜索50个每个都有一个分片的索引完全等价,或者使用_split API来拆分索引。
可以创建索引别名来指向一个或多个索引,相当于软链接。
动态更新索引
倒排索引一旦被写入文件后就具备不变性
索引更新
新增的内容写入一个新的倒排索引中,查询时,每个倒排索引都轮流查询,查询完再对结果进行合并。
由于分段的不变性、更新、删除等操作实际是将数据标注为删除,记录到单独的位置,这种方式为标记删除,删除部分的数据不会释放磁盘空间。
近实时搜索
每秒产生一个新分段,新段先写入文件系统缓存,但稍后再执行flush刷盘操作,写操作很快会执行完,一旦写成功,就可以像其他文件一样被打开和读取了,ES正是利用这种特性实现了近实时搜索。
段合并
Refresh:每秒清空一次写缓冲,将数据写入文件,每次Refresh会生成一个新的Lucene段,分段太多会带来文件句柄、内存的消耗。
每个搜索请求,都需要轮流检查每个段,查询完结束之后对结果进行合并。
所以分段越多,查询越慢,所以需要通过合并策略来优化。
合并操作中,标记为删除的数据不会写入新分段,当合并过程结束,旧的分段数据被删除,标记删除的数据才从磁盘删除。
RESTAPI
正排索引和倒排索引
正排索引:从ID到文档
倒排索引:从单词到文档ID