NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

亚军 watermelon 作品解析

  • 2019-11-25
  • 本文字数:2833 字

    阅读完需:约 9 分钟

亚军watermelon作品解析

今年夏天有幸参加了华为云 TaurusDB 性能挑战赛,并与众多优秀大咖同台竞技、切磋交流,我们感到十分荣幸。我们是一支名叫 watermelon 的三人组团队,均是在读研究生,分别来自浙江大学和上海交通大学,都是明年毕业。初赛和复赛的成绩都是第四名,历史成绩非常的稳定。


这里我们总结了此次参赛的体验,包括对题目重点的解读、我们设计的架构(网络、磁盘、缓存等),以及我们设计的每一个性能优化点。

题目重点解读

  • KV 都是定长的:这样简化了文件和内存的操作和管理。

  • value 远大于 key:把 KV 分离存储,解除索引和数据之间的耦合性。

  • 线程数固定:测评程序固定使用 16 个线程访问数据库。

  • 只需要保证进程意外退出时的持久性:所以可以利用操作系统的缓存对写入方式进行一些优化。

  • 分阶段测评:随机写、随机读、顺序读三个阶段互相没有重叠。

  • 计算节点无状态:我们知道,在这种基于共享存储的计算存储分离架构下,所有持久化数据只能存于存储节点,计算节点只进行逻辑操作。

  • 数据读取的线程和数据写入线程之间没有绑定关系:也就是说每个线程不是只读取自己写入的数据,与初赛不一样,读取线程 id 不一定读的是相同 id 写入的数据。

  • 最后,随机读的随机性在每个时刻只局限在一个 10M 热点分区内,并且热点分区按写入的顺序逆序推进。

核心架构

我们计算节点和存储节点的线程采用一对一的 tcp 连接,因为测评程序是 16 线程,所以连接数就是 16。在存储节点,我们有数据持久化产生的文件,以及读写文件的缓存。


在计算节点,我们维护了读数据的缓存,但是没有写数据的缓存,因为要保证计算节点被 kill 的数据持久性。并且我们的索引也是只在计算节点上维护的,在数据库启动阶段从存储节点把索引数据拉到计算节点。


文件组织形式

  • 首先,按写入线程进行数据的分区,也就是说每个写入线程按顺序写自己的分区文件,这样就避免了多线程写同一个文件冲突的问题。

  • 然后,在每个分区内,将 key 和 value 分离存储为两个文件,一个是 key log,一个是 value log,可以解除索引和数据之间的耦合性。并且我们为了提高写入 value 的速度,对 value 进行了缓存,缓存中凑齐若干个 value 后,再一起进行刷盘。

  • 为了保证缓存不丢失,缓存也使用了 mmap 的形式,因此对应有一个缓存文件。

  • 我们的索引也是按分区进行构建的,每个分区是一个 hash,里面存的是该分区所有数据的索引项,索引项就是一个 key 和 一个 value offset。


性能优化

复赛的优化历程,我们从最开始跑通的 2300s,到最后的 780s,中间经过了好几次架构和方法的改变。


  • 我们的第一个优化是,在启动阶段把 key 从存储节点批量的传到计算节点,这样相比每个 key 都请求一次,批量的方法相当于减少了一半的网络请求,使得时间提升了 300s。

  • 由于我们无法搞定网络传输大数据包的问题,因此我们选择先在存储节点实现顺序读和随机读的缓存,这样减少了存储节点的 io 次数,时间提升了 500s。

  • 我们解决了网络传输的问题,所以先在计算节点进行了顺序读的缓存,成绩提升到 1100s。

  • 我们按存储节点缓存一样的思路,把随机读缓存也拿到了计算节点,这样做之后我们的成绩就已经突破了 800s。

  • 最后我们又优化了一些细节问题,最终成绩是 781s。



围绕读写文件,缓存策略,和网络传输这三个方面,来讲解我们是如何把这个系统的性能提升到极致的。


读写文件

对于 key 这种小数据量的读写模式,采用 mmap 可以利用 page cache 将小数据读写转换为整个内存页的读写,减少了系统调用的时间消耗。value 的大小固定为 4KB,我们知道,写入数据大小要对齐 ssd 的内部 page 时,可以达到最优写入性能。


我们经过线上测试,按 1M 大小顺序写入数据可以达到最大吞吐量。所以,为每一个分区分配一个容量为 1M 的写缓冲区,写满 256 个 value 再将缓存数据一起刷盘,刷盘方式采用 direct io。并且,用 mmap 做缓存,可以保证数据持久性。

缓存策略

随机读的缓存要如何做,才能使得缓存命中率最高呢?


现在的背景是,随机读在每个时刻只局限在一个 10M 热点分区内,并且热点分区按写入的顺序逆序推进。


看图,上面是我们实际存储的文件,按 10M 分为了若干个 block,就是说,我们的缓存只能按 block 对齐进行加载数据。然后,下面是测评的热点分区示意图,我们发现一共 400w 数据,热点分区的边界跟实际数据 10M 边界很可能是不对齐的,并且边界值未知。所以,如果我们只用单个 10M 的缓存,会出现下面这样的问题。


假设当前阶段,测评程序要随机访问 hot1 这个热点分区。第一个位置,我们缓存加载了 block3,然后,访问第二个位置,发现缓存失效,加载了 block2,继续访问第三个位置,缓存又失效了,重现加载回了 block3 ,所以这样就产生了一个缓存来回震荡的问题,极端情况是,我要访问 400 万数据,一共要加载 400 万次大块的缓存,肯定超时,还不如不做缓存。



我们的方案是,采用两个 10M 的 buffer,一前一后,一起往前推进,这样非常完美的避免了缓存来回震荡的问题。并且这个 buffer 不一定是 10M,只要大于 10M 都可以解决这个问题。

网络传输

那么网络的传输效率又应该怎么做才最高呢?


我们发现,写入阶段的网络传输时间主要瓶颈是在周转时间上,也就是说,不是网络有多么拥塞导致网络传输变慢,而是说,value 发过去再回来,本身就需要这么长的时间。


所以我们的优化只能是让存储节点尽可能快的返回 ack 信号,我们的做法是在数据写入存储节点的 mmap 之后,就返回 ack,而不用等待 page cache 刷盘。对于持久性,recover 阶段会把 cache buffer 里面的数据都重新写进 value 文件里。



对于大块数据进行拆分,然后进行多次发送,可以在发送的同时进行流量控制,使吞吐量保持在一个较高的水平。我们的流量控制方法非常简单粗暴,在发送每两个 4k 数据之间,直接加一个延时,延时的方法是让 CPU 自旋一会。并且,存储节点也做了读缓存,把存储节点的读缓存,批量拆分传到计算节点。


整体架构解读

宏观上看,通过这次比赛,我们严格按照计算存储分离的思想来设计了我们的系统架构,对基于共享存储的计算存储分离架构有了一些认知和理解。


首先,我们看计算节点我们的架构只支持一个 RW 节点,进行数据的写入。但是 RO 节点在理论上是可以无限扩展的。并且,由于底层的共享存储,所以主从复制的延迟可以做到非常低。


当 RW 写入一个 kv 数据,对于 RO 节点,它只需要更新已经存在自己 buffer pool 中的数据,而如果发现 RW 写入的数据不在它的 buffer pool 中,那它什么也不做。只有在 RO 节点读取数据时,发现要请求的数据不在自己的 buffer pool 中,它才去下面的存储节点中拉取这个数据到自己的 buffer pool 中。


这样看来,我们在实现高可用功能时候,可以很直接的进行主从切换,RO 节点可以迅速提升为 RW 节点,直接开始对外服务。再看存储节点我们当前只是在单个节点上保证了数据的持久性,而这种 kv 存储可以扩展为分布式架构,采用多副本存储,从而能获得更好的容错性,和更好的读写性能。


所以这样一整套架构,可以解决很多实际的痛点,因此,会成为当今云数据库的一个趋势。



本文转载自 HW 云数据库。


2019-11-25 08:00548

评论

发布
暂无评论
发现更多内容

记一次GC频繁且间隔较长解决实战总结

AI乔治

Java 架构 JVM GC

LiteOS基于Sensorhub的超声波模组移植

华为云开发者联盟

物联网 LiteOS 超声波

语音识别端到端模型解读:FSMN及其变体模型

华为云开发者联盟

大数据 模型 语音识别

为什么short、byte会被提升为int?及基本类型的真实大小

烫烫烫个喵啊

Java JVM

「五大常用算法」一文搞懂分治算法

bigsai

算法 分治算法;

SpringBoot整合Mybatis-Plus 实战之动态SQL,Mybatis最拿得出手的功能之一

比伯

Java 编程 架构 面试 计算机

高速公路二维码定位报警系统搭建解决方案

t13823115967

高速公路二维码定位报警 智慧公安

🤳你要悄悄变优秀,然后惊艳所有人

蚂蚁集团移动开发平台 mPaaS

mPaaS 智能投放 界面改版 产品资讯

小心踩雷,一次Java内存泄漏排查实战

AI乔治

Java 架构 JVM 内存

高并发的核心 - AQS【哪些琐是基于AQS来实现的】

Java架构师迁哥

年轻人,快来看看分布式与集群的区别是什么?

程序员小灰

redis 分布式 后台开发 集群 Linux服务器开发

「linux」Socket缓存是如何影响TCP性能的?

linux大本营

Linux 后台开发 socket 架构师 TCP/IP

区块链落地开发,区块链版权应用搭建

t13823115967

区块链+ 区块链落地开发 区块链版权应用搭建

360OS张焰:AI视觉在教育中的应用

ZEGO即构

淦!终于有人把Java 8和Spring 5完美合体了,业界堪称“神迹”

Java架构追梦

Java spring 架构 面试 springboot

框架设计

raox

极客大学架构师训练营

AOT星辰生态系统APP开发|AOT星辰生态软件开发

系统开发 现成系统

开发技巧 | mPaaS 小程序自定义事件,如何取消注册?

蚂蚁集团移动开发平台 mPaaS

小程序 API mPaaS

专访阿里云 Serverless 负责人:无服务器不会让后端失业

阿里巴巴云原生

Serverless 微服务 云原生 CloudNative 无服务器

架构师训练营 -week11-作业

大刘

极客大学架构师训练营

了不起的 Deno:带你极速获取各大平台今日热榜

华为云开发者联盟

Java 安全 deno

华为云&跟谁学|华为云API入门学习赛·AI人脸识别 未来工程师梦想的起点

DT极客

稳坐开发领域霸主之位,揭秘C语言无可取代的几大原因!

华为云开发者联盟

c rust Go 语言

整天都在讨论使用SpringBoot,可你居然连缓存都不清楚

小Q

Java 缓存 学习 面试 springboot

解锁高速 IT 团队利器:Jira Service Management

Atlassian

DevOps Atlassian Jira ITSM ITIL

AWS IoT Core设计解析

soolaugust

边缘计算 AWS 工业4.0 工业物联网 iiot

深入解读:KubeVela 与 PaaS 有何不同?

阿里巴巴云原生

阿里云 开源 容器 云原生 CloudNative

3本书免费学习数据科学与统计学

计算机与AI

统计学

双非本硕四面百度竟意外成功?看完我的面试经历 网友都称:过于优秀

比伯

Java 编程 架构 面试 计算机

从零开始搭建Kafka+SpringBoot分布式消息系统

小Q

kafka zookeeper 学习 面试 springboot

接口测试之post常见数据提交方式

测试人生路

post 接口测试

亚军watermelon作品解析_语言 & 开发_HW云数据库_InfoQ精选文章