1、elasticsearch之脑裂问题
(一)背景分析:
- 脑裂问题(split-brain),是分布式系统中的经典网络问题。
- 比如集群有3个节点(node1,node2,node3)。如果此时由于网络问题,node1无法和node2,node3访问,则node2和node3会重新选举master,然后更新cluster state;
- 而node1自己组成集群后,也会更新cluster state。
- 同一个集群有2个master,而且维护不同的 cluster state,那么网络恢复后则会产生矛盾,无法选择正确的master。
(二)解决方案:
- 可配置可选举master-eligible 节点数大于等于 quorum时才可以进行master选举。
- quorum=master-eligible 节点数/2 + 1,例如 3个master_eligible 节点时,quorum是2.
- 设定discovery.zen.minimum_master_nodes=quorum 即可避免脑裂问题。
(三)一些优化:
##一个节点多久ping一次,默认1s
discovery.zen.fd.ping_interval: 1s
##等待ping返回时间,默认30s
discovery.zen.fd.ping_timeout: 10s
##ping超时重试次数,默认3次
discovery.zen.fd.ping_retries: 3
##选举时需要的节点连接数
discovery.zen.minimum_master_nodes=N/2+1
2、segment、refresh、translog、flush
(一)segment
- lucene 构建的单个倒排索引称为 segment,合在一起称为 index。这里与es 的 index 概念不同。es中的一个shard 对应一个 lucene index。而其 es 的index是可分布在多个shard 上的。
- lucene 会有一个专门的文件来记录所有的 segment 信息,称为 commit point。如下图所示:
(二)refresh
- segment 写入磁盘过程很耗时,可以借助文件系统缓存的特性,先将 segment 在缓存中创建并开放查询来进一步提升实时性,该过程在es 中被称为 refresh。
- 在refresh 之前文档会先存储一个在 buffer 中,refresh 时将 buffer 中的所有文档清空并生成 segment。
- es默认每1秒执行一次refresh,因此文档的实时性被提高到1秒,这也是es被称为近实时(Near Real Time)的原因。如下图:
(三)translog
- 如果在内存中的 segment还没有写入到磁盘前发生了宕机,那么其中的文档就无法恢复了,为解决这个问题,translog 产生了。
- es引入translog机制。写入文档到 buffer 时,同时将该操作写入translog(操作记录)。
- translog文件会即时写入磁盘(fsync,异步),6.x默认每个请求都会落盘,可以修改为每5秒写一次,这样的风险就是有可能会丢失5秒内的数据,这个可以通过配置修改,相关配置为index.translog.*(请自行查阅)。
- es启动时会检查translog文件,并从中恢复数据。
(四)flush
flush 负责将内存中的 segment写入磁盘,主要作如下的工作:
- 将 translog 写入磁盘;
- 将index buffer清空,其中的文档生成一个新的 segment,相当于一个 refresh 操作;
- 更新 commit point并写入磁盘;
- 执行 fsync 操作,将内存中的 segment 写入磁盘;
- 删除旧的 translog文件。
- flush工作较多,耗时长。
(五)其他
1> refresh 发生的几种情况:
- 间隔时间到达是,可通过index.settings.refresh_interval 来设定,默认是1秒;
- index.buffer 占满时,其大小可通过 indices.memory.index_buffer_size来设定,默认为 jvm heap 的10%,所以shard共享。
- flush 发生时会发生 refresh。
2> flush 发生的几种情况:
- 间隔时间达到时,默认是30分钟,5.x之前可以通过 index.translog.flush_threshold_period 修改,之后无法修改;
- translog 占满时,其大小可通过设置 index.translog.flush_threshold_size 控制,默认是 512mb,每个index 都有自己的translog。
3> 删除与更新文档
- segment 一旦生成就不能更改,否则更多的io 造成性能不好。此时删除就出现问题了。
- lucene为解决上述问题,专门维护了一个 .del的文件,记录所有已经删除的文档,注意 .del 上记录的是文档在 lucene内部的 id。
- 然后在查询结果返回前会过滤掉 .del中的所有文档。
- 更新文档其实es是先删除文档,再创建新文档。
4> segment merging
- 随着 segment的增多,会造成查询效率下降(因为一次查询的segment太多了);
- es会定时在后台进行 segment merge 操作,减少 segment 的数量;
- 通过force_merge API可以手动强制做segment merge 的操作。
3、elasticsearch之ingest node
(一)、介绍:
- 5.x新增的一个节点类型。
- 在数据写入es前(bulk/index 操作)对数据进行处理
- 可设置独立的ingest node 专门进行数据转换处理,node.ingest: true
- api endpoint 为 pipeline
(二)、pipeline
(1)pipeline 是由一系列的 processor 组成,可看成是 logstash 的 filter plugin,结构如下:
{
"description": "xxx",
"processor": [ yyy ]
}
(2)pipeline api
PUT 创建,GET 获取,DELETE 删除,SIMULATE 模拟调试
举例:
1》
PUT _ingest/pipeline/test
{
"description": "for test",
"processor": [
{
"set": { // 输出增加一个name字段,其值是 hahaha
"field": "name",
"value": "hahaha"
}
}
]
}
2》
GET _ingest/pipeline/test
3》
DELETE _ingest/pipeline/test
4》
POST _ingest/pipeline/_simulate
{
"pipeline": {
"description": "for test",
"processor": [
{
"set": { // 输出增加一个name字段,其值是 hahaha
"field": "name",
"value": "hahaha"
}
}
]
},
"docs": [
{ // 测试pipeline,展示my message 在你指定pipeline的表现
"_source": {
"message": "my message"
}
}
]
}
5》
POST _ingest/pipeline/test/_simulate // 此处使用的 是test pipeline
{
"docs": [
{ // 测试pipeline,展示my message 在你指定pipeline的表现
"_source": {
"message": "my message"
}
}
]
}