您的当前位置:首页正文

ElasticSearch(七):分布式特性

来源:华拓网

一 分片和副本

  • 分片特性
    分片存储部分数据,可以分布任意节点上;
    分片在创建索引时指定且不许更改,默认为5个;
    分片有主副之分,四线数据高可用;
    副本分片的数据由主分片同步,提高读取吞吐量;
  • 实例操作
集群设置:
node1/node2/node3,且node1为主节点;
创建索引:
PUT test_index
{
  "settings":{
    "number_of_shards":3, ##分片数为3
    "number_of_replicas":1 ##副本数为1
  }
}
分片和副本分布:
node1-p0 r1 node2-p1 r2 node3-p2 r0
  • 问题
1-在上述的分布式环境中,增加节点数是否提高test_index的数据容量?
不能,因为只有3个分片,且已经分布在3台节点上,新增节点无法使用;
2-增加副本数是否可以提高test_index的读取吞吐量?
不能,新增的副本依然分布在三个节点上,利用同样资源;
3-建议:
分片数过小,无法通过新增节点实现水平扩容;
分片数过大,导致一个节点上存在多个分片,造成资源浪费;

二 集群状态

  • 集群状态
    Green:健康状态,所有主副分片正常分配;
    Yellow:主分片分配正常,但是副本分片分配不正常;
    Red:存在主分片未分配;
  • 故障转移
集群设置:
node1/node2/node3,且node1为主节点;
主分片数为3,副本数为1,

故障转移:
1-主副分片分布为:node1-p0 r1 node2-p1 r2 node3-p2 r0,当前集群为Green状态;
2-node1宕机,node2/node3发现node1宕机后,发起master选举,假设node2为新主节点,
此时主副分片分布为:node2-p1 r2 node3-p2 r0,集群为Red状态;
3-由于主分片p0未分配,新主节点node2将node3上的r0副分片提升为主分片p0,
此时主副分片分布为:node2-p1 r2 node3-p2 p0,集群为Yellow状态;
4-node2为p0和p1生成新的副本,
此时主副分片分布为:node2-p1 r2 r0 node3-p2 p0 r1,集群为Green状态;

三 文档分布式存储

  • 文档到分片的映射
    文档在分片中尽量分布均匀,充分利用资源;
文档映射算法:
shard = hash(routing) % number_of_primary_shards
1-hash算法保证数据均匀分布在分片中;
2-routing是关键参数,默认是文档id,也可自行指定;
3-算法与主分片数有关,分片数确定后不可更改的原因;

四 脑裂问题

  • 脑裂
    同一个集群中两个master,维护不同的cluster state,网络恢复后无法选择正确的master;
  • 实例操作
集群设置:
node1/node2/node3,且node1为主节点;
脑裂发生:
1-node1与node2和node3间的网络发生隔离;
2-node2与node3自己选举新主节点node2,node2维护新的cluster state;
3-node1自己组成集群后,更新自己的cluster state;
4-网络恢复后,一个集群两个master,两个cluster state,无法恢复统一;
解决方案:
可选举的master-eligible节点数大于quorum时进行master选举,
quorum = master-eligible/2 + 1
在以上问题中,node1数目小于quorum2,无法进行master选举;
设定discovery.zen.minumum_master_nodes为quorum即可避免脑裂;

五 文档搜索实时性

  • refresh
    segment写入磁盘耗时,借助文件系统缓存特性,将segment缓存并开放搜索实时性,称为refresh;
    refresh之前将文档存储到一个buffer中,refresh时将buffer中的文档清空生成segment;
refresh发生时机:
1-间隔时间到达,通过index.settings.refresh_interval来设定,默认时1秒;
2-index.buffer满时,其大小通过indices.memory.index_buffer_size设置,默认为JVM heap的10%,所有shard共享;
3-flush发生时发生;
  • translog
    解决内存中segment未写入磁盘就发生宕机问题;
    文档写入buffer时,同时将请求操作写入translog,6.x默认每个请求都落盘;
    Es启动时检查translog文件,并从中恢复数据;

  • flush
    负责将内存中的segmet写入磁盘;
    将index buffer清空,其中的文档生成一个新的segment,相当于一个refresh操作;
    更新commit point并写入磁盘;
    执行fsync操作,将内存中的segment写入磁盘;
    删除旧的translog日志;

flush发生时机:
1-间隔时间到达时,默认时间时30分钟,5.x之前通过index.translog.flush_threshold_period修改;
2-translog占满时,大小通过index.translog.flush_threshold_size控制,默认时512m;
  • 删除与更新文档
    segment一旦创建就不能更改,如何删除与更新文档呢?
删除:
1-维护一个.del文件,记录所有删除文档的id,查询时过滤.del中的所有文档;
更新:
1-首先删除文档,后新建文档;
  • segment merge
    Es会定时在后台进行segment merge操作,减少segment的数量;
    通过force_merge api实现手动强制做segment merge;