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

“打脸”谷歌云,说好的超低延迟和可靠性呢?

  • 2022-08-17
    北京
  • 本文字数:3805 字

    阅读完需:约 12 分钟

“打脸”谷歌云,说好的超低延迟和可靠性呢?

在国内,很多朋友习惯用 Discord 收发消息。每一天,都有成百上千万用户通过 Discord 平台传递多达 40 亿条消息,而文本聊天其实只占其中一部分。服务器角色、自定义表情符号、视频通话等也都在一刻不停地往来流转,共同构成了全球用户高达数百 TB 的交互数据总量。


为了支持如此庞大的数据规模,我们运行有一组 NoSQL 数据库集群(采用 ScyllaDB),其中每个集群都作为相应数据集的真实来源。作为实时聊天平台,我们希望 Discord 的数据库能够尽快响应来自用户的高频率查询。



从截屏中可见,我们的数据库每秒处理约 200 万条请求

超越硬件极限


我们这套数据库面临的最大性能挑战,就是单一磁盘操作带来的延迟——也就是面向物理硬件执行数据读取/写入所耗费的时间。在数据库查询率低于一定水平时,磁盘延迟其实并不明显,毕竟我们的数据库在并行处理请求方面颇有心得(不会阻塞单个磁盘操作)。


但这种并行能力是有极限的,所以一旦查询率达到某个阈值,数据库就需要先等待上一条磁盘操作完成,之后才会发出下一条。再加上本身就需要一、两毫秒才能完成的磁盘操作,就导致数据库无法立即向传入的查询提供数据结果。于是乎,磁盘操作和查询就得排队等待,拖慢对查询客户端的响应速度,进而导致应用程序性能不佳。


在最极端的情况下,整个事态可能会级联出一个不断扩大的磁盘操作队列,最终使得磁盘查询超时。我们在自己的服务器上就曾经见到过这样的状况,数据库中的磁盘读取队列越来越长,查询操作也开始发生超时。


看到这里,细心的朋友可能发现了:磁盘操作要一、两毫秒才能完成?磁盘延迟不是应该以微秒为单位吗,这怎么直接提升了一个数量级?


Discord 的大部分硬件运行在谷歌云中,所以能够获得对“本地 SSD”的直接访问。所谓本地 SSD,就是基于 NVMe 的实例存储,确实可以提供令人印象深刻的超低延迟性能指标。


但遗憾的是,我们在测试中发现了一大堆可靠性问题,所以没法安心将关键数据存储在这套解决方案当中。于是我们重新开始思考,既然无法依赖超高速存储设备,那要怎么获得极低的延迟水平?


谷歌云还提供另外一种实例存储选项,也就是持久磁盘。这些磁盘可以一边运行,一边从服务器上附加/拆解,可以无需停机就调整容量大小,可以随时生成当前时间点快照,也可以按设计进行复制(防止单块磁盘故障导致数据丢失)。优点确实很多,但持久磁盘的短板就是并非直接接入服务器,而是通过网络就近(可能与服务器处于同一处数据中心内)连接。


虽然本地网络连接的延迟并不算高,但还是没法跟跨度在一米以内的 PCI 或 SATA 连接相比肩。所以,磁盘操作的平均延迟(从操作系统的角度来看)一般在几毫秒左右,而直连磁盘则可以控制在约 0.5 毫秒。



本地 SSD 还有其他问题。跟传统磁盘驱动器一样,一旦某款硬件(可能是 SSD 本身,也可能是 SSD 控制器)发生故障,则盘上的所有数据都会立即丢失。而且比传统磁盘更糟的是,如果本地 SSD 所接入的主机发生严重故障,那么盘上的数据将永久消失。因为无法为全盘创建时间点快照,所以 Discord 的某些工作流程(例如数据备份)在 SSD 上根本就不可行。正是由于这些功能缺失,所以 Discord 的几乎所有服务器配备的都是持久磁盘,而非本地 SSD。

问题评估


在理想状态下,我们当然应该用持久磁盘搭配本地 SSD,让它们各自发挥最佳属性,共同为数据库提供完美支持。但这样的完美搭配根本不存在,至少在常规云服务商的生态系统中完全找不到。选择延迟更低的直连 SSD,就意味着必须放弃持久磁盘的灵活性优势。


但如果我们愿意放弃其中一部分灵活性呢?比方说,写入延迟对我们的工作负载并不重要,因为读取延迟才是对应用程序性能影响最大的部分(消息发布平台上的大部分工作负载都属于读取密集型)。另外,在不停机的前提下,调整磁盘大小也没那么重要,我们完全可以认真预估容量需求,并提前配置更大的存储空间。



所以在考量了数据库运营中最关键的几项指标之后,我们缩小了对数据库解决方案的要求:


  • 继续使用谷歌云(继续使用 Google Cloud Platform 的存储产品)

  • 继续使用时间点快照进行数据备份

  • 将低延迟 SSD 读取,设为高于其他一切指标的首要原则

  • 不影响现有数据库的正常运行时间谷歌云提供多种存储选项,能够以各自不同的方式满足上述要求。所以如果能把两种存储方案组合成超级选项,那可就太方便了。因为我们对存储性能的核心诉求是低延迟读取,所以最好是能把读取操作交给谷歌云的本地 SSD(保证低延迟),而写入则继续指向持久磁盘(发挥快照、复制冗余等优势)。那么,有没有办法能在纯软件层面创建起这样的超级存储方案呢?

创建“超级盘”


我们前文描述的这套存储方案在本质上其实是个直写缓存,其中以本地 SSD 作为缓存、持久磁盘则作为存储层。我们的数据库服务器运行的是 Ubuntu,所以我们发现 Linux 内核提供 dm-cache、lvm-cache 和 bcache 等模块,能够以多种方式在盘这个层次上实现数据缓存。


但很遗憾,我们在缓存实验中发现了几个问题。首先就是如何处理缓存盘中的故障:一旦缓存中出现坏扇区,就会直接导致整个读取操作失败。本地 SSD 是 NVMe SSD 硬件之上的一个“薄”层,所以跟常规物理盘一样会受到坏扇区的影响。


我们当然可以用来自存储层的数据覆盖掉缓存上的扇区,借此实现坏扇区修复,但目前可选的缓存选项要么不提供这种功能、要么就是复杂度超出了当前阶段的承受范围。


总之,如果无法修复缓存中的坏扇区,这些扇区将直接暴露在执行调用的应用程序面前,我们的数据库则会出于安全原因而关闭:


storage_service - 由于 I/O 错误导致通信关闭,需要操作员干预


storage_service - 盘错误:std::system_error (error system:61, 无可用数据)


到这里,我们的需求被更新为:能够容忍本地 SSD 上存在坏扇区。为此,我们尝试了另外一种不同类型的 Linux 内核系统:md。


其实 md 的作用很简单,就是允许 Linux 创建软件 RAID 阵列,将多个盘转化成单一“阵列”(虚拟盘)。但我们无法简单将本地 SSD 和持久磁盘构建成简单的镜像(RAID1)阵列,因为这样会导致约一半的读取操作错误命中持久磁盘。这时候 md 的优势就来了,它提供一项传统 RAID 控制器所不具备的附加功能,即“write-mostly”。内核手册对这项功能做出了准确描述:


RAID1 中的单个设备可被标记为“write-mostly”。这些驱动器将被排除在正常的读取均衡之外,仅在没有其他选项时才会被读取。这项功能适用于通过慢速链路接入的设备。


就是它了,“通过慢速链路接入的设备”,这说的不就是持久磁盘吗?看起来 md 应该能帮我们完成打造“超级盘”的计划。只要构建一个包含本地 SSD 和 “write-mostly”持久磁盘的 RAID1 阵列,我们的所有要求就都能得到满足。


但现在还有最后一个问题:谷歌云中的本地 SSD 大小正好是 375 GB。对于某些应用程序,Discord 需要让单一数据库实例具备 1 TB 甚至更大的存储空间,所以 375 GB 明显有点不够看。我们当然可以把多个本地 SSD 接入服务器,但还需要找到办法把这堆小盘整合成统一的大盘。



好在 md 提供多种 RAID 配置,可以跨多个盘实现数据条带化。最简单的方式就是用 RAID0 将原始数据拆分到所有盘上,但这样如果某个盘损坏,整个阵列都会出现故障、导致全部数据丢失。更复杂的方法是用 RAID5、RAID6 保持奇偶校验,这样至少在单盘损坏时仍能保持数据完好,但代价就是性能下降。这是一种常见的正常运行时间保障方法,把损坏盘拆下、换块新盘即可。


但在谷歌云中,压根不存在替换本地 SSD 这个概念——毕竟这些设备都隐藏在谷歌数据中心的未知角落。另外,谷歌云还为本地 SSD 提供了一项神奇的“保障”服务:一旦有本地 SSD 发生故障,整个服务器将被迁移至另外一套数据集上,就相当于擦除了该服务器之前的所有本地 SSD 数据。因为没办法更换本地 SSD,也不想承担 RAID 条带造成的性能影响,所以我们最终选择用 RAID0 把多个本地 SSD 转化为单一低延迟虚拟磁盘。


我们用本地 SSD 建立 RAID0 阵列,再把持久磁盘跟 RAID0 阵列共同构建成 RAID1 阵列,这样就可以为数据库提供低延迟读取盘,同时仍然享受持久磁盘提供的种种灵活性优势。



数据库性能


从测试来看,这套新方案确实表现不错。那在实际生产中,它又能不能满足我们的需求呢?


结果没有令我们失望 — 在峰值负载时,我们的数据库再未出现过磁盘操作队列,而且查询延迟也不会波动。再结合实践指标,可以看到绝大部分数据库读取都发生在这套“超级盘”上,极少会跑去读持久磁盘,所以 I/O 操作的整体耗时得到显著降低。



凭借出色的性能提升,我们能够在同一批服务器上处理更多查询。这对我们这些数据库服务器维护人员和公司财务部门来说,都是个好消息。

总结

回想起来,我们真该在数据库部署之初就认真处理磁盘延迟问题。云计算世界中包含太多系统,所以同样的硬件在其中的运行方式往往跟我们熟悉的本地数据中心截然不同。


通过这次“超级盘”解决方案的研发和测试经历,我们总结出一系列实用的性能监控指标,让团队理解了存储设备的内部工作原理(包括在 Linux 和谷歌云环境下),同时也改善了我们的测试与验证架构变更文化。随着“超级盘”的生产实践,我们的数据库终于能随 Discord 用户规模的扩大而稳定拓展了。


但拥有 RAID 集群维护经验的朋友可能还抱有疑问:这样一套配置能稳定运行吗?毕竟云环境下充斥着无数系统,往往会以难以理解的方式引发故障。所以单靠 md 配置,恐怕不足以支撑起一套稳定的存储组合方案。说得没错,所以请大家期待本系列博文的第二部分,届时我们将具体介绍“超级盘”在云端遇到的极端案例,并分享我们的解决思路。


原文链接:


https://discord.com/blog/how-discord-supercharges-network-disks-for-extreme-low-latency


公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2022-08-17 18:045931
用户头像
赵钰莹 InfoQ 主编

发布了 875 篇内容, 共 606.1 次阅读, 收获喜欢 2671 次。

关注

评论

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

数据库不推荐使用外键的9个理由!

TimeFriends

8月月更

【LeetCode】受限条件下可到达节点的数目Java题解

Albert

LeetCode 8月月更

面试突击72:输入URL之后会执行什么流程?

王磊

Java 面试

HMS Core分析服务智能运营6.5.1版本上线

HMS Core

业务缓存之体系化设计与开发

Qunar技术沙龙

系统开发

在SAP分析云里根据业务数据绘制词云(Word Cloud)

Jerry Wang

SaaS SAP 词云 8月月更 word-cloud

易周金融分析 | 互联网系小贷平台密集增资;上半年银行理财子公司综合评价指数发布

易观分析

金融 分析 易周金融

Python逆向之 eval 函数解析,看着一篇就会了,案例掌房

梦想橡皮擦

Python 爬虫 8月月更

Spring(五、注解开发)

开源 8月月更

如何用建木CI构建前端E2E质量自查

Jianmu

DevOps 前端 持续集成 代码质量 自动化测试

K8S之Flannel的vxlan网络模式初步源码解析

k8s flannel 签约计划第三季

Java 在Word中合并单元格时删除重复值

在下毛毛雨

java; 合并单元格 删除重复值

一文读懂配置管理(CM)

SEAL安全

企业安全 企业it安全 代码安全

结合“xPlus”探讨软件架构的创新与变革

BizFree

敏捷开发 软件架构 数字化 信息化 软件定制

STM32F103ZE+SHT30检测环境温度与湿度(IIC模拟时序)

DS小龙哥

8月月更

以技术御风险,护航云原生 | 同创永益 X 博云举办产品联合发布会

BoCloud博云

云计算 容器 云原生

Dapr在Java中的实践 之 环境准备

万猫学社

微服务 dapr Sidecar

鲲鹏开发者创享日2022:鲲鹏全栈创新 与开发者共建数字湖南

科技热闻

Kubernetes资源编排系列之四: CRD+Operator篇

阿里云大数据AI技术

大数据 运维

5S软件就是将软件应用全维度简单化的软件系统

BizFree

k8s 敏捷开发 软件架构 高性能 快捷调试

PWA 应用 Service Worker 缓存的一些可选策略和使用场景

Jerry Wang

typescript 前端开发 angular Service Worker 8月月更

Dapr在Java中的实践 之 服务调用

万猫学社

微服务 dapr Sidecar

语音聊天app开发——对用户更具吸引力的设计

开源直播系统源码

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

Redis 定长队列的探索和实践

vivo互联网技术

redis 数据结构 消息队列 Lua脚本

分分钟快速定制您的专属个性化软件应用——BizTool自动化工具简介

BizFree

软件开发 快速开发 低代码开发 个性化 应用开发

「控制反转」和「依赖倒置」,傻傻分不清楚?

蝉沐风

ioc 依赖倒置原则 DIP DI 控制反转

左益豪:用代码创造一个新世界|OneFlow U

OneFlow

实习 社区之星

开源一夏 | 牛plus,多层嵌套动态JSON该如何解析总结

知识浅谈

开源 8月月更

使用类似搭积木的低代码开发方式进行 SAP API 开发

Jerry Wang

低代码 云平台 SAP 8月月更 low-code

自动驾驶中的SLAM

博文视点Broadview

Dapr在Java中的实践 之 状态管理

万猫学社

Java 微服务 dapr Sidecar

“打脸”谷歌云,说好的超低延迟和可靠性呢?_文化 & 方法_Glen Oakley_InfoQ精选文章