第二届华为云数据库挑战赛参赛总结


继上次参加第五届中间件性能挑战赛之后,又一次参加类似的工程类性能比赛,和上次的TSDB题目类似,本次是实现多版本的KV数据库,由于上次的遗憾出局(复赛第七),这次抱着破釜成舟一定要拿奖的的心态,最终结果也算比较满意(复赛第五,Java语言最高分)。

1. 赛题分析

本次比赛需实现一个多版本的KV数据库引擎,写入为随机写,查询功能为MinV~NV Delta的累加结果,同时需支持进程奔溃级的故障恢复。本赛题的读写比例为7:1,需寻找合适的数据组织方式来最小化写入和查询IO的总耗时。

赛题介绍

代码地址

2. 程序结构及存储结构设计
2.1 分区策略

评测程序是30/15个线程并发的发送数据,读写同时在进行。由于key可能在多个线程中出现,为了减少一次查询的IO次数,我们在写入时让相同的key放入一个文件。但是如果全局单文件的话同步消耗不可忽视。因此我们决定基于key进行分区。最多30个线程写,理想情况下,同一时间每个线程写不同的文件,因此将分区定为30。文件Id为hash(key)%30。

由于索引结构中包含了key/version,因此查询时不需要文件中的key/version,所以在一个分区下我们将key/version存入一个文件,delta存一个文件,查询时只需读取delta文件。

2.2 存储结构&索引结构

为了让读取尽量能够在一次IO中完成,我们采用了随机写delta数据的方式,尽量将相同的key紧凑的存储,将文件分为多个page,page的大小固定,如果一个key的delta超过了page的阈值,则顺序开辟一个page存放此key的delta,一个page中只会存放一个key的delta。

key和version采用顺序追加写,同时每个key/version后面追加一个delta的偏移坐标。一个分区Bucket的结构如下图所示:
在这里插入图片描述

Key/ Version文件有两个作用

  1. 故障恢复时构建内存索引。
  2. 当数据总量大至索引无法在内存中存放,可以将key/version文件排序,在内存中构建稀疏索引,采用二分查找来查询所需的key和 version。

由于索引数据可以全放入内存,相比于B+树,Hash索引更具有查询优势。因此采用基本LongObjectHashMap充当索引,即Key -> Versions的映射,Versions保存了key所有的v,以及该key所拥有的pages。

3. 读写实现

写入接口的传入的是一个package,我们对package中相同的key进行压缩合并,同时和可能溢出int,但是不会超过long,因此对合并之后的delta进行压缩。然后逐个遍历不同的key,通过hash(key)取得key的分区Id,根据当前分区的索引判断key是否需要开辟一个page,如果不需要就将delta追加至已存在的page中。否则就开辟新page,并且将新的page位置添加至索引中。key/version/off追加至id.key文件。

key只会在一个文件中,只需找到相应的bucket中的Map索引,遍历Versions中的version即可,因为delta是聚集存储,基本上一次IO即可完成查询。

  • 压缩

    Package中可能有多个相同的key,由于Package内共享一个version,因此可以认为相同的key的delta可以累加为1个。n个key的field占用空间M = (32 + log2n)*64 /8

4. 细节优化
  1. 缓存

    由于写入和读取在引擎侧基本都是内存复用,评测结束还有3.5G左右的内存空闲,但是由于评测程序占用内存的峰值在2G左右,我们采用了通用的1.8G固定大小的缓存。还有些没有采用的定向优化方案,比如二阶段写入时缓存替换、绕过峰值追加缓存等等

  2. JVM gc参数调优

  • 调大年轻代老年代的比例,减少Full GC次数,线上Full gc由于之前1:1 的至少三次降至最多一次

  • 使用-XX:+UseAdaptiveSizePolicy`自适应调节STW和吞吐

    最终gc的耗时在4秒左右

  1. 减少索引的内存占用,复用对象等。
5. Java的不足

赛后我们也在想为什么与cpp的差距,往往Java和cpp的差距在于内存占用,本次比赛中cpp的程序总共占用在1.5G以内,包括测评程序。而Java的内存占用在3G左右,导致的差距就是缓存的容量,cpp可以缓存2.5G,而Java最多可缓存1.8G的数据。

6. 总结

从第一个版本的900秒至最后的85秒,这是一个对赛题认知的过程,比赛就是比赛,当然能做到工程化的扩展是加分项,但是如果连决赛都进不去,那就毫无意义了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值