报名参加CloudWeGo黑客松,奖金直推双丰收! 了解详情
写点什么

150 倍加速机械盘,UCloud 云主机 IO 加速技术揭秘

  • 2019-11-11
  • 本文字数:4685 字

    阅读完需:约 15 分钟

150倍加速机械盘,UCloud云主机IO加速技术揭秘

现如今 CPU 的计算能力和磁盘的访问延迟之间的差距逐渐扩大,使得用户云主机的磁盘 IO 经常成为严重的性能瓶颈,云计算环境下更加明显。针对机械盘 IO 性能低下的问题,我们通过自研的云主机 IO 加速方案,使 4K 随机写的最高性能由原来的 300 IOPS 提升至 4.5W IOPS,提高了 150 倍,即用机械盘的成本获得了 SSD 的性能。13 年上线至今,该方案已历经五年的运营实践,并成功应用于全网 93%的标准型云主机,覆盖 12.7 万台实例,总容量达 26PB。

1 为什么需要 IO 加速

传统的机械磁盘在寻址时需要移动磁头到目标位置,移动磁头的操作是机械磁盘性能低下的主要原因,虽然各种系统软件或者 IO 调度器都致力于减少磁头的移动来提高性能,但大部分场景下只是改善效果。一般,一块 SATA 机械磁盘只有 300 左右的 4K 随机 IOPS,对于大多数云主机来说,300 的随机 IOPS 哪怕独享也是不够的,更何况在云计算的场景中,一台物理宿主机上会有多台云主机。因此,必须要有其他的方法来大幅提升 IO 性能。


早期 SSD 价格昂贵,采用 SSD 必然会带来用户使用成本的提升。于是,我们开始思考能否从技术角度来解决这个问题,通过对磁盘性能特性的分析,我们开始研发第一代 IO 加速方案。即使今天 SSD 越来越普及,机械盘凭借成本低廉以及存储稳定的特点,仍然广泛应用,而 IO 加速技术能让机械盘满足绝大多数应用场景的高 IO 性能需求。


2IO 加速原理及第一代 IO 加速


我们知道机械磁盘的特性是随机 IO 性能较差,但顺序 IO 性能较好,如前文中提到的 4K 随机 IO 只能有 300 IOPS 的性能,但其顺序 IO 性能可以达到 45000 IOPS。


IO 加速的基本原理就是利用了机械磁盘的这种性能特性,首先系统有两块盘:一块是 cache 盘,它是容量稍小的机械盘,用来暂时保存写入的数据;另一块是目标盘,它是容量较大的机械盘,存放最终的数据。

1. IO 的读写

写入时将上层的 IO 顺序的写入到 cache 盘上,因为是顺序的方式写入所以性能非常好,然后在 cache 盘空闲时由专门的线程将该盘的数据按照写入的先后顺序回刷到目标盘,使得 cache 盘保持有一定的空闲空间来存储新的写入数据。


为了做到上层业务无感知,我们选择在宿主机内核态的 device mapper 层(简称 dm 层)来实现该功能,dm 层结构清晰,模块化较为方便,实现后对上层体现为一个 dm 块设备,上层不用关心这个块设备是如何实现的,只需要知道这是一个块设备可以直接做文件系统使用。



按照上述方式,当新的 IO 写入时,dm 层模块会将该 IO 先写入 cache 盘,然后再回刷到目标盘,这里需要有索引来记录写入的 IO 在 cache 盘上的位置和在目标盘上的位置信息,后续的回刷线程就可以利用该索引来确定 IO 数据源位置和目标位置。我们将索引的大小设计为 512 字节,因为磁盘的扇区是 512 字节,所以每次的写入信息变成了 4K 数据+512 字节索引的模式,为了性能考虑,索引的信息也会在内存中保留一份。


读取过程比较简单,通过内存中的索引判断需要读取位置的数据是在 cache 盘中还是在目标盘中,然后到对应的位置读取即可。


写入的数据一般为 4K 大小,这是由内核 dm 层的特性决定的,当写入 IO 大于 4K 时,dm 层默认会将数据切分,比如写入 IO 是 16K,那么就会切分成 4 个 4K 的 IO;如果写入数据不是按照 4K 对齐的,比如只有 1024 字节,那么就会先进行特殊处理,首先检查该 IO 所覆盖的数据区,如果所覆盖的内存区在 cache 盘中有数据,那么需要将该数据先写入目标盘,再将该 IO 写入目标盘,这个处理过程相对比较复杂,但在文件系统场景中大部分 IO 都是 4K 对齐的,只有极少数 IO 是非对齐的,所以并不会对业务的性能造成太大影响。

2. 索引的快速恢复与备份

系统在运行过程中无法避免意外掉电或者系统关闭等情况发生,一个健壮的系统必须能够在遇到这些情况时依然能保证数据的可靠性。当系统启动恢复时,需要重建内存中的索引数据,这个数据在 cache 盘中已经和 IO 数据一起写入了,但因为索引是间隔存放的,如果每次都从 cache 盘中读取索引,那么,数据的恢复速度会非常慢。


为此,我们设计了内存索引的定期 dump 机制,每隔大约 1 小时就将内存中的索引数据 dump 到系统盘上,启动时首先读取该 dump 索引,然后再从 cache 盘中读取 dump 索引之后的最新 1 小时内的索引,这样,就大大提升了系统恢复的启动时间。


依据上述原理,UCloud 自研了第一代 IO 加速方案。采用该方案后,系统在加速随机写入方面取得了显著效果,且已在线上稳定运行。

3 第一代 IO 加速方案存在的问题

但随着系统的运行,我们也发现了一些问题。


1)索引内存占用较大

磁盘索引因为扇区的原因最小为 512 字节,但内存中的索引其实没有必要使用这么多,过大的索引会过度消耗内存。

2)负载高时 cache 盘中堆积的 IO 数据较多

IO 加速的原理主要是加速随机 IO,对顺序 IO 因为机械盘本身性能较好不需要加速,但该版本中没有区分顺序 IO 和随机 IO,所有 IO 都会统一写入 cache 盘中,使得 cache 堆积 IO 过多。

3)热升级不友好

初始设计时对在线升级的场景考虑不足,所以第一代 IO 加速方案的热升级并不友好。

4)无法兼容新的 512e 机械磁盘

传统机械磁盘物理扇区和逻辑扇区都是 512 字节,而新的 512e 磁盘物理扇区是 4K 了,虽然逻辑扇区还可以使用 512 字节,但性能下降严重,所以第一代 IO 加速方案的 4K 数据+512 字节索引的写入方式需要进行调整。

5)性能无法扩展

系统性能取决于 cache 盘的负载,无法进行扩展。

4 第二代 IO 加速技术

上述问题都是在第一代 IO 加速技术线上运营的过程中发现的。并且在对新的机械磁盘的兼容性方面,因为传统的 512 字节物理扇区和逻辑扇区的 512n 类型磁盘已经逐渐不再生产,如果不对系统做改进,系统可能会无法适应未来需求。因此,我们在第一代方案的基础上,着手进行了第二代 IO 加速技术的研发和优化迭代。

1. 新的索引和索引备份机制

第一代的 IO 加速技术因为盘的原因无法沿用 4K+512Byte 的格式,为了解决这个问题,我们把数据和索引分开,在系统盘上专门创建了一个索引文件,因为系统盘基本处于空闲状态,所以不用担心系统盘负载高影响索引写入,同时我们还优化了索引的大小由 512B 减少到了 64B,而数据部分还是写入 cache 盘,如下图所示:



其中索引文件头部和数据盘头部保留两个 4K 用于存放头数据,头数据中包含了当前 cache 盘数据的开始和结束的偏移,其后是具体的索引数据,索引与 cache 盘中的 4K 数据是一一对应的关系,也就是每个 4K 的数据就会有一个索引。


因为索引放在了系统盘,所以也要考虑,如果系统盘发生了不可恢复的损坏时,如何恢复索引的问题。虽然系统盘发生损坏是非常小概率的事件,但一旦发生,索引文件将会完全丢失,这显然是无法接受的。因此,我们设计了索引的备份机制,每当写入 8 个索引,系统就会将这些索引合并成一个 4K 的索引备份块写入 cache 盘中(具体见上图中的紫色块),不满 4K 的部分就用 0 来填充,这样当系统盘真的发生意外也可以利用备份索引来恢复数据。


在写入时会同时写入索引和数据,为了提高写入效率,我们优化了索引的写入机制,引入了合并写入的方式:



当写入时可以将需要写入的多个索引合并到一个 4K 的 write buffer 中,一次性写入该 write buffer,这样避免了每个索引都会产生一个写入的低效率行为,同时也保证了每次的写入是 4K 对齐的。

2. 顺序 IO 识别能力

在运营第一代 IO 加速技术的过程中,我们发现用户在做数据备份、导入等操作时,会产生大量的写入,这些写入基本都是顺序的,其实不需要加速,但第一代的 IO 加速技术并没有做区分,所以这些 IO 都会被写入在 cache 盘中,导致 cache 盘堆积的 IO 过多。为此,我们添加了顺序 IO 识别算法,通过算法识别出顺序的 IO,这些 IO 不需要通过加速器,会直接写入目标盘。


一个 IO 刚开始写入时是无法预测此 IO 是顺序的还是随机的,一般的处理方式是当一个 IO 流写入的位置是连续的,并且持续到了一定的数量时,才能认为这个 IO 流是顺序的,所以算法的关键在于如何判断一个 IO 流是连续的,这里我们使用了触发器的方式。


当一个 IO 流开始写入时,我们会在这个 IO 流写入位置的下一个 block 设置一个触发器,触发器被触发就意味着该 block 被写入了,那么就将触发器往后移动到再下一个 block,当触发器被触发了一定的次数,我们就可以认为这个 IO 流是顺序的,当然如果触发器被触发后一定时间没有继续被触发,那么我们就可以回收该触发器。

3. 无感知热升级

第一代的 IO 加速技术设计上对热升级支持并不友好,更新存量版本时只能通过热迁移然后重启的方式,整个流程较为繁琐,所以在开发第二代 IO 加速技术时,我们设计了无感知热升级的方案。


由于我们的模块是位于内核态的 dm 层,一旦初始化后就会生成一个虚拟的 dm 块设备,该块设备又被上层文件系统引用,所以这个模块一旦初始化后就不能卸载了。为了解决这个问题,我们设计了父子模块的方式,父模块在子模块和 dm 层之间起到一个桥梁的作用,该父模块只有非常简单的 IO 转发功能,并不包含复杂的逻辑,因此可以确保父模块不需要进行升级,而子模块包含了复杂的业务逻辑,子模块可以从父模块中卸载来实现无感知热升级:



上图中的 binlogdev.ko 就是父模块,cachedev.ko 为子模块,当需要热升级时可以将 cache 盘设置为只读模式,这样 cache 盘只回刷数据不再写入,等 cache 盘回刷完成后,可以认为后续的写入 IO 可直接写入目标盘而不用担心覆盖 cache 盘中的数据,这样子模块就可以顺利拔出替换了。


这样的热升级机制不仅实现了热升级的功能,还提供了故障时的规避机制,在 IO 加速技术的灰度过程中,我们就发现有个偶现的 bug 会导致宿主机重启,我们第一时间将所有 cache 盘设置为只读,以避免故障的再次发生,并争取到了 debug 的时间。

4. 兼容 512e 机械磁盘

新一代的机械磁盘以 512e 为主,该类型的磁盘需要写入 IO 按照 4K 对齐的方式才能发挥最大性能,所以原先的 4K+512B 的索引格式已经无法使用,我们也考虑过把 512B 的索引扩大到 4K,但这样会导致索引占用空间过多,且写入时也会额外占用磁盘的带宽效率太低,所以最终通过将索引放到系统盘并结合上文提到的合并写入技术来解决该问题。

5. 性能扩展和提升

在第一代的 IO 加速技术中只能使用 1 块 cache 盘,当这块 cache 盘负载较高时就会影响系统的性能,在第二代 IO 加速中,我们设计了支持多块 cache 盘,并按照系统负载按需插入的方式,使加速随机 IO 的能力随着盘数量的提升而提升。在本地 cache 盘以及网络 cache 盘都采用 SATA 机械磁盘的条件下,测试发现,随着使用的 cache 盘数量的增多,随机写的性能也得到了大幅度的提升。



目前,我们已经大规模部署应用了第二代 IO 加速技术的云主机。得益于上述设计,之前备受困扰的 cache 盘 IO 堆积过多、性能瓶颈等问题得到了极大的缓解,特别是 IO 堆积的问题,在第一代方案下,负载较高时经常触发并导致性能损失和运维开销,采用第二代 IO 加速技术后,该监控告警只有偶现的几例触发。

5 写在最后

云主机 IO 加速技术极大提升了机械盘随机写的处理能力,使得用户可以利用较低的价格满足业务需求。且该技术的本质并不单单在于对机械盘加速,更是使系统层面具备了一种可以把性能和所处的存储介质进行分离的能力,使得 IO 的性能并不受限于其所存储的介质。此外,一项底层技术在实际生产环境中的大规模应用,其设计非常关键,特别是版本热升级、容错以及性能考虑等都需要仔细斟酌。希望本文可以帮助大家更好的理解底层技术的特点及应用,并在以后的设计中做出更好的改进。


本文转载自公众号 UCloud 技术(ID:ucloud_tech)。


原文链接:


https://mp.weixin.qq.com/s/jze_a8ozR1ChswvJmTe9Ig


2019-11-11 16:361183

评论

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

实践基地+新工科实训 青软与西南大学展开多元校企合作

神奇视野

青软集团蝉联华为云「千万俱乐部奖」「最佳销售黑钻奖」两大奖项

神奇视野

工程师如何拥抱数字化转型?

星策开源社区

工程师 产业数字化 数字化时代 智能化转型

RT-Thread记录(十二、I/O 设备模型之UART设备 — 使用测试)

矜辰所致

RT-Thread 8月月更

大厂面试真的很难吗?字节跳动3面+腾讯6面一次过,谈谈我的大厂面经

程序知音

Java java面试 程序员面试 后端技术 八股文

即刻报名|汽车制造行业如何玩转大数据分析?

Kyligence

数据分析 汽车制造

开源一夏 | MySQL 事务的隔离级别

六月的雨在InfoQ

开源 mysql事务 MySQL 数据库 8月月更

Zebec社区利好频传,Galaxy Project上领取专属Zebec OAT

小哈区块

什么是外网?外网需要做等保吗?与内网的区别是什么?

行云管家

等保 等级保护 内网 外网

天翼云为这场酷炫的元宇宙会议做了这件事

天翼云开发者社区

企业搭建知识库的重要性,你了解多少?

Geek_da0866

基于 Flink x TiDB,智慧芽打造实时分析新方案

Apache Flink

大数据 flink 编程 流计算 实时计算

金山云团队分享 | 5000字读懂Presto如何与Alluxio搭配

Alluxio

金山云 presto Alluxio 大数据 开源 8月月更

天翼云TeleDB系列产品升级发布会开幕在即,精彩邀您共鉴

天翼云开发者社区

图灵访谈 | Vue.js官方团队成员霍春阳:跨专业做程序员,是什么感受?

图灵教育

“客户体验管理”这么热,究竟能给企业带来什么变化?

科技怪咖

Golang 使用过程中遇到的小技巧(一)

皮特王

DPDK技术原理与架构

C++后台开发

虚拟化 DDoS DPDK VPP NFV

Zebec社区利好频传,Galaxy Project上领取专属Zebec OAT

西柚子

基于 Flink 构建大规模实时风控系统在阿里巴巴的落地

Apache Flink

大数据 flink 编程 流计算 实时计算

语音交友APP:搭建部署流程及主要功能介绍

开源直播系统源码

软件开发 直播系统源码 语音直播系统

重庆邮电大学新工科训练营 实践Java和大数据方向全真产业项目

神奇视野

程序员被京东淘汰转身痛哭,HR扎心了

千锋IT教育

如何让工业制造拥有更强的“数字内核”?

天翼云开发者社区

使用 Canonical MAAS 部署 openEuler 测试

openEuler

centos 开源 操作系统 openEuler MaaS

今日头条三天点击破亿!四天精通springcloud微服务架构

退休的汤姆

社招 java架构师 秋招 #java spring、

RT-Thread记录(十三、I/O 设备模型之PIN设备)

矜辰所致

RT-Thread 8月月更 I/O设备模型

金融机构求索数据价值,“数牍方案”提供可行解 数牍科技

Jessica@数牍

隐私计算 金融行业 数据隐私安全

云成本支出不受控制怎么办?教您一招!

行云管家

云计算 云资源 云成本

2022“易观之星”年度奖项启动征集,发现卓越数智力量

易观分析

报名 数智化 易观之星

天翼云入选可信边缘计算推进计划与分布式云扬帆计划首批成员单位!

天翼云开发者社区

150倍加速机械盘,UCloud云主机IO加速技术揭秘_文化 & 方法_王宏辉_InfoQ精选文章