2.X/6. Modeling Your Data

6-4-14. Scale Is Not Infinite

drscg 2017. 9. 23. 12:55

Throughout this chapter we have spoken about many of the ways that Elasticsearch can scale. Most scaling problems can be solved by adding more nodes. But one resource is finite and should be treated with respect: the cluster state.

이 장 전반에 걸쳐, Elasticsearch를 확장하는 많은 방법에 대해 이야기했다. 대부분의 확장 문제는 더 많은 node를 추가하여 해결할 수 있다. 그러나, 어떤 자원은 유한하고 고려되어야 한다. 그것이 cluster state이다.

The cluster state is a data structure that holds the following cluster-level information:

cluster state 는 cluster-level의 정보를 가지고 있는 아래와 같은 데이터 구조이다.

  • Cluster-level settings

    cluster-level의 설정

  • Nodes that are part of the cluster

    cluster의 일부인 nodes

  • Indices, plus their settings, mappings, analyzers, warmers, and aliases

    indices, 그리고 index의 settings, mappings, analyzers, warmers, aliases.

  • The shards associated with each index, plus the node on which they are allocated

    각 index와 관련된 shard, 그리고 shard가 할당된 node

You can view the current cluster state with this request:

아래 request로, 현재 cluster state를 볼 수 있다.

GET /_cluster/state

The cluster state exists on every node in the cluster, including client nodes. This is how any node can forward a request directly to the node that holds the requested data—every node knows where every document lives.

cluster state는 클라이언트 node를 포함하여, cluster의 모든 node에 존재한다. 이것은 어떤 node가 request한 데이터를 가지고 있는 node로 request를 직접 전달할 수 있는 방법이다. 모든 node는 모든 document가 어디에 있는지 알고 있다.

Only the master node is allowed to update the cluster state. Imagine that an indexing request introduces a previously unknown field. The node holding the primary shard for the document must forward the new mapping to the master node. The master node incorporates the changes in the cluster state, and publishes a new version to all of the nodes in the cluster.

master node만이 cluster의 state를 업데이트할 수 있다. 색인 request에 기존에는 없었던 field가 포함되어 있다고 가정해 보자. document에 대한 primary shard를 가지고 있는 node는 새로운 mapping을 master node로 반드시 전달해야 한다. master node는 cluster state에 변경사항을 포함시키고, cluster내의 모든 node에 새로운 버전을 배포한다.

Search requests use the cluster state, but they don’t change it. The same applies to document-level CRUD requests unless, of course, they introduce a new field that requires a mapping update. By and large, the cluster state is static and is not a bottleneck.

검색 request는 cluster state를 사용 하지만, 그것을 변경할 수 없다. 물론, mapping 업데이트가 필요한 새로운 field가 있지 않는 한, document 수준의 CURD request에도 동일하게 적용된다. 대체로, cluster state는 정적이고 병목 현상이 없다.

However, remember that this same data structure has to exist in memory on every node, and must be published to every node whenever it is updated. The bigger it is, the longer that process will take.

그러나, 이 동일한 데이터 구조가 모든 node의 메모리에 존재해야 하고, 업데이트될 때마다 모든 node에 배포되어야 한다는 것을 기억하자. 그것이 클수록, 해당 프로세스는 더 오래 걸린다.

The most common problem that we see with the cluster state is the introduction of too many fields. A user might decide to use a separate field for every IP address, or every referer URL. The following example keeps track of the number of times a page has been visited by using a different field name for every unique referer:

cluster state에 대한 가장 일반적인 문제는 너무 많은 field의 도입이다. 사용자가 모든 IP Address나 referer URL을 개별 field로 사용할 것을 결정했다. 아래 예제는, 모든 유일한 referer URL에 대해, 다른 field 이름을 사용하여, 페이지의 방문 횟수를 추적하고 있다.

POST /counters/pageview/home_page/_update
{
  "script": "ctx._source[referer]++",
  "params": {
    "referer": "http://www.foo.com/links?bar=baz"
  }
}

This approach is catastrophically bad! It will result in millions of fields, all of which have to be stored in the cluster state. Every time a new referer is seen, a new field is added to the already bloated cluster state, which then has to be published to every node in the cluster.

이 방법은 아주 좋지 않다. 수백만 개의 field가 나타나는데, 이 모두가 cluster state에 저장되어야 한다. 새로운 referer가 나타날 때마다, 새로운 field가 이미 부풀어 있는 cluster state에 추가되고, cluster내의 모든 node에 배포되어야 한다.

A much better approach is to use nested objects, with one field for the parameter name—referer— and another field for its associated value—count:

더 나은 방법은, 이름 매개변수를 위한 field(referer), 이름과 연관된 값을 위한 또 하나의 field(count)를 가진, nested objects를 사용하는 것이다.

    "counters": [
      { "referer": "http://www.foo.com/links?bar=baz",  "count": 2 },
      { "referer": "http://www.linkbait.com/article_3", "count": 10 },
      ...
    ]

The nested approach may increase the number of documents, but Elasticsearch is built to handle that. The important thing is that it keeps the cluster state small and agile.

nested 방식은 document의 수를 증가하겠지만, Elasticsearch는 그것을 처리할 수 있도록 만들어져 있다. 중요한 점은 그것이 cluster state를 작고 날렵하게 유지한다는 것이다.

Eventually, despite your best intentions, you may find that the number of nodes and indices and mappings that you have is just too much for one cluster. At this stage, it is probably worth dividing the problem into multiple clusters. Thanks to tribe nodes, you can even run searches across multiple clusters, as if they were one big cluster.

결국, 좋은 의도에도 불구하고, 가지고 있는 node, index, mapping의 수는 단일 cluster가 가지기에는 너무 많다는 것을 알 수 있다. 이 시점에서, 문제를 다수의 cluster 사이에 분배하는 것도 의미가 있을 것이다.tribe nodes 덕분에, 다수의 cluster가 하나의 거대한 cluster인 것처럼, 검색하는 것도 가능하다.

'2.X > 6. Modeling Your Data' 카테고리의 다른 글

6-4-09. Retiring Data  (0) 2017.09.23
6-4-10. User-Based Data  (0) 2017.09.23
6-4-11. Shared Index  (0) 2017.09.23
6-4-12. Faking Index per User with Aliases  (0) 2017.09.23
6-4-13. One Big User  (0) 2017.09.23