paust-team / paust-db

GNU General Public License v3.0
6 stars 5 forks source link

Time Range Query Error #134

Closed elon0823 closed 5 years ago

elon0823 commented 5 years ago

현재 Time range 상에서 range query문제가 있습니다.

가장먼저 문제분석이필요하고요

다음 일환으로 test case 를 자동으로 테스트하고 결과를 보고할수있는 스크립트를 만들어서 테스트를 돌려야할것같습니다.

elon0823 commented 5 years ago

json marshal 관련 문제인것같은데 해당 부분을 걷어내는 방안을 검토해보도록 하죠

dragon0170 commented 5 years ago

확인해 본 결과 json marshal 문제 맞네요. 현재 paust-db는 아래와 같은 KeyObj struct를 json marshal한 byte array를 rowKey로 사용하고 있습니다.

type KeyObj struct {
    Timestamp []byte `json:"timestamp"`
    Salt      []byte `json:"salt"`
}

Timestamp와 Salt 자체는 BigEndian 인코딩을 통해서 각각 uint64, uint16이 고정된 길이의 byte array로 들어가게됩니다. 여기까지는 sorting을 하는 데 문제가 없지만 KeyObj를 json marshal할 때 문제가 발생합니다. json의 경우 byte를 직접적으로 처리할 수 없어서 보통 base64 encoding을 거친 string으로 다루게 됩니다. go의 json marshal도 마찬가지로 byte slice를 base64 encoding하여 json object 내에 string value로 집어넣습니다.

따라서 json marshal을 거친 실제로 데이터를 저장할 때 사용하는 rowKey는 {"timestamp":"FXAiwIQ3f5g=","salt":"axk="}와 같은 형태가 됩니다. 그래서 byte 각각을 비교해 sorting 했던 기존 의도와는 다르게 encoding된 string의 character 각각이 비교되어 sorting되어 있어서 발생하는 문제입니다.

dragon0170 commented 5 years ago

그래서 rowKey 구조를 현재의 json marshal을 하는 방식이 아니라 fixed size의 byte array를 직접 설계해서 사용하는 것이 좋아보입니다.

현재 KeyObj struct를 반영해서

rowKey(10byte) = timestamp(8byte, uint64 big endian encoding) + salt(2byte, uint16 big endian encoding)

으로 구성해서 hotfix-v0.1.1에 반영하면 어떨까요?

elon0823 commented 5 years ago

Keyobj를 제외하고 timestamp, salt로 부터 rowKey 를 생성해주는 메소드를 하나 만들어서 서버에서도 사용하면 되겠네요