es是分布式的,存在很多节点,每个节点是以lucene为基础的。
分布式都是有主副分片的,分片是shard,主分片是primary_shard,副分片是replica_shard。一般是有几个节点就会有几个主分片,一个节点对应一个主分片,这是数据安全的考虑,一个主分片一般会有一到两个副分片,同一主副分片的分片是存储在不同的节点上的,这是为了数据完整性的考虑。对于消息应该存储到哪个分片中,这是由哈希值对主分片总数取余来确定的,当主分片和其一个副分片写入成功后,才会返回写入成功的响应。
每个分片其实是由很多个segment组成的。由commit文件来维护该分片中的segment组成。并且为了实现数据的高可靠性,数据从进入内存到写入segment,还需要经过translog和文件缓存。translog相当于内存中数据的备份,文件缓存是在写入磁盘中的segment之前的缓存。数据在写入内存之后,会先存入translog,生成文件缓存,文件缓存是为了保证服务的实时性而设计的,因为读写磁盘太慢,因此文件缓存也会加入到搜索范围使其可以被实时搜索到。文件缓存最后会生成一个新的segment。然后commit文件更新其segment的范围。从内存到文件系统默认是一秒一次。从内存到文件系统的动作称为refresh,es提供了接口/_refresh来实现主动刷新,从上面可以知道commit内容和分片的搜索范围并不是始终一致的。
translog是为了防止从文件缓存写道磁盘时发生硬盘故障时,会从commit的位置开始,恢复整个translog的内容,保持数据一致性。当从文件系统写入磁盘和commit 文件更新成功之后,translog文件会清空,这一步叫flush,es也提供了/_flush接口可实现主动调用。
segment的合并由于每秒钟生成一个segment文件,如果不做合并的话commit文件中就会包含很多segment文件,性能绝对不高,因为有合并线程定时合并小的segment文件为大的segment文件,但是每个segment文件最大不超过5G。
查询查询数据的时候,就是会先从每个主分片查到相同数目或全部的数据,然后对所有分片返回的数据进行排序筛选,得到满足数目的数据返回。