본문 바로가기

프로젝트 일지

[농산물빅데이터플랫폼] 실시간 데이터 로직 정리

[서비스 목적]

실시간 경매 데이터를 실시간으로 클라이언트에게 시각화 한다.  

시각화시 동일 (품목-등급) 에 대해 1주일 전, 한달 전, 평년 전 평균 가격을 함께 보여준다. 

 

[데이터 설명]

- 공공데이터포털 도매시장별실시간경매속보조회서비스 

- 24시간 기준 약 90MB 크기 

- 데이터 스키마 

{
      "bidtime": "29일 13:28 58",
      "coname": "호남청과",
      "gradename": "특",
      "marketname": "광주서부도매",
      "mclassname": "호박",
      "price": "10200",
      "sanji": "전남 구례군",
      "sclassname": "호박 애호박",
      "tradeamt": "20",
      "unitname": "8kg 파렛트"
}


[요구사항]

- 실시간 데이터는 kafka - ? (저장소) - WAS - 클라이언트(ios) 순으로 처리한다.

- 일일 단위로 쌓인 경매 데이터를 저장소에 저장한다. 

 

[고민하고 있는 부분] 


- kafka topic partition 개수
데이터 특성 상 시계열 순서가 보장되어야 하기 때문에 파티션을 여러 개로 두면 데이터들이 여러 파티션에 분산되기 때문에 컨슈머가 데이터를 저장소로 저장할 때 일일이 timestamp 를 비교해서 저장해야한다. 그렇다고 patition 개수를 한 개로 하자니 처리량이 문제,,, 왜냐면 데이터가 특정 시간대에 확 몰리기 때문에 파티션 하나만 두고 하자니 처리량이 걱정이다. 

 

- 저장소로 redis vs hbase vs RDB?

redis 와 hbase 모두 실시간 데이터 적재에 강한 nosql 이지만

redis는  in-memory 라서 외부 어플리케이션과 빠르게 공유할 수 있다는 장점이 있고

hbase는 hdfs 위에 올려져 나중에 따로 hdfs 에 저장하지 않아도 된다는 장점이 있다. 

일일 데이터 크기가 90mb 라면 hdfs 에 저장하지 않고 RDB 에 저장해도 되지 않을까? 정렬도 인덱싱 조절만 잘하면 RDB 도 문제 없어 보인다. 

 

- redis 저장 시 어떻게 모델링?
품종 별로 table을 만들지, 어떤 데이터 구조 가질지 (hash, list, set ..) , key 값 어떻게 부여할지 등등 모델링에 고민이 많다.
최대한 데이터의 timestamp key 속성을 살려 저장하고 싶다. 저장할 때 key 값을 명시적으로 생성하지 않았기 때문에 WAS에서 데이터를 시간순차적으로 가져갈 수 있게 key 를 생성하고 싶다. 데이터의 timestamp 가 초단위로 제공되지만 데이터 여러개가 초까지 같은 timestamp 를 충분히 가질 수 있기 때문에 오로지 timestamp(bidtime)을 key로 가질 수는 없다. 직관적이게 품목:timestamp:구분자로 하면 되려나? 구분자는 kafka partition offset 으로 하면 고유값이기 때문에 설정하기 편하지만 저장(레디스) 과 수집(kafka) 간 의존성을 버리고 싶다. 좋은 방법을 강구해보고있다.

 

- 왜 HBase 안쓰고 Redis 저장 후 hdfs 에 저장 ?  - 만약 선택지가 Hbase 와 Redis 뿐이라면

수집 데이터의 특성에 맞게 동적으로 컴포넌트를 구성할 수 있는 플랫폼을 만들어보자는게 프로젝트의 목적

실시간 경매 데이터를 이용해 제공하는 서비스는 실시간 경매 현황 시각화, 급등/급락 가능성 여부 파악이다.

하지만 급등/급락 가능성 여부를 파악할 수 있는 로직이 필요한데 아직 가격 예측 서비스도 모델링 중이여서 급등/급락 가능성 여부를 파악하는 로직을 금방 짜기 쉽지 않았다. 또한 급등/급락 가능성은 재배/수확 기간동안 작용하는 기상, 외부환경 등 장기간 요소에 영향을 받기 때문에 실시간으로 경매 데이터 하나하나를 모니터링하기 보다는 일일, 일주일 등 배치성으로 모니터링 하는게 맞다고 판단을 내렸다. 그래서 실시간 데이터를 Redis 에 저장하여 외부어플리케이션(WAS) 이 빠르게 접근하여 실시간으로 클라이언트에 시각화할 수 있게 하고 1일 단위로 레디스에 적재된 데이터를 hdfs 에 저장 후 레디스에서는 데이터를 소멸시키기로 했다.  

 

- redis에 실시간 경매 데이터가 아니라 매일 동일 (품목-등급) 의  1주일 전, 한달 전, 평년 전 평균 가격만 저장한다면?

실시간 데이터는 하루 평균 9만건 정도 들어온다. 들어올 때 마다 데이터의 품목-등급에 대해 1주일 전, 한달 전, 평년 전 평균 가격 을 계산한다면 오버헤드가 심하게 발생할 것이다. 어차피 하루동안 (품목-등급) 의 1주일 전, 한달 전, 평년 전 평균 가격은 변하지 않으므로 미리 계산을 해둔 후 redis 에 저장하여 cache 처럼 사용하는 게 어떨까? 하루가 지나면 저장되어있는 데이터를 소멸시키고 다음 일자에 해당하는 값을 계산하여 미리 저장한다. 

 

- 어떻게 하면 WAS 는 데이터 유실 없이 저장소에서 데이터를 가져올 수 있을까? 

여기서 데이터 유실이란 WAS가 저장소에서 새로 쌓인 데이터를 가져갈 때 동시에 저장소에 새로운 데이터가 저장되는 상황에서 로직을 잘못 짰다가는 새로운 데이터를 무시해버릴 수 있다. WAS(읽기) 와 저장소(쓰기) 간 읽고 쓰는 과정은 atomic 해야 한다. 레디스 서버는 싱글스레드라서 모든 자료구조에 대해 atomic 하다. 

- WAS 는 어떻게 효율적으로 새로 들어온 데이터를 알까? 

물론 이 프로젝트에서 WAS 담당은 따로 있지만 primary key index 로 가져가게끔 ? 

 커서페이징을 찾아보자!