쿠팡과 같은 쇼핑몰의 주 데이터 저장소를 HBase 로 한다고 했을 때, 어떤 데이터 모델과 key 설계를 해야할지 고민해보자.
쿠팡의 댓글 기능을 설계해본다.
댓글기능을 중심으로 요구사항을 작성해 보았다.
Order
: 주문을 해야 프로덕트의 코멘트가 남으니까 주문정보가 있어야 함.
Product
: content 는 이미지도 올라갈 수 있고 여러 가지 올라갈 수 있으니까 byteArray로 해놓았음. 그리고 생성된시간, 업데이트 된 시간 기록할 수 있도록 해놓았음Comment
: 코멘트 자체에는 id를 두지 않았음. product id와 order id를 조합하면 유니크한 키가 됨. 요즘은 수정됨. 이라고 뜨니까 isEdited 등 class Comment {
String orderld;
String productid;
String userld;
String content;
long timestamp;
boolean isEdited;
}
class Order {
String id;
String userId;
}
class User {
String id;
String name;
String nickname;
}
class Product {
String id;
String sellerId;
byte[] content;
long createdAt;
long updatedAt;
}
class Seller {
String id;
String name;
}
Comment --> Order : dependent
Order --> User : dependent
Comment --> User : dependent
Comment --> Product : dependent
Product --> Seller : dependent
id
id
id
id
orderId:productId
userId:reverseTimestampOfComment
10개 조회해서 10개의 코멘트 row key얻은 다음에 그 rowkey로 코멘트들을 다시 조회하는 식이 될 것
productId:c:reverseTimestampOfComment:reverseLengthOfContentInComment
RowKey에 가장 먼저 productId가 들어 가야 pid별로 모이고, 전체가 spot하게 분산이 될 것임. 잘 팔리는 상품은 리뷰를 동시에 여러 사람이 남길 수도 있으니 timestamp가 같은 서로 다른 리뷰들이 있을 수 있음. reverseLengthOfContentInComment를 콘텐츠 length를 길게 한 애들이 같은 시간에서는 더 앞에 올 수 있도록 위치시킴.
productId:r:number
결국 프로덕트에 남겨진 코멘트들 중에 좋은 코멘트들 10개씩 남긴다고 했으니 index table용도로 남기고, 이거를 어떤 걸 위치시킬지 계산하는 건 다른 시스템을 만들 거고, Overwrite 한다고 생각을 했다. 그래서 pid가 앞에 옴.
product-comment 와 RowKey의 길이 수가 다르다.
Value: RowKey of comment로 한 이유
우리는 Index table 방식을 채택했다. 코멘트 데이터는 양이 매우 많기 때문에, 이를 value로 직접 저장하면 스토리지를 많이 차지하는 단점이 있다. 또한 같은 데이터를 여러 곳에 저장할 경우 RDB처럼 트랜잭션으로 연결할 수 없으므로, 원본이 변경될 때마다 모든 저장소를 갱신해야 한다. 하지만 HBase는 이러한 다중 업데이트를 보장하기 어렵고, 이를 직접 구현하려면 시스템 복잡도가 높아져 버그 발생 가능성이 크다.
따라서 우리는 comment의 RowKey만 index table에 저장하기로 했다. RowKey는 일반적으로 변하지 않으므로, index table은 한 번 저장된 후 immutable하게 유지된다.
물론 이 방식은 index table 조회 후 원본 코멘트를 다시 조회해야 하므로 응답 속도가 다소 느려진다. 그러나 채팅 서비스처럼 밀리초 단위의 빠른 응답이 요구되는 것이 아니라, 쇼핑몰 코멘트 조회처럼 100~200ms 정도의 지연이 허용 가능한 서비스라면 충분히 감수할 수 있다고 판단했다. 결국, 속도보다 데이터 일관성과 관리 용이성을 우선시하여 이런 설계를 적용했다.
이번 Coupang 시나리오의 구현은 위 KakaoTalk 을 참고해서 직접 구현해보자.
가능하다면 API 까지 디자인 해보면 좋다.