es写数据过程
- 客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)
- coordinating node对document进行路由,将请求转发给对应的node(有primary shard)
- 实际上的node上的Primary Shard处理请求,然后将数据同步到replica node
coordinating node 如果发现 primary node和replica node都搞定了之后,就返回响应给客户端
es读数据过程
可以通过doc id来查询,会根据doc id进程hash,判断出来当时把doc id 分配到哪个shard 上去,从那个shard 进行查询。
客户端发送请求到任意一个node,成为coordinate node
- coordinate node对doc id进行过哈希路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard 和 其所有的replica shard随机选择一个,让读请求负载均衡。
- 接收请求的node返回document给coordinate node
-
es搜索数据的过程
es强大的是做全文检索。
客户端发送请求到一个coordinate node
- 协调节点将搜索请求转发到所有的shard对应的primary shard或者replica shard, 都可以
- query phase: 每个shard 将自己的搜索结果(其实就是一些doc id)返回给协调节点,由协调 节点进行数据的合并、排序、分页等操作,产生最终的节点
- fetch phase : 接着由协调节点根据doc id 去各个节点拉取实际的document数据,最终返回给客户端。
写请求就是写Primary Shrd, 然后同步给所有的replica shard,读请求可以从Primary Shard或者Replica Shard读取,采用的随机轮询算法。
写数据底层原理
先写内存buffer, 在buffer里的时候是搜索不到的,同时将数据写入translog日志文件。
如果buffer快满了,或者到一定时间,就会将内存buffer的数据refresh到一个新的segment file 中,但是此时数据不知直接进入segment file 磁盘文件,而是先进入os cache, 这个过程就是refresh.
为什么es是准实时的?
默认1秒refresh一次,所以是准实时的,因为数据写入1秒之后才能被看到。可以通过es 的restful api或者java api,手动执行一次refresh操作,手动将buffer刷入到os cache中,让数据立马就可以看到。只要数据被输入到os cache,buffer就被清空了,因为不需要保留buffer了,数据在translog里面已经持久化磁盘上一份了。
translog的作用?
buffer和os cache都是内存,机器死了,内存数据丢失,将操作写入一个专门的translog, 机器宕机,再次重启,可以恢复。
丢数据问题?
translog默认5秒刷一次到磁盘中去,所以默认情况下,可能有5秒的数据仅仅停留在buffer或者translog的os cache中,如果机器挂了,会丢失5秒的数据。
总结:数据先写入内存buffer, 然后每隔1s,将数据refresh到os cache, 到了os cache就能被搜索到了。(所以我们说es从写入到被搜索到,中间有1秒的延迟),每隔5秒,将数据写入到translog,(这样如果机器宕机,内存数据全没,最多会有5秒的数据丢失),translog大到一定程度,或者默认每隔30分钟,会触发commit操作,将缓冲区的数据flush到segment file磁盘文件上。
删除/更新数据底层原理
如果是删除操作,commit的时候会生成一个.del的文件,里面将某个doc标识为deleted状态,那么搜索的时候根据.del文件就知道这个doc是否被删除了。
如果是更新操作,将原来的doc标识为deleted状态,然后新写入一条数据。
buffer 每refresh一次,就会产生一个segment file , 所以默认情况下1秒钟产生一个segment file, 这样segment file 会越来越多,此时会定期执行merge,多个合并成一个,同时会将标识为deleted的doc给物理删除掉,然后将新的segment file写入磁盘,这里会写一个commit point,标识所有新的segment file, 然后打开segment file 供搜索使用,同时删除旧的segment file.
底层lucene
lucene就是一个jar包,里面包含了封装好的各种建立倒排索引的算法代码。
倒排索引
倒排索引就是关键词到文档id的映射,每个关键词都对应着一系列的文件,这些文件中都出现了关键词。
倒排索引的两个重要细节:
- 倒排索引中的所有词项对应一个或者多个文档
- 倒排索引中的词项根据字典顺序升序排列。