node
集群中的每个node都可以处理http和transport请求(接收客户端请求,转发请求)
- master-eligible node:候选节点
- data node:储存数据
- ingest node:预处理document
每个node都是一个coordinating node。一个node将node.master,node.data,node.ingest全部设为false,它就只是coordinating node
注意:默认情况每个node的node.master,node.data,node.ingest都是true
大集群通常把4种node分开设置
写数据
- 客户端发送请求给协调节点(coordinating node)
- 协调节点向document进行路由,将请求转发给对应节点
- 对应节点的主分片(primary shard)处理请求,并将数据同步到副本分片(replica shard)
- 协调节点返回响应给客户端
读数据
- 客户端发送请求到任意node
- node对doc_id进行哈希路由,将请求转发到对应node,用随机轮询算法(round-robin)在主分片及其所有副本中随机选择一个,使读请求负载均衡
- 接收请求的node返回document给协调节点
- 协调节点返回document给客户端
数据搜索
- 客户端发送请求到协调节点
- 协调节点将搜索请求转发到所有对应分片
- query phase:每个分片将doc_id返回给协调节点,由协调节点整合排序产出最后结果
- fetch phase:协调节点根据doc_id去各节点拉取实际document数据,最终返回给客户端
写请求只写入主分片,之后同步给所有副本。读请求主副分片都读,采用随机轮询算法
底层原理
先写入内存(buffer),同时写入日志(translog)文件,在内存里的数据无法搜索
当内存满了 / 到时间了,刷新(refresh)数据到磁盘文件(segment file),刷新需要经过操作系统缓存(os cache)
每隔一秒,ES将内存数据写入新的磁盘文件。每秒钟产生一个新的磁盘文件,储存1秒内内存写入的数据
内存没有数据时不刷新
只要内存中的数据被刷入缓存,数据就可以搜索
ElasticSearch被称为准实时搜索(near real-time),写入数据后1秒可见。当数据刷入os缓存内存buffer即被清空,通过日志把数据持久化到磁盘文件里
日志长度到达阈值触发提交(commit),内存数据刷新到缓存,写入对应所有磁盘文件的commit point,同时将缓存里数据同步(fsync)到磁盘,清空日志并重启
提交默认30分钟执行一次,可以通过es api手动执行
当机器死机,内存(buffer和cache)的数据全部丢失,日志文件保证宕机重启后数据可以重新恢复到内存中
但是日志也需要先写入cache,每隔5秒再刷一次到磁盘,机器宕机会使5秒数据丢失
如果把日志设置成每次写数据就同步到磁盘,保证数据不丢失,性能会变差
index.translog.sync_interval 控制强刷时间,最小100毫秒
index.translog.durability request / async 每次操作都同步到磁盘 / 每隔5秒刷一次
ElasticSearch是准实时的,写入一秒后就可以被搜到。宕机可能会导致5秒数据丢失,停留在buffer,日志缓存和磁盘缓存的数据没有写入磁盘
更新删除原理
提交时生成.del文件会标识需要删除和更新doc为deleted
磁盘文件(segment file)合并(merge)时将deleted doc删除
新磁盘文件写入时写一个commit point,标识所有新的磁盘文件,将旧文件删除
Lucene
Lucene封装了倒排索引的算法代码,通过Lucene可以建立索引
倒排索引
每个文档拥有对应的文档ID,文档内容就是关键词的集合
倒排索引是关键词到文档 ID 的映射,每个ID对应一系列文档
用户查询单词,搜索查找倒排索引,找出包含这个单词的文档,搜索出的文档就是用户的搜索结果
注意:
- 倒排索引的单词根据字典升序排列