es一致性問題

概述

內部因素

es的一致性主要有兩個方面:html

  • 使用lucene索引機制帶來的refresh問題java

  • 使用分片和複製帶來的副本一致性問題(consistency:one、all、quorum)git

外部因素

外部因素的話,就是若是使用db跟es的同步機制的話,那麼這裏的同步有必定的延時,另外也有可能由於異常狀況發生不一致的狀況,好比事務回滾之類的。github

更新操做以後refresh

org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepositoryspring

@Override
    public <S extends T> S save(S entity) {
        Assert.notNull(entity, "Cannot save 'null' entity.");
        elasticsearchOperations.index(createIndexQuery(entity));
        elasticsearchOperations.refresh(entityInformation.getIndexName());
        return entity;
    }

    public <S extends T> List<S> save(List<S> entities) {
        Assert.notNull(entities, "Cannot insert 'null' as a List.");
        Assert.notEmpty(entities, "Cannot insert empty List.");
        List<IndexQuery> queries = new ArrayList<IndexQuery>();
        for (S s : entities) {
            queries.add(createIndexQuery(s));
        }
        elasticsearchOperations.bulkIndex(queries);
        elasticsearchOperations.refresh(entityInformation.getIndexName());
        return entities;
    }

一旦有更改就refresh到filesystem cache,這樣就能夠被搜索到。json

clipboard.png

副本一致性問題

可是還有一個問題,一旦有多個replication,就涉及到一致性的問題。segmentfault

  • 若是consistency是one,那麼寫入速度快,不能保證讀到最新的更改;curl

  • 若是是quorum則是相對摺中的版本,write的時候,W>N/2,即參與寫入操做的節點數W,必須超過副本節點數N的一半。若是是quorum策略,則讀取要保證一致性的話,就得使用read quorum,讀取N個副本中的W個而後仲裁獲得最新數據。或者是指定從primary上面去讀。
    相關的類async

org/elasticsearch/action/WriteConsistencyLevel.java
org/elasticsearch/action/RealtimeRequest.java
  • realtime request
    es提供了realtime request,就是從translog裏頭讀,能夠保證是最新的。elasticsearch

public class GetRequest extends SingleShardRequest<GetRequest> implements RealtimeRequest {
  //......
}

可是注意get是最新的,可是檢索等其餘方法不是(若是須要搜索出來也是最新的,須要refresh,這個會刷新該shard但不是整個index,所以若是read請求分發到repliac shard,那麼可能讀到的不是最新的數據,這個時候就須要指定preference=_primary)。

clipboard.png

  • all策略即強一致的策略

小結

若是要保證讀的強一致:

  • 當write consistency不是all的時候,須要指定從primary shard讀

  • 當write consistency爲all的時候,並且replication是sync模式(默認),無需額外指定,若是replication是async模式,則須要從primary shard讀取。

curl -XGET 192.168.99.100:9200/myindex/_settings

curl -XPUT '192.168.99.100:9200/myindex/_settings' -d '
{
    "index" : {
        "action.write_consistency" : "all"
    }
}'

可是都須要在update的時候手工refresh。

若是是讀多寫少的應用(特別是replica很少的時候),則能夠指定write consistency爲all,這樣就能夠很好地利用replica shard的讀來提高es的讀性能呢。

參考

相關文章
相關標籤/搜索