ES
ES 三大操作:
构建索引、检索数据、聚合数据
ES 特性:
分布式、倒排索引、近实时、相似精度
适用场景:
倒排索引可以为一个文档中每个term提供索引,特别适合解决由于查询条件组合场景过多,导致索引数量急剧膨胀的查询场景。
ES查询过程:
查询-合并过程大致过程:master 接收请求,分发到shard查询,轮询shard查询结果,最后合并排序后返回。
举例:如果客户端需要2条数据,从小到大排序,master会向每个shard收集f2条数据,最终master会获得shardCount*pageSize条数据,shardCount是总分片数,pageSize是请求所需单页数据量。
分片:分片是对一个大数据索引的分割。分片数可以大于node集群节点数,集群节点数也可以大于分片数。一般有5个node节点,5个分片,会均匀分布到5个node节点上;如果有3个node节点,但是有5个分片,某些node节点上会存储多个分片。反之,分片数小于node节点数,可能是处于分片备份的考虑,比较浪费机器。一般分片数都会大于等于node节点数,预留一定的扩容空间。
routing功能:ES可以提供分片路由功能,如果不开启分片路由,收到查询请求的节点(暂且称为master)会广播查询请求到各个node节点,开启分片,只会像分片所在node节点发起查询请求。当然跨分片查询时有发生。
内存分配:官方建议物理内存50%预留,主要是文件缓存系统使用,缓存磁盘上的索引数据,减少磁盘IO,硬盘速度影响ES速度。剩余内存分配JVM大内存,如上ES查询需要开辟大量的缓存队列,及其消耗内存,内存不足时,OOM也是常有的事情。ES还有大量的缓存机制都是消耗内存的。
term缓存:缓存term到文档的映射
fiter缓存:缓存单一filter查询结果,缓存的粒度过大不利于命中,比如按照所有查询条件缓存,粒度过小,意义不大,对查询效率提高不明显。粒度过小可能已经接近索引本身粒度。
段合并:段合并主要是lucene索引段合并。lucene构建索引很有意思,在发生修改和删除操作时,通常不是直接修改和删除索引中对应数据,而是额外增加一个文件记录这部分修改。查询结果返回前,会根据这个文件删除已经删掉和修改的数据。修改过的数据所在的新的索引段文件,同样也会参与搜索,以此来保证修改后的最新数据参与搜索并返回。这种机制也带来一个问题,就是查询结果的不精确性。
注意事项:
段合并是一个比较消耗资源的操作,除非你很清楚它的机制,否则不建议频繁手动发起,而是应该根据业务场景对数据实时性的要求权衡,通过配置,让ES自发的发起段合并。尽管段合并可能会带来查询效率提升,但是合并过程代价很大,要做出选择。
ES不支持join操作,这对数据模型选择会造成一些干扰。通常建议,按照业务场景组织数据,数据尽量扁平化,消除join需求。扁平化对查询效率也是友好的,可评估的。
内存分配:50%原则,文件系统缓存不应该被挤压。
bulk操作:有时我们通过bulk操作以提高数据处理速度,但是bulk会占用大量资源,比如网卡IO,对bulk操作进行IO流量限制是一个不错的选择,同时应该让你的bulk操作尽可能的平稳,消除毛刺峰值。
集群下打分:集群环境下,打分机制可能无法权衡所有分片的整体情况,而造成某些node节点打分失实的情况。用于计算相关度的词项统计信息是基于分片的。如果有许多分片,每一个都只有很少的数据会导致很低的相关度。可能分片A中的最高分,放到分片B中只能处在中下排名,但是有时为了效率问题,这些公平性被抹杀。处理分片时,还是需要注意的,尽可能的减弱这种影响。
使用索引别名:有助于重新索引以及在线升级
避免发生swapping:vm.swappiness = 1 或 bootstrap.mlockall: true
深度分页:先查后取的过程支持用 from 和 size 参数分页,但是这是 有限制的 。 要记住需要传递信息给协调节点的每个分片必须先创建一个 from + size 长度的队列,协调节点需要根据 number_of_shards * (from + size) 排序文档,来找到被包含在 size 里的文档。