Big Data/HBase&Phoenix

Phoenix Query Server

신씅 2016. 8. 25. 22:27
Phoenix Query Server(PQS) 는 Phoenix 와  HBase 간의 통신을 위한 또 하나의 방법입니다. (기존 : phoenix thick client)

Phoenix 는 버전 4.4 부터 thin 클라이언트와  stand-alone 서버를 도입하였습니다.
PQS 는 클라이언트를 위해  phoenix 커넥션을 관리하는 Java 서버이며, 클라이언트는 최소한의 dependency 만을 가지고 구현된 JDBC driver 입니다.
PQS 는 JDBC(Client)-Http(Server) 구조의 데이터베이스 드라이버를 구현하기 위한 프레임워크인 Avatica 를 기반으로 구현되어있기 때문에 Avatica 와 마찬가지로 두 가지 형태의 전송 메커니즘을 제공합니다.
  • JSON
  • Protocal Buffers(4.7 부터 기본)
그리고, thick 클라이언트 대신 thin 클라이언트를 사용하는 sqlline 이 제공됩니다.

설치

PQS 와 JDBC client 는 Phoenix 배포판에 포함되어 있으며, 추가적인 dependency 는 필요 없습니다.

사용

1. Server 실행
bin/queryserver.py 를 통해 관리할 수 있습니다.

$ bin/queryserver.py [start | stop]

인자가 없이 실행하게 되면, PQS 는 foreground 형태로 실행됩니다.
첫번째 인자로는 PQS 의 데몬을 실행/중지 할 수 있는 start 또는 stop 을 받을 수 있습니다. 이 외에도 추가 인자들은 메인 클래스에 전달 됩니다.
PQS 가 실행 될 때 query server 의 jar 파일과 classpath 에 HBASE_CONF_DIR이 필요합니다.

2. 클라이언트
Phoenix 는 PQS 와 통신하기 위해 두 가지 방법을 제공합니다.
  • JDBC Driver 를 이용하는 방법 : phoenix-<version>-thin-client.jar
  • 스크립트를 이용하는 방법 : bin/sqlline-thin.py

< JDBC 를 통해 접속하는 방법 >

jdbc:phoenix:thin:url=<scheme>://<server-hostname>:<port>[...]

인자내용
<scheme>서버와 통신할 때의 프로토콜. http 만 지원
<server-hostname>query server 가 설치된 호스트 이름
<port>호스트가 리스닝하고 있는 port 번호(기본값 : 8765)

< 스크립트를 이용한 방법 >
bin/sqlline-thin.pybin/sqlline.py 은 동일하게 동작하며 사용방법은 아래와 같습니다.

bin/sqlline-thin.py [[scheme://]host[:port]] [sql_file]

첫 번째 인자(optional)는 접속 URL 이고, 만약 인자를 따로 지정하지 않으면 기본값은 http://localhost:8765 로 설정됩니다.
두 번째 인자(optional)는 sql 명령어 파일입니다.

PQS 모델


위 그림에서 보면, 기존 구조에서는 Application 에 포함되어 있던 Phoenix-thick-client 가 phoenix-client와 abase-client 를 모두 포함하고 있었지만 이를 PQS 가 대신 처리하고 Application 은 phoenix-thin-client 를 통해 PQS 와 단순하게 통신만 수행합니다.

PQS 배포 방안

PQS 는 HTTP 서버의  일반적인 배포 전략을 따라갑니다. PQS 를 HTTP 서버와 마찬가지로 stateless 방식으로 동작합니다.
(PQS 는 내부적으로 state 를 유지하여 PQS 인스턴스 내의 잃어버린 상태를 클라이언트가 자동으로 복구 할 수 있도록 서버와 Java 클라이언트가 구현되어 있습니다.)
PQS 는 stateless 로 설계되었기 때문에 scale-out 이 가능하므로, 일반적인 경우 PQS 를 Region Server 가 실행중인 모든 노드에 설치할 것을 권고합니다.
PQS 가 배포된 node 의 수를 늘리거나 줄이면서 Phoenix 의 처리량을 조절할 수 있습니다.

그러나 모든 region server 의 노드에 PQS 를 배포하는 것에 대해 고려해야 할 것들이 있습니다.
보안상의 문제로 외부 클라이언트에서 클러스터 내의 일부 또는 모든 Region server 들에 접근이 불가능한 경우를 가정해 봅시다. (클라이언트가 클러스터 외부에서 실행중인 경우도 마찬가지 입니다.)
이러한 경우, 외부와 연결하기 위한 특정 노드들이 필요하게 될 것이고, 그 노드들에 배포된 PQS 인스턴스들은 제한적일 것입니다.

HA (고가용성, High Availability)

PQS 의 HA 구성을 위해 HTTP 로그밸런스를 사용할 수 있습니다. 로드 밸런싱을 위해 두 가지 방법이 있으며 각각의 장/단점을 알아보도록 하겠습니다.

1. Generic 로드밸런서
앞서 언급했듯이 Avatica 의 Java 클라이언트는 서버쪽에서 잃어버린 상태를 복구할 수 있기 때문에 PQS 는 일반적인 HTTP 로드 밸런서(HAProxy, Nginx, httpd)를 사용할 수 있습니다.
클라이언트가 지속적으로 특정 서버에만 라우팅 되지 않도록(sticky sessions) 로드 밸런서를 적절히 설정하기를 강력히 권고합니다.
이렇게 해야 클라이언트가 서버사이드에 상태를 재생성 하는데 과도하게 시간을 낭비하는 것을 방지합니다.

< HAProxy 예제 >
HAProxy 설정 파일의 예입니다.(HAProxy 1.5.14 기준)
global
  maxconn 256
defaults
  mode http
  timeout connect 5000ms
  timeout client 60000ms
  timeout server 60000ms
frontend http-in
  bind  *:8888
  default_backend servers
backend servers
  balance source
  server queryserver1 server1:8765 check
  server queryserver2 server2:8765 check
cs

2. 클라이언트-드리븐 라우팅

이 방법은 back-end 의 쿼리 서버들에 대한 라우팅을 제어하는 로드 밸런서에게 식별자를 전달하기 위한  Avatica 의 프로토콜을 구현하여 커스텀 클라이언트를 만드는 방법입니다.
Avatica 의 wire API는 각 메시지 마다 back-end 서버의 주소 속성을 포함하고 있습니다. 클라이언트는 요청 후 라우팅을 결정에 영향을 주기 위해 이 속성을 로드밸런서에게 제공할 수 있습니다.

클라이언트-드리븐 라우팅 방식은 back-end 서버가 죽었을 때 클라이언트가 복구할 수 있는 능력도 요구합니다.

추가 고려사항

로드밸런서, 클라이언트-드리븐 두 가지 방식 모두 동일한 데이터 셋에 대한 쿼리의 결과가 실행할 때마다 정렬이 다를 수 있는 이슈가 있습니다.

Avatica 의 Java 클라이언트를 이용한 방식(로드 밸런서)과 클라이언트-드리븐 라우팅 방식에서 예를 든 커스텀 클라이언트 방식 모두 실행할 때마다 결과셋의 기본적인 정렬을 이용합니다.
PQS 는 쿼리가 수행되는 동안에 발생하는 클라이언트의 자동 복구를 구현하기 위한 결과셋에 대한 offset을 이용하기 때문에, 만약 쿼리 결과에 대한 이 offset이 변경되버린다면, 클라이언트는 row 가 빠지거나 중복된 row를 결과 셋으로 받을 가능성도 있게 됩니다.

이러한 경우를 방지하기 위해 Phoenix 는 hbase-site.xml 의 ‘phoenix.query.force.rowkeyorder’ 속성을 이용하여 정렬을 강제할 수 있습니다.
이 속성을 true 로 설정하면 ORDER BY 절을 쓰지 않더라도 모든 쿼리에 대해 같은 정렬 결과를 보장합니다.