오랜 시간 동안 http를 썼지만 정식 용어를 모를 때가 많다.


HTTP는 HTTP 응답에서 Last-Modified라는 이름의 헤더를 제공한다. 


Last-Modified 헤더는 데이터가 마지막으로 변경된 시기를 의미한다. Last-Modified 헤더는 피드의 updated 필드의 기능을 대신한다.



클라이언트는 HTTP 헤더의 값을 저장한다. 

그리고 HTTP GET 요청에 클라이언트는 GET 요청과 함께 If-Modified-Since 헤더에 읽기 값을 보낸다. 데이터가 변경되었다면 서버는 HTTP 304(변경 되지 않음) 상태 코드를 응답한다. 그리고 상태 코드를 제외하고 어떠한 데이터를 전송하지 않는다.


데이터가 변경되었는지 쉽게 결정할 수 있다. 예를 들어 데이터베이스의 마지막 변경 시간을 결정하는 코드를 구현할 수 있다. 이는 모든 데이터를 Atom 표현으로 변환하는 것보다 훨씬 효율적이다.


데이터가 실제로 변경되었다면 요청에 대해 200(OK)으로 정상적으로 응답된다. 또한 클라이언트가 HTTP 캐싱을 다시 사용할 수 있도록 Last-Modified 헤더에 새로운 값이 전송된다.


지정된 If-Modified-Since 헤더를 포함한 요청을 데이터베이스에서는 마지막 변경 시간과 비교하고 결정하는 데 사용된다. 데이터가 변경되지 않으면 HTTP 304 상태 코드를 리턴한다. 이 경우 HTTP 요청에 응답하는 데 하나의 데이터베이스 쿼리만 필요하다.



이런 방식을 Conditional Get (조건부 Get)라 한다.

'영어앤영문권' 카테고리의 다른 글

Stalemate- 교착 상태  (0) 2019.08.24
snowflask system(눈송이 시스템)  (0) 2019.08.16
self-contained system (SCS) 번역  (0) 2018.08.28
authz, authn  (0) 2018.08.10
BYOD  (0) 2018.07.28
Posted by '김용환'
,

OpenTsdb 분석

scribbling 2018. 8. 31. 12:50





opentsdb 소스(https://github.com/OpenTSDB/opentsdb )를 살펴보니.. 큰 특징은 다음과 같다.


<내용>

1. grafana를 지원한다. (사실 이것 때문에 쓰는 것임)


2. hbase 쿼리 튜닝은 되어 있지 않다(start, end로 해서 읽어옴, 대용량 데이터에 엄청 취약)


3. gpgl 이다. (소스를 건들 수 없다)

    OpenTSDB is free software and is available under both LGPLv2.1+ and GPLv3+.


4. 성능을 위해 async hbase(Defered)를 사용했다. (그러나 성능 이슈는 앱의 쓰레드 부분이 아니라 쿼리 부분에서 발생한다)


5. 야후 개발자 한명이 혼자 다 개발한다. 따라서 확장성에서 취약하다. 아저씨 코드이다. 


6. 현재 3.0 개발중(google bigtable도 깔끔하게 지원될 것 같다)


7. 데이터가 많아지면 트래픽에 굉장히 취약하다. 대용량 환경에서는 druid가 답이다. 


7. 2.3까지 pre-aggregation, google big table/cassandra 지원은 완벽하지 않다. hbase 빼고는 답이 없다. (대용량에 취약하다.)


8. druid vs opentsdb 

https://community.hortonworks.com/questions/89810/druid-vs-opentsdb-for-tick-data.html

https://www.popit.kr/time-series-olap-druid-%EC%9E%85%EB%AC%B8/ (람다 아키텍처 지원)

https://groups.google.com/forum/#!topic/druid-development/bPJbWO-g4aw

https://java.libhunt.com/compare-opentsdb-vs-druid







<세부 내용>

1. 원래 opentsdb의 의도는 한 대의 host, network를 모니터링을 위해 만들어졌다. kafka* 이런식의 모아보기 용은 아니다.


2. 키 구성

row key : metric_uid + timestamp + tagk1 + tagk2 + <tagkN> + <tagvN>

timestamp 

tagk1=tagv1

tagk2=tagv2



3. 키 검색 순서

time range -> metric -> tags

따라서 동일한 그룹핑 단어가 많아지면 성능은 좋지 않다.(data. agg. 으로 시작하는 단어)



4. opentsdb 2.0부터 4개의 테이블이 생성된다.

data

uid

tree

metadata 테이블 : name <--> id 매핑


5. tagk 길이 제한

rowkey에 저장해야 하기에 5개 태그 미만으로 저장해야 한다.



6. opentsdb가 api에 예민(host 정보 없으면 에러 출력), 성능이 약해서 opentsdb 앞단에 opentsdb compatible api g/w를 사용해야 잘 감싸는 서버가 필요하다. 따라서 custom, 모아보기 기능도 쉽게 진행할 수 있다. 




<opentsb를 활용한 프로젝트>


https://github.com/turn/splicer : 여러 opentsdb 클러스터와 redis를 두어 모니터링(더이상 운영 안됨)


https://github.com/facebookarchive/beringei : facebook에서는 인메모리 TSDB용으로 개발(더이상 운영 안됨)





<참고>

Opentsdb 좋은 공부 자료

http://tsunanet.net/~tsuna/hbasecon-2014-opentsdb-2.0.pdf

http://opentsdb.net/misc/opentsdb-oscon.pdf

http://Marp의 opentsdb 튜닝가이드 https://mapr.com/blog/hbase-key-design-opentsdb/

http://opentsdb.net/docs/build/html/user_guide/backends/bigtable.html







다음은 opentsdb를 분석하며 대충 그려놓은 그림이다. 자료가 없어서 이를 참조하면 좋을 것 같다. 













Posted by '김용환'
,




카프라 토픽에 저장된 데이터가 너무 많아지면 lag의 값은 점점 커진다.


lag이 커지면 처리되야 할 양은 많아지고, 결국 카프카가 저장하는 토픽 저장소의 한계도 넘어서게 된다.


따라서, 이럴 때 간단히 해결할 수 있는 방법은 파티션을 늘리는 것이다. 


topic에 할당한 파티션(partion)의 개수가 5이면 10개로 늘리면, 조금씩 lag이 줄어든다..

10개이면 20개로 늘리면 조금씩 lag이 줄어든다.



consumer group의 병렬 처리 정도는 consume하는 파티션의 수에 의해 제한된다. 따라서 일반적으로 파티션이 많아지면 당연히 처리량, throghput이 높아진다.




그렇다면 파티션을 늘리는 것이 답일까??

먼가 kafka에 영향을 주지 않을까 고민하던데 차에. 아래 문서를 보게 되었다.





http://www.confluent.io/blog/how-to-choose-the-number-of-topicspartitions-in-a-kafka-cluster/




요점 - 발 번역



1. 파티션 개수가 많아지면 오픈 파일 핸들(open file handle)을 더 필요로 한다.


각 파티션은 브로커의 파일 시스템의 디렉토리에 매핑된다. 해당 디렉토리에는 로그 세그먼트 당 두 개의 파일 (인덱스 용, 실제 데이터 용)이 존재한다. 각 브로커는 모든 로그 세그먼트의 인덱스와 데이터 파일 모두에 대한 파일 핸들을 연다. 따라서 파티션이 많을수록 기본 운영 체제에서 열린 파일 핸들 제한을 구성한다. 따라서 카프카 서버 운영자 입장에서는 open file handle(fd) 개수 더 커지지 않도록 운영할 필요가 있다.



2. 파티션 개수가 많아지면 비-가용성이 증가된다.


장애 상황에 이슈가 발생할 수 있다. 브로커가 불명확하게 종료될 비-가용성은 파티션 수에 비례한다. 브로커에 총 2000개의 파티션이 있고 각 파티션에 2 개의 복제본이 있다고 가정하면 해당 브로커는 약 1000개의 파티션을 위한 리더가 될 것이다.  해당 브로커가 불완전히 실패하면 1000개의 파티션을 모두 동시에 사용할 수 없게 된다. 단일 파티션에 대한 새로운 리더를 선출하는 데 5ms가 걸린다고 가정하면 1000개의 모든 파티션에 대한 새로운 리더를 뽑는는 데 최대 5 초가 소요된다. 일부 파티션의 경우 비-가용성은 5초+실패 감지 시간이 될 것이다. 


불행한 경우, 실패한 브로커가 컨트롤러라면 심각하다. 페일 오버는 자동으로 발생하지만 새 컨트롤러는 초기화하는 동안 ZooKeeper에서 모든 파티션의 일부 메타 데이터를 읽어야 한다. 예를 들어 카프카 클러스터에 10,000 개의 파티이 있고 ZooKeeper에서 메타 데이터를 초기화하는 데 파티션 당 2ms가 걸리면 사용 불가능한 창에 20초가 더 걸릴 수 있다.


따라서 최악의 경우를 피하려면 브로커 당 파티션 수를 2개에서 4000개 밑으로 제한하고 클러스터의 총 파티션 수를 수만 개로 제한하는 것이 좋다.



3. 파티션 개수가 많아지면 end-to-end 대기 시간이 증가된다.


카프카의 end-to-end 대기 시간은 producer가 메시지를 퍼블리싱하고 consumer가 메시지를 읽을 때까지의 시간으로 정의된다. 메시지 커밋 시간은 end-to-end 대기 시간의 상당 부분을 차지한다. default로 카프카 브로커는 두 개의 브로커 간에 복제본을 공유하는 모든 파티션에 대해 단일 스레드를 사용하여 다른 브로커의 데이터를 복제한다. 한 브로커에서 다른 브로커로 1000개의 파티션을 복제하면 약 20ms의 대기 시간이 추가될 수 있다. 즉 end-to-end 대기 시간이 최소 20ms임을 의미한다. 


end-to-end 대기 시간을 줄이려면 브로커 당 파티션 수를 100 x 카프카 클러스터의 브로커 수 x replica factor로 제한하는 것이 좋다. 



4. 파티션 개수가 많아지면 producer/consumer 클라이언트에서 많은 메모리를 필요로 한다.

0.8.2 릴리스에서 producoer는 파티션 당 메시지를 버퍼한다. 충분한 데이터가 축적되거나 충분한 시간이 경과하면 축적 된 메시지가 버퍼에서 제거되고 브로커로 전송된다.


파티션 수를 늘리면 producer의 더 많은 파티션에 메시지가 저장하게 된다. 사용된 메모리 총량이 설정된 메모리 제한을 초과할 수 있다. 이 경우 producer는 새로운 메시지를 차단하거나 삭제해야 하며 어느 쪽도 이상적이지 않다. 


따라서 producer가 생성하는 파티션 당 최소 수십 KB를 할당하도록 하고 파티션 수가 크게 늘어날 경우 총 메모리 양을 조정해야 한다.


비슷한 문제가 consumer에도 존재한다. consumer는 파티션 당 메시지 덩어리를 가져온다. 파티션이 클수록 더 많은 메모리가 필요하다.

Posted by '김용환'
,