关于es的一些问题
什么叫倒排索引?
关键词和数据的关联,保存到倒排表,查询时从倒排表中进行查询
es为什么要把索引设计成不可变的, 索引不可变有什么好处?
es是支持集群的,这就必然涉及到一个多线程多进程的问题。假如索引可变,就必须增加锁的机制,所以,索引不可变就不需要锁了。降低了系统的复杂度。
索引不可变的另一个好处就是可以更有效的利用内存,由于索引不可变,当索引 一旦被读入内存,他就可以一直在那儿,只要系统有足够的内存空间,大量的读就可以直接通过访问内存来完成,极大的提高了系统的性能。总结来说,不可变有两个好处,一是不用考虑锁,二是高效利用内存。
索引不可变每次更新文档都需要将旧索引删除重新建立索引,更新频繁的话会很影响效率,es如何解决索引更新的问题?
es为了解决这个问题,引入了动态索引的思想。
动态索引的本质是多个索引,当新增文档时,直接生成一个新的索引,当进行查询时,将每个索引的数据都查询出来,然后进行聚合处理。
索引过多时,查询结果聚合也会影响查询效率,es如何解决这个问题?
在es中每一个倒排索引都称之为一个segment(段)。es查询时会将所有的segment结果查询出来然后进行聚合汇总返回。索引不可变,事实上就是segment不可变。当segment不断增多时,合并汇总的压力会增大,此时会触发es的segment合并的线程,将许多小的segment合并成一个大的segment,并删除原来小的segment
es 如何保存数据的?(translog的作用)
对于es来说,文档也不是直接就放进文件中,而是先会在内存中进行处理,处理成索引信息后,会等到缓冲区满或显示提交时,才会保存到文件中。
但是如果es进程出现问题,数据就可能会丢失。所以,es在索引之会先写入translog,该日志写在文件中,然后生成索引,最后才会保存到文件中。这样就算es进程出现问题,会先从translogh中进行恢复,保证了数据不丢失‘。
回顾es索引过程,不断写入操作translog就会不断增大,而已经写入成功的transLog其实是完全没有必要存在的,es如何解决的?(flush)
es的策略是flush,即每30分钟将translog向磁盘转移一次,转移成功后就会清空translog.当translog达到设定得最大值时,即使没到30分钟也会进行flush。
可以通过配置修改flush的间隔时长以及触发的最大值等。如下:
index.translog.flush_threshold_ops:当发生多少次操作时进行一次flush。默认是 unlimited。
index.translog.flush_threshold_size:当translog的大小达到此值时会进行一次flush操作。默认是512mb。
index.translog.flush_threshold_period:在指定的时间间隔内如果没有进行flush操作,会进行一次强制flush操作。默认是30m。
index.translog.interval:多少时间间隔内会检查一次translog,来进行一次flush操作。es会随机的在这个值到这个值的2倍大小之间进行一次操作,默认是5s。
近实时搜索
在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh 。 默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是 近 实时搜索: 文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。默认每秒刷新一次。可以修改这个刷新频率,
PUT /my_logs
{
"settings": {
"refresh_interval": "30s"
}
}
也可以关闭
PUT /my_logs/_settings
{ "refresh_interval": -1 }
打开
PUT /my_logs/_settings
{ "refresh_interval": "1s" }
es写数据的流程
1. 客户端请求集群节点(任意) 协调节点
2. 协调节点将请求转换到制定的节点
3. 主分片需要将数据保存
4. 主分片将数据发送给副本
5. 副本保存成功后进行反馈
6. 主分片进行反馈
7. 客户端获得反馈
es的master选举流程
- es的选主是由Zendiscovery模块负责的,主要包含ping(各个节点之间通过这个RPC来发现彼此)和Unicast(单玻模块包含一个主机列表以控制那些节点需要ping通)这两部分
- 对所有可以成为master的节点(node.master:true)根据nodeId字典排序,每次选举每个节点都把自己所知道的节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
- 如果对某个节点的投票数达到一定的值(可以成为master节点数n/2 + 1)并且该节点自己也选自己,那么这个节点就是master。否则重新选举一直到满足为止。
- master节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理(数据节点完成);data节点可以关闭http功能
es的脑裂产生的原因有哪些?
- 网络问题:集群间的网络延迟导致一些节点访问不到master,认为master挂掉了从而选举出新的master,并对master上的分片和副本标红,分配新的主分片。
- 节点负载:主节点的角色既为master又为data,访问量较大时可能会导致ES停止响应造成大面积延迟,此时其它节点得不到主节点的响应,就认为主节点挂掉了,重新选举新的主节点。
- 内存回收:data节点上的ES进程占用的内存较大,引发了JVM的大规模内存回收,造成ES进程失去响应。
脑裂问题如何解决?
- 减少误判:discovery.zen.ping_timeout节点状态响应时间默认为3s,可以适当调大,如果master在该响应时间范围内没有做出响应,判断该节点挂掉。适当调大可以减少误判。
- 选举触发:discovery.zen.minimum_master_nodes:1。选举发生的最小集群主节点数量,官方建议(n/2)+1,n为主节点个数
- 角色分离:master节点与data节点分离,限制角色 主节点
node.master:true node.data:false,从节点node.master:false node.data:true
es获取数据流程
1. 客户端发送查询请求到协调节点
2. 协调节点计算数据所在的分片以及全部的副本
3. 为了负载均衡,可以轮询所有的节点
4. 将请求转发给具体的节点
5. 节点返回查询结果,将结果反馈给客户端
es 更新一个文档
1. 客户端发送一个更新请求到协调文档
2. 协调节点将请求转发到主分片
3. 主分片不断尝试写入(可能有其他写入,需要等待,锁的概念)
4. 主分片将数据同步给副本
- 分片是将数据的水平拆分(可以结合mysql的分表来理解 ),副本 是对数据的备份
- 写文档:分片选择 hash(id)%分片数
- 分片控制:用户可以访问任何一个节点获取数据,这个节点称之为协调节点
- refresh是将数据写到os cache的过程,默认1s执行一次,写入到缓冲区(或disk)之后,数据才可被检索
- flush是数据从缓冲区或translog写到disk过程,默认执行规则是30分钟一次,或者translog达到设定最大值
- 新的数据写入索引时,就会创建一个新的segment
参考:
- https://www.codenong.com/1662561743496601320/
- https://www.elastic.co/guide/cn/elasticsearch/guide/current/near-real-time.html
- https://www.bilibili.com/video/BV1hh411D7sb