> ## Content Index
> Fetch the complete content index at: https://www.popit.kr/llms.txt
> Use this file to discover other available public pages before exploring further.

# Time Series OLAP - Druid Trouble Shooting(6)
- URL: https://www.popit.kr/time-series-olap-druid-trouble-shooting/
- Published: 2018-06-06T23:00:27.000Z
- Updated: 2018-06-07T01:22:00.000Z
- Author: jerryjung
- Tags: #소프트웨어, Kafka, druid, hadoop, bigdata, #데이터분석, QA, olap

# Druid - 오른손이 하는 일을 왼손이 모르게 하라

길고 길었던 Druid 시리즈 연재의 마무의리...이렇게 오래 걸릴줄은..... 그사이 Druid는 2018년 2월에[ Apache Incubator Project](http://incubator.apache.org/projects/druid.html?ref=popit.kr)가 되었다.

## 실시간 Index Task

**1\.** [**tranquility**](https://github.com/druid-io/tranquility?ref=popit.kr)**를 사용해야 하냐?** [**supervisor(kafka-index-service)**](http://druid.io/docs/latest/development/extensions-core/kafka-ingestion.html?ref=popit.kr)**를 사용해야 하나?**

tranquility의 경우 실시간 데이터에 대한 push 방식, supervisor의 경우 input source로 부터 데이터를 가져오는 pull 방식이다. tranquility의 경우 기존 Steaming Framework에 tranquility library를 추가하여 구현할 수 있다. 즉, Spark/Flink/Storm등의 코드에서 실시간 처리 후 결과 셋을 druid로 sink 할 수 있다. 단, 이 경우 windowPeriod 내에서의 데이터만 처리하기 때문에 late message의 경우는 drop된다. 이미 데이터가 정제된 형태로 kafka에 들어있는 경우라면 ingestion spec을 통해 수집하는 supervisor방식의 수집을 이용하자.

supervisor에서 task개수는 replicas와 taskCount에 의해서 결정되며 workerCapacity = 2\*replias \* taskCount 이다. 만약 taskCount > {numKafkaPartitions} 라면 {numKafkaPartition} tasks가 생기데 된다. taskDuration이 지나면 새로운 task 수행하게 되며 총 task개수는 replicas \* taskCount 이다. supervisor persistence는 metadata database에서 관리하게 된다. 즉, overlord가 재수행 되더라도 직전까지 처리한 index정보는 druid meta database로부터 읽게 된다.

**2\. real-time index task가 안떠요\~**

supervisor에 index json은 submit은 되지만 indexing task가 동작하지 않는 경우, kafka broker 접속이 overlord, middle manager에서 제대로 되는지 확인해 보아야 한다. supervisor는 meta db에 offset을 저장하게 되어있다. metadb에 접속하여 druid\_dataSource테이블을 조회해 보자. 다음과 같이 등록된 offset정보가 없으면 kafka로부터 데이터를 못 읽어온 것이다.  

```
| datasource_name     | 2018-06-05T00:50:49.017Z | {"type":"kafka","partitions":{"topic":"topic_name","partitionOffsetMap":{"0":11076358,"1":15803623,"2":14405618,"3":10999443,"4":15688862,"5":14323317,"6":11039514,"7":16214317,"8":14754624,"9":11340887}}} | 2EDD772548A34F83B7ACFB10FF67DB211A0C7174 |
```

**3\. kafka offset 처음부터 읽고 싶어요**

supervisor의 경우 offset을 reset하는 명령어가 있다. 혹은 ingestion spec에 useEarliestOffset을 줄 수도 있다.

> curl -X POST -H 'Content-Type: application/json' http://{overload-host}:8090/druid/indexer/v1/supervisor/{datasource\_name}/reset

## Performance Tuning

**1\. batch ingestion 에서 hadoop을 ingestion하는 경우 mapreduce에 대한 옵션을 추가해 주어야 한다.**

> "mapreduce.map.java.opts" : "-server -Xmx4096m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps",  
> "mapreduce.reduce.java.opts" : "-server -Xmx4096m -Duser.timezone=UTC -Dfile.encoding=UTF-8 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

**2\. library conflict 문제**

druid extension을 로딩하다보면(필자의 경우 parquet extension추가시 발생) 참조하는 library중에 druid에서 사용하는 library가 conflict나는 경우가 있다. 이 경우에는 jobProperties 에 다음과 같이 설정한다.

> "mapreduce.job.user.classpath.first":"true",

**3\. Component node memory할당**

[http://druid.io/docs/latest/operations/performance-faq.html](http://druid.io/docs/latest/operations/performance-faq.html?ref=popit.kr) 를 참조하길 바란다.

> `druid.processing.buffer.sizeBytes * (druid.processing.numMergeBuffers + druid.processing.numThreads + 1`

위의 공식을 참고한다.

## Druid Q&A

아래 내용은 2016년 "데이터야 놀자"에서 아래 주제로 발표 했을때 나왔던 질문 리스트이다

[https://www.slideshare.net/jerryjung7/data-analytics-with-druid](https://www.slideshare.net/jerryjung7/data-analytics-with-druid?ref=popit.kr)

**Q1\. dimension이나 aggregator개수에 따라 성능 차이가 심하지 않느냐?** A1) dimension의 cardinality가 중요하다. aggregator의 개수에 따라 저장되는 용량이 달라질 수 있다. 질문하신 분은 cardinality가 높은 userId를 예로 들었는데, 그런 경우는 summary할때 count만 세는 방법이 낫다.

**Q2\. L2 cache로 memcached만 지원하냐? In-memory인데 왜 L2 cache를 또 썼냐? redis는 왜 안썼냐** A2) memcached는 특정 쿼리에 대해 multi-broker에 대한 빠른 응답을 위해 썼다. (topN, search query) 현재 redis는 지원하지 않는 것으로 알고있다. 찾아보니 관련 이슈는 있음([https://github.com/druid-io/druid/issues/1927](https://github.com/druid-io/druid/issues/1927?ref=popit.kr)­)

**Q3\. Data Lake를 위해서 elastic search는 고려해보지 않았느냐? 왜 Druid냐?** A3) 다루고자 하는 데이터 속성이 timestamp기반이였고 무엇보다 numeric 데이터에 대한 aggregation이 필요했다. 머신러닝에 input데이터 속성이기에 aggregator에 대한 빠른 응답도 필요했다.

**Q4\. 수집시 중간에 스키마가 바뀌는 경우 이전 세그먼트와 머지할때 conflict가 나지 않냐?** A4) schemaless구조이고 스키마가 바뀌어도 최종 스냅샷을 갖고 있는 구조이다. 추가로 설정하지 않는 한 기존 저장된 segment와 별도의 merge과정은 거치지 않는다.

**Q5\. openTSDB는 고려해 보지 않았느냐?** A5) Hbase에 대한 경험이 없고 관리가 용이하지 않다고 생각한다. sparse한 데이터를 다루기 위해서 고려해 볼수도 있겠지만 druid로 numeric데이터에 대한 빠른 응답은 만족스럽다.

**Q6\. 실시간 수집시 서로 다른 timestamp에 대한 처리는 어떻게 해야 하는가?** A6) tranquility를 통해 pre-processing이 필요하다. 다른 timezone에 대해 시간을 동일하게 convert 하는 작업이 필요하다.

**Q7\. druid를 OLAP/BI로 쓰는가?** A7) OLAP/BI용도로 사용하기도 하고 분석용 데이터를 빠르게 질의하기 위해서도 이용된다.

**Q8\. 별도 UI가 있는가?** A8) 오픈된것은 pivot, superset등이 있다.

**Q9\. elastic search의 경우 jvm에러가 많은데 druid도 그런가?** A9) 내부에서 off-heap을 사용하기 때문에 큰 문제는 없다. 그러나 groupBy Query같은 경우에는 broker에서 결과를 merge하기 때문에 broker의 jvm 메모리를 충분히 할당해 주어야 한다.

## 마치며

이 글의 연재 순서는 다음과 같습니다.

- [Druid 입문(1)](https://www.popit.kr/timeseries-olap-druid-intro-1/) \-> [실시간 Ingestion(2)](https://www.popit.kr/timeseries-olap-druid-realtime-ingestion-2/) \-> [Batch Ingestion(3)](https://www.popit.kr/time-series-olap-druid-batch-ingestion3/) \-> [Segment deep dive(4)](https://www.popit.kr/time-series-olap-druid-segment/) \-> [Glue Architecture(5)](https://www.popit.kr/time-series-olap-druid-glue-architecture/) \-> [Trouble Shooting(6)](https://www.popit.kr/time-series-olap-druid-trouble-shooting/)

**THE END**