#Redicoke
자체개발한 분산 KeyValue DB인 REDICOKE에 대해 소개하고, 기존 저장 구조에 성능 한계와 개선되는 구조에 대해 공유합니다. Key-Value 데이터에 NVMe 저장에 대한 최적화 고민과 문제를 어떻게 풀었는지 자세히 설명 할 예정입니다.
발표자 : leon.nam 카카오 분산기술셀에서 다양한 분산 플랫폼을 개발하는 레온입니다.
남현우 Leon.nam카카오Copyright 2022. Kakao Corp. All rights reserved. Redistribution or public display is not permitted without written permission from Kakao.NVMe 기반 KV 스토리지 성능 개선if(kakao)2022분산 DB Redicoke 소개
View Slide
REDICOKE?성능 이슈새로운 구조개선 결과
REDIS + COKE = REDICOKECOKEAPIObject StorageDataIndex- COnsistent KEy-value storage- 자체개발한 NVMe 기반 분산 Key-Value DB(3 COPY)- 카카오에 object storage에서 내부 index DB로 개발- Redis protocol 사용- 노드 수에 비례해 스케일 아웃 가능- 일관성, 내구성, 고가용성 및 저지연성에 중점
서비스 운영- 하나의 클러스터로 운영- 사용자는 DB 관리가 불필요- 무제한에 가까운 공간 제공- 낮은 latency (평균 1ms 이하)REDICOKE
클러스터 구성- Key hash기반 샤딩- Range scan은 불필요하고, 밸런싱이 중요- 약 4000개 이상의 샤드 파티션으로 운영중- 하나의 노드에 80개 정도의 청크 할당HashFunc(Key “ABCD”)=> 400
RedisIn-memory DBRedicokeNVMe 기반 분산 KV DB
기존 스토리지 엔진 구조C 40 C CC C 25 CC 10 C CC C C 20HashfileA B C DDataoffset10 20 25 45- Write보다는 Random Read에 유리한 구조- Hash index, data 모두 disk 로 관리- BufferedIO를 통한 커널 캐시 사용- Disk기반 hash 구성으로 write amplification이 큰 구조(최대 8byte->4K)
- Write 트래픽이 높지 않을 경우 안정적이지만, 특정 임계점을 넘으면 tail latency 가 크게 증가- 커널에 page cache 이슈스토리지 엔진 개선이 필요0K25K50K30s 90s 150s 210s0800160030s 90s 160s 210sWrite TPS Tail Latency(ms)
RocksDB 스토리지 엔진 테스트- LSMT 구조로 SSD에 최적화된 KV DB- Compaction 될 때 성능 편차- Random Read에서 성능 편차- Range scan 기능은 불필요- 하나의 청크는 최대 128G 로 사용MEM TABLEFlushRocksDB 구조
015003000hard disk sata ssd NVMeNVMe 성능012hard disk sata ssd NVMeWrite throughput(MB) Seek time(ms)
최대 Write TPS는?Write throughput(3G) / Data size(1K) = 300M TPS
필요한 부분KV DATAIndex?- NVMe에 최적화된 write 패턴이 필요- 커널 page cache 문제- Index는 가능한 메모리 활용이 필요- 디스크 사이즈 대비 메모리가 부족한 상태
Direct IO 사용DirectIOPagecacheFILEBufferedIO- 모든 IO는 DirectIO 로 처리- Page cache를 사용 안함- Write amplification을 최소화- File write는 append만 허용
영역 분리- LEVEL1만 가지는 단순한 LSMT와 비슷한 구조- 각 영역은 INDEX + KV DATA 영역으로 구성- Request를 받는 Mutable KV와Immutable KV 로 구분- Merge될때 리소스 사용을 최소한으로 처리MUTABLE KVAppendCompactionIMMUTABLE KVRequest
MUTABLE INDEXslot(2^24)Height + Hash + Offset- 메모리로만 구성된 hash index- 2^24 slot으로 hash 상위 3byte 를 표시- 키 하나당 10byte 사용(height(1) + hash(5) + offset(4))
IMMUTABLE INDEX- 메모리에 index를 모두 올릴 수 없기 때문에 index를 분리- Sparse index는 memory,file index는 disk에 구성- Hash로 정렬한 index로 구성- 데이터를 검색할때 반드시 disk read가 필요SparseIndexFileIndexKV DataOffset OffsetMemory
Sparse Index11020138910121517202225- Page align(4K) 단위로 sparse index를 구성- Interpolation search로 빠르게 검색 가능- 1억개의 키를 저장할때File index : 1억 * (hash(8B) + offset(4B)) = 1.2GSparse index : 1.2G / (4K / 12B) = 3.6M
Bloomfilter?SparseIndexBloomFilter?IndexKV Data- Index앞에 bloomfilter 사용을 고민- Bloomfilter를 통해 존재하지 않는 데이터에 대한 빠른 검색이 가능- 데이터 구성이 커져도 index검색 횟수는 고정이기 때문에 큰 성능향상이 없음- False positive로 tail latency 편차가 증가
HashIndexSparseIndexMutable KV Immutable KVKV Data KV DataFileIndexFILEMemory
0K90K180K1h 2h 3h 4h 6h 7h 8h개선 버전 기존 버전개선 결과060012001h 2h 3h 4h 6h 7h 8h개선 버전 기존 버전Write TPS Tail Latency(ms)
- 대규모 온라인 마이그레이션 진행중- 청크 단위로 스케줄링하여 진행- 내부 Management tool을 통해 자동화청크 마이그레이션Request마이그레이션
E.O.D