Inertia

dynamodb

RDBMS에 비해 nosql이 가지는 이점은

  • denormalized되지 않았다는 것. -> join이 없으니 쿼리가 간단해 짐.
  • ACID 제약사항) 을 가지지 않는 것. -> locking이 필요 없으니 병렬화 할 수 있고, 성능 이점을 가짐.

nosql의 대표 주자인 dynamo 디자인할때 생각해야 할 사항들을 정리해 보자.

dynamo의 primary key = partition key + sort key 임.

design consideraton

  1. RDB와는 다르게 컬럼명이 스토리지에 중복해서 저장되므로 컬럼명이 짧을 수록 스토리지 비용을 아낄 수 있다.
  2. LSI(local secondary index)의 경우는 하나의 partition key에 대해서 10G의 사이즈 제한이 있다. 그 이유는 10G가 넘어가게 되면 partitionkey + sort key를 기반으로 해쉬해서 한번더 파티션을 나누기 때문인데, 이때의 인덱스는 더이상 로컬일 수가 없기 때문이다. 이때는 GSI(global secondary index)를 사용해야 한다. GSI는 GSI를 위한 별도의 테이블이 생성되는 것과 같다.

partition key

dynamo는 물리적 파티션을 나눠서 관리하기 때문에 이 파트션을 나눌 키를 정의해야 한다. user id 같은것. date(2018-10-10)같은 것은 좋지 않다. 왜나하면 그 날의 데이터는 모두 하나의 파티션으로 몰릴 것이기 때문에 핫 파티션 문제가 생김.

sort key

파티션 키 하위를 소트할때 사용하는 키. sort key를 사용해서 범위로 쿼리 할 수 있음. 또한 sort key로 정렬이 되므로 순서를 줄 수 있음

LSI(local secondary index)

특정 컬럼명으로 빨리 검색을 하고 싶거나 소트 순서를 주고 싶다면 LSI를 걸 수 있다. KEYS_ONLY로 키만 걸수도 있고, 특정 컬럼을 카피해서 가지고 있을 수도 있다. 현재로서는 10G의 크기 제한이 있기 때문에 설계할때 고려를 해야한다. 크기제한을 벗어나고 싶다면 GSI(Global secondary index)를 걸 수 있다.

ttl

table의 ttl을 enable하고 ttl property를 설정해주면 특정시간이 지난 row를 dynamo가 자동으로 삭제해주는 기능이 있다.

나의 경우 이 기능을 푸쉬를 보낼때 사용했다. ttl에 의해 row가 삭제되면 그 이벤트를 dynamo stream으로 보내게 되고, 그것을 lambda로 받아서 push 처리를 하게 하였다.

이때 한가지 문제가 ttl에 의해서 삭제가 되었는지, 사용자의 DELETE 요청에 의해서 지워졌는지를 어떻게 판단할 수 있는가 였는데 찾아보니 userIdentity 속석에 의해서 판단이 가능했다.

즉, 아래처럼 판단이 가능하겠다.

1
2
3
4
5
6
7
8
9
10
11
exports.handle = (event, context, callback) => {
console.log('Stream record v1: ', JSON.stringify(event, null, 2));

event.Records.forEach((record) => {
if (record.eventName === 'REMOVE' &&
record.userIdentity // only ttl triggered item has userIdentity property
) {
// send push
}
}
}

이 속성을 기반으로 ttl에 의한 이벤트이면 푸쉬를 보내고, 사용자의 삭제 요청에 의한 것이면 푸쉬를 보내지 않게 판단할 수 있게 되었음.