paust-team / paust-db

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

Test adding count value to rowkey for preventing duplication #156

Closed dragon0170 closed 5 years ago

dragon0170 commented 5 years ago

Reference https://github.com/paust-team/paust-db/issues/144#issuecomment-476141728

andrew, elon과 논의해본 결과, rocksdb 내에 timestamp마다 counter를 두는 것은 저장공간도 차지하고 데이터 put 시 효율적이지도 않은 것 같습니다. 중복 방지를 위해서라면 굳이 억지로 counter를 rocksdb에 도입하는 것이 아니라 ABCI server 상에서 데이터를 저장할 때 count value를 추가해서 rowkey를 구성하는 것이 더 좋아보입니다. 그래서 매 블록마다 메모리 상의 counter를 ABCI server에서 범용적으로 사용하는 방식을 테스트해볼 예정입니다. 즉, 특정 block에 대한 ABCI cycle을 돌 때 시작 시 counter value를 0으로 초기화하고 deliverTx 실행 시마다 counter value를 1씩 증가시키면서 rowkey = timestamp + counter value 구조로 데이터를 저장하는 것을 의미합니다.

위 댓글에서 언급한 중복 방지를 위한 rowkey 구성방식이 제대로 동작하는지 테스트 해보려고 합니다.

dragon0170 commented 5 years ago

rowkey(10byte) = timestamp(uint64, 8byte) + counter value(uint16, 2byte) 위와 같이 rowkey를 변경해서 client와 master application을 수정해 테스트하여보았습니다.

rowkey의 구조는 기존과 같게 길이는 10byte로 동일하지만 rowkey를 생성하는 곳이 client에서 master application으로 변경되었습니다. Master application에서는 BeginBlock function에서 counter를 0으로 초기화하고 DeliverTx function에서 데이터를 rocksdb의 batch에 추가할 때마다 counter를 1씩 증가시키도록 하였습니다. 데이터가 실제로 저장되는 rowkey는 DeliverTx function에서 생성되며 client에서 받은 데이터의 timestamp와 counter value를 concatenate해서 만듭니다.

위의 rowkey 구조와 생성방식을 사용하려면 한가지 문제가 있습니다. 현재 types.go에 있는 MetaDataObj, RealDataObj struct는 데이터를 put, query, fetch할 때 모두 동일한 데이터 형식으로 서버와 클라이언트가 통신하기 위해서 만든 struct입니다. 하지만 rowkey가 생성되는 곳이 master application으로 바뀌게 되면 Client가 put을 할 때는 MetaDataObj, RealDataObj의 rowkey를 정할 수 없습니다. rowkey 구성을 위해서는 timestamp와 counter value가 모두 필요하기 때문입니다.

type MetaDataObj struct {
    RowKey    []byte `json:"rowKey"`
    OwnerId   string `json:"ownerId"`
    Qualifier []byte `json:"qualifier"`
}

type RealDataObj struct {
    RowKey []byte `json:"rowKey"`
    Data   []byte `json:"data"`
}

우선은 현재 interface를 그대로 유지하면서 테스트를 진행했습니다. client에서 put할 때의 MetaDataObj, RealDataObj의 RowKey field는 counter value를 모두 0으로 두고 생성한 rowkey를 담아서 paust-db에 전달하였습니다. Master Application에서는 DeliverTx가 실행될 때 RowKey의 counter value 부분을 실제 counter value로 바꿔치면서 데이터를 저장했습니다.

테스트 결과 하나의 tendermint block이 쌓일 때 동일한 timestamp에 대해서도 counter value가 1씩 증가하면서 rowkey가 생성되고 overwrite없이 데이터가 저장되었습니다. query, fetch도 정상 동작하는 것을 확인했습니다.

테스트는 잘 되지만 앞으로 RowKey 생성 방식이 바뀐다면 server와 client간의 통신을 위한 struct 구조는 이 테스트에서 사용한 것처럼 사용하는 방식에 있어서 변화를 주거나 구조 자체의 변경이 필요해 보입니다. rowkey를 Master Application에서 생성하게 된다면 timestamp도 client에서 받는 것이 아닌 Master Application에서 생성해서 rowkey를 구성하는 방식도 고려해봐야 할 것 같습니다. 지금 간단히 생각나는 것으로는

elon0823 commented 5 years ago

해당 내용은 row key 에 counter 기능을 구현해서 중복저장을 막기 위한 test 였습니다. 나중에 paust-db 로 네트워크를 구성할 때, 똑같은 데이터에 대해 (timestamp, ownerid, meta, real) 중복저장을 허용할 것인지, overwrite 할 것인지에 대한 정책중에 중복저장을 허용하기 위한 방법을 테스트 한 것입니다. 데이터 구조는 앞으로 meta, real data object 가 query interface 를 설계하는 부분을 만들면서 변경되게 될탠데 그것과 별개로 counter 를 이용해서 중복방지를 할 수 있다는 걸 확인했으니 issues 는 여기서 닫을께요