Elasticsearch基本组成
Elasticsearch组成示意图
Cluster
+--------------------------------------------------------------------------+
| Node 1 Node 2 |
| +-----------------------------+ +-----------------------------+ |
| | | | | |
| | +---------+ +-----------+ | | +---------+ +-----------+ | |
| | | shard A | |replica B1 | | | | shard B | |replica A1 | | |
| | +---------+ +-----------+ | | +---------+ +-----------+ | |
| | | | | |
| +-----------------------------+ +-----------------------------+ |
| |
| Node 3 |
| +---------------------------------+ |
| | | |
| | +-------------+ +-----------+ | |
| | | reaplica A2 | |replica B2 | | |
| | +-------------+ +-----------+ | |
| | | |
| +---------------------------------+ |
| |
+--------------------------------------------------------------------------+
Elasticsearch是一个分布式系统,以集群(Cluster)方式运行。所谓集群就是多台计算机
协同对外提供服务,是相对于单台计算机而言,集群方式有两个好处:1. 集群内某台计算
机出现故障时,不影响集群作为一个整体对外提供服务,2. 充分了利用了多台计算机的运
算能力,有更强的服务能力。上图中的Node 1、Node 2和Node 3分别指集群内的一台计算
机,Node也可以按照英文本义翻译成节点。
在Elasticsearch的语境中,Index(索引)有两种意思:
- 含义和mysql中的索引类似,就是为了便于搜索,写入时建立的索引结构
- 类似mysql中的表(table)的概念,结构和逻辑上相似的数据组成的集合,称为一个Index
这一节讨论的是第2种含义的索引(Index)
在分布式的情况下,一个索引(Index)被分成很多分片(shard),每一个分片是一个相对独立
单元,能够提供数据写入, 更新, 查询等.不同分片(shard)可以分布在不同的Node上,以便
充分利用分布式多台计算机的优势.
一个分片(shard)还可以有一个或者多个副本,分片副本的数据完全拷贝对应分片的数据,
这也是从分布式系统容灾的角度设计的.当一个分片所在机器因为某种原因无法提供服务时
或者数据丢失时,该分片的副本此时能提供服务.
一个索引的分片数量在索引创建后就不可更改,分片副本数量可以随时更改
shard内部结构
Elasticsearch是基于Apache Luence开发的,一个分片(shard)是相对独立的单元,实际是一
个Luence中的索引(Index),它的内部结构如下:
shard(Luence Index)
+-------------------------------------+
| segement1 |
| +-+ segement2 |
| | | +-+ segement3 |
| | | | | +-+ segement4 |
| | | | | | | +-+ |
| | | | | | | | | |
| +-+ +-+ +-+ +-+ |
+-------------------------------------+
shard由许多segement组成,一个segement可以看成是一个小的索引,可以进行文档的搜索
segement中存储数据的结构有: Inverted Index(倒排索引)、Stored Field、
Document Value(field cache)。
- Inverted Index(倒排索引)用于搜索,可以根据搜索关键词,快速找到匹配文档的ID
- stored Field原始的文档,Elasticsearch中原始文档是json格式的字符串,我们可以根
据文档ID从Stored Field中获取某个字段的值 - Document Value的用途和Stored Field一样,也是为了根据文档ID来获取某个字段的值,
但Document Value获取的速度更快,对于大量数据aggregation(聚合)的场景场景十分有用
segement本身还有一个重要性质:segement对象创建后是不可变的。这意味着Elatic-
search在删除请求时,并不会立刻删除文件,而是将segement中的文件先标记为删除状态。
segement创建的时机有2个:新增文档时或者segement合并。
- 新增的文档首先进入到内存中缓存(此时无法被搜索到),默认情况下,每隔1s钟,
Elasticsearch会把缓存的文档刷新到一个新建的Segement里(此时可以被索引到)。这也是
Elasticsearch不是实时,而是接近实时(near real time)的原因。 - 随着时间推移,Shard里会有越来越多的大大小小的segement,这时Elasticsearch会合并
小的segement,合并的同时,会真正删除掉标记为删除的数据
Inverted Index(倒排索引)
Inverted Index(倒排索引)结构并不复杂,我们直接看一个例子,假设有以下3条数据:
1: winter is coming
2: ours is fury
3: the choice is yours
对应的Inverted Index(倒排索引)如下
terms frequency documents ID
-----------------------------------
choice 1 3
comming 1 1
fury 1 2
is 3 1,2,3
ours 1 3
the 3 1,2,3
winter 1 1
yours 1 3
输入的字符串经过处理得到了terms,包含terms的文档ID和出现频率也记录了下来。
当我们根据某个词语搜索时,能够迅速得到包含这个词语的文档,这是Elasticsearch搜索
的原理。
其他一些高级的搜索也是基于同样原理,比如中文里的根据拼音首字母搜索,在插入数据
时可以建立拼音字母的terms,比如有下面的文档
1: 北京大学
2: 清华大学
为了支持拼音首字母搜索,可以建立下面的索引
terms frequency documents ID
-----------------------------------
bjdx 1 1
qhdx 1 2
由此也说明,处理输入数据得到terms这一步是非常重要的
一次完整的搜索过程
Elasticsearch Cluster
+--------------------------------------+
| +-------+ |
| .---->|Node B | |
o ...{"term":"winter"}... | +------+ / +-------+ |
T -------------------------+----> |Node A|/ |
/ \ | | |\ +-------+ |
| +------+ `----->|Node C | |
| +-------+ |
+--------------------------------------+
- 用户发起查询请求,查询语法是Elasticsearch特有的,也是JSON格式的
- 请求随机的分发到Node A,由Node A来处理这个请求
- NodeA根据请求的索引,把请求分别发送到改索引的所有shard
- 各个shard接收到请求后,在shard内的每个segement里执行搜索请求,然后每个
segement的数据 - 各个shard把自己的搜索结果发送给Node A, Node A汇总最后的结果,返回给用户
Elasticsearch和CAP定理
Elasticsearch作为一个分布式系统究竟有多可靠呢?特别是在发生网络故障的时候?
这不是一个容易回答的问题,Elasticsearch官方长期维护了一个页面
说明这个问题.
总之把Elasticsearch当作主要的数据存储并不被推荐,认为Elasticsearch不丢数据的想法
也是不对的.