Elasticsearch是基于一款高性能的、可扩展的信息检索工具库Lucene构建的强大的搜索引擎,在很多情况,它也被作为NoSql数据库并取得了很好的效果,下面介绍下ES的基本概念,映射到数据库的概念就比较好理解。
集群(Cluster):一组拥有共同的cluster name的节点,新创建的节点只要指定集群名,启动后就会自动加入集群,称为其中的节点,整个集群可以认为是一个数据库引擎。
节点(Node) :集群中的一个Elasticearch实例,可以是一个虚机,容器等,每个实例有独立的存储,不会由于一个节点的故障导致数据丢失。
索引(Index) :相当于关系数据库中的database概念,一个集群中可以包含多个索引,索引名就是库名
分片(shard):一个索引会被切割成多个分片,分布到不同的集群节点上,每个主分片可以有一个或者多个副本,副本不和主分片在同一个节点上,以便完成数据备份。
类型(Type):相当于数据库中的table概念,mapping相当于数据库中的schema,是针对 Type 的,同一个type下要求格式一致,同一个索引里可以包含多个 Type。
文档(Document) :相当于数据库中的row,是查询的实体。
字段(Field)相当于数据库中的column。
ES也是采用主从模式和运用了服务发现的原理,业界成熟的服务发现组件有Zookeeper/etcd/Consul,但是ES并没有采用这些组件,而是自己实现了一个ZenDiscovery,当启动节点时,先使用内部实现的RPC命令ping来调用其他host,从各节点返回的信息里获取master节点信息并认主,如果没有主,则根据id的排序顺序选一个主出来,主节点负责监控从节点的状态,并协调分片的位置和职责。一旦有节点加入集群,主节点会根据分片及节点数量调整各节点拥有的分片数量,调整始终会保证主分片和副本分片(一般有多个副本)放在不同的节点,当某节点故障后,主节点会删除该节点,并重新调整分片,如果某主分片在那个节点,主节点会重新为该分片指定一个主分片,必须保证任一单个节点故障,ES都能正常提供服务,数据不会丢失,节点主从,索引分片,分片副本,副本散列分布都是为了解决这个问题,而分片分散分布在各节点也会提高搜索效率。
ES最为我们所赞叹的是其强大的索引能力,这也是现在ES如此受亲睐的原因。在索引机制上,ES使用倒排索引,倒排索引是相对正排索引的,正排索引大概是这样一个套路:文档1包含什么单词,出现了几次,在哪里出现的,文档2包含什么单词,出现几次,在哪里出现...。这样方式在查询的时候我们必须去扫描所有文档,并获取文档存储的内容,大大影响的查询效率,而倒排索引反其道而行,以关键词为key,映射文档的id,当我们存储一个文档,首先提取其包含的关键字,然后将关键字作为key,包含该关键字的文档id作为value,类似这样:key1:1,2,3;key2:2,4,这样当我们查询某key的时候就可以直接查询到哪些文档包含个key,大大节省了查询效率。但ES做的不止这些,比如查到的文档非常多我们该怎定位到某一个文档,全部放到内存里过滤不太现实,会把内存撑爆,ES采用的index分页机制和FST压缩技术来实现,index分页机制会存储查询条目的前缀,以及前缀所指向的block的映射关系,FST压缩技术则通过对前缀和后缀的重复利用来压缩存储空间这样,存储在内存的数据量就会大幅度下降,我们通过前缀找到对应的block,然后再通过二分法查找目标文档,减少了磁盘读取次数。总体来讲,Elasticsearch的索引思路就是将磁盘里的东西尽量搬进内存,减少磁盘随机读取次数(同时也利用磁盘顺序读特性),结合各种奇技淫巧的压缩算法,用及其苛刻的态度使用内存。
为了理解ES的一些机制,下面通过ES的读写操作来进行说明。
当我们向ES写数据时,节点收到信息会先查找文档属于哪个分片,该分片位置,然后将消息路由过去,执行插入命令成功时,将内容返回,并并行的将数据同步到其他分片的副本,全部副本更新成功后才会向客户端返回成功。这么做是为了保证主切片与副本的数据同步。
对于读操作,请求节点会为每个请求选择不同的副本来完成负载均衡,默认的负载均衡策略是轮询。
对于更新操作,节点收到信息会先查找文档属于哪个分片,该分片位置,然后将消息路由过去,查询当前内容,把查到的内容修改然后执行插入,如果发现文档被修改,则重新查询、修改、插入,完成后,并并行的将数据同步到其他分片的副本,全部副本更新成功后才会向客户端返回成功。