1.3万亿条数据查询,如何做到毫秒级响应?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 1.3万亿条数据查询,如何做到毫秒级响应?

知乎,在古典中文中意为“你知道吗?”,它是中国的 Quora,一个问答网站,其中各种问题由用户社区创建,回答,编辑和组织。

作为中国最大的知识共享平台,我们目前拥有 2.2 亿注册用户,3000 万个问题,网站答案超过 1.3 亿。

随着用户群的增长,我们的应用程序的数据大小无法实现。我们的 Moneta 应用程序中存储了大约 1.3 万亿行数据(存储用户已经阅读过的帖子)。

由于每月累计产生大约 1000 亿行数据且不断增长,这一数字将在两年内达到 3 万亿。在保持良好用户体验的同时,我们在扩展后端方面面临严峻挑战。

在这篇文章中,我将深入探讨如何在如此大量的数据上保持毫秒级的查询响应时间,以及 TiDB 是一个开源的 MySQL 兼容的 NewSQL 混合事务/分析处理( HTAP)数据库,如何为我们提供支持获得对我们数据的实时洞察。

我将介绍为什么我们选择 TiDB,我们如何使用它,我们学到了什么,优秀实践以及对未来的一些想法。


我们的痛点


本节介绍了我们的 Moneta 应用程序的体系结构,我们尝试构建的理想体系结构,以及数据库可伸缩性作为我们的主要难点。


系统架构要求

知乎的 Post Feed 服务是一个关键系统,用户可以通过该系统接收网站上发布的内容。

后端的 Moneta 应用程序存储用户已阅读的帖子,并在知乎的推荐页面的帖子流中过滤掉这些帖子。

Moneta 应用程序具有以下特征:


  • 需要高可用性数据:Post Feed 是第一个出现的屏幕,它在推动用户流量到知乎方面发挥着重要作用。
  • 处理巨大的写入数据:例如,在高峰时间每秒写入超过 4 万条记录,记录数量每天增加近 30 亿条记录。
  • 长期存储历史数据:目前,系统中存储了大约 1.3 万亿条记录。随着每月累积约 1000 亿条记录并且不断增长,历史数据将在大约两年内达到 3 万亿条记录。
  • 处理高吞吐量查询:在高峰时间,系统处理平均每秒在 1200 万个帖子上执行的查询。
  • 将查询的响应时间限制为 90 毫秒或更短:即使对于执行时间最长的长尾查询,也会发生这种情况。
  • 容忍误报:这意味着系统可以为用户调出许多有趣的帖子,即使有些帖子被错误地过滤掉了。


考虑到上述事实,我们需要一个具有以下功能的应用程序架构:


  • 高可用性:当用户打开知乎的推荐页面时,找到大量已经阅读过的帖子是一种糟糕的用户体验。
  • 出色的系统性能:我们的应用具有高吞吐量和严格的响应时间要求。
  • 易于扩展:随着业务的发展和应用程序的发展,我们希望我们的系统可以轻松扩展。


勘探

为了构建具有上述功能的理想架构,我们在之前的架构中集成了三个关键组件:


  • 代理:这会将用户的请求转发给可用节点,并确保系统的高可用性。
  • 缓存:这暂时处理内存中的请求,因此我们并不总是需要处理数据库中的请求。这可以提高系统性能。
  • 存储:在使用 TiDB 之前,我们在独立的 MySQL 上管理我们的业务数据。随着数据量的激增,独立的 MySQL 系统还不够。然后我们采用了 MySQL 分片和 Master High Availability Manager( MHA)的解决方案,但是当每月有 1000 亿条新记录涌入我们的数据库时,这个解决方案是不可取的。


MySQL Sharding 和 MHA 的缺点

MySQL 分片和 MHA 不是一个好的解决方案,因为 MySQL 分片和 MHA 都有它们的缺点。


MySQL 分片的缺点:

  • 应用程序代码变得复杂且难以维护。
  • 更改现有的分片键很麻烦。
  • 升级应用程序逻辑会影响应用程序的可用性。

MHA 的缺点:

  • 我们需要通过编写脚本或使用第三方工具来实现虚拟 IP(VIP)配置。
  • MHA 仅监视主数据库。
  • 要配置 MHA,我们需要配置无密码安全 Shell( SSH)。这可能会导致潜在的安全风险。
  • MHA 不为从属服务器提供读取负载平衡功能。
  • MHA 只能监视主服务器(而不是从主服务器)是否可用。


在我们发现 TiDB 并将数据从 MySQL 迁移到 TiDB 之前,数据库可伸缩性仍然是整个系统的弱点。

什么是 TiDB?


TiDB 平台是一组组件,当它们一起使用时,它们将成为具有 HTAP 功能的 NewSQL 数据库。

image.png

TiDB 平台架构

在 TiDB 平台内部,主要组件如下:


  • TiDB 服务器是一个无状态的 SQL 层,它处理用户的 SQL 查询,访问存储层中的数据,并将相应的结果返回给应用程序。它与 MySQL 兼容并且位于 TiKV 之上。
  • TiKV 服务器是数据持久存在的分布式事务键值存储层。它使用 Raft 共识协议进行复制,以确保强大的数据一致性和高可用性。
  • TiSpark 集群也位于 TiKV 之上。它是一个 Apache Spark 插件,可与 TiDB 平台配合使用,支持商业智能(BI)分析师和数据科学家的复杂在线分析处理(OLAP)查询。
  • 放置驱动程序(PD)服务器是由 etcd 支持的元数据集群,用于管理和调度 TiKV。



除了这些主要组件之外,TiDB 还拥有一个工具生态系统,例如用于快速部署的  Ansible 脚本,用于从 MySQL 迁移的 Syncer 和 TiDB 数据迁移。

以及用于收集对 TiDB 群集进行的逻辑更改并提供增量备份的 TiDB Binlog。复制到下游(TiDB,Kafka 或 MySQL)。

TiDB 的主要功能包括:


  • 水平可扩展性。
  • MySQL 兼容的语法。
  • 具有强一致性的分布式事务。
  • 云原生架构。
  • 使用 HTAP 进行最小提取,转换,加载( ETL)。
  • 容错和 Raft 恢复。
  • 在线架构更改。


我们如何使用 TiDB


在本节中,我将向您展示如何在 Moneta 的架构中运行 TiDB 以及 Moneta 应用程序的性能指标。

我们架构中的 TiDB

image.png

我们在系统中部署了 TiDB,Moneta 应用程序的整体架构变为:


  • 顶层:无状态和可伸缩的客户端 API 和代理。这些组件易于扩展。
  • 中间层:软状态组件和分层 Redis 缓存作为主要部分。当服务中断时,这些组件可以通过恢复保存在 TiDB 群集中的数据来自我恢复服务。
  • 底层:TiDB 集群存储所有有状态数据。它的组件高度可用,如果节点崩溃,它可以自我恢复其服务。


在该系统中,所有组件都是可自我恢复的,整个系统具有全局故障监视机制。然后,我们使用 Kubernetes 来协调整个系统,以确保整个服务的高可用性。


TiDB 的性能指标

由于我们在生产环境中应用了 TiDB,因此我们的系统具有高可用性和易于扩展性,并且系统性能得到显著改善。例如,在 2019 年 6 月为 Moneta 应用程序采用一组性能指标。

image.png

image.png

第 99 百分位响应时间约为 25 毫秒,第 999 百分位响应时间约为 50 毫秒。实际上,平均响应时间远远小于这些数字,即使对于需要稳定响应时间的长尾查询也是如此。

image.png

image.png

我们学到了什么


我们迁移到 TiDB 并非顺利,在这里,我们想分享一些经验教训。


更快地导入数据我们使用 TiDB 数据迁移(DM)来收集 MySQL 增量 Binlog 文件,然后使用 TiDB Lightning 将数据快速导入 TiDB 集群。

令我们惊讶的是,将这 1.1 万亿条记录导入 TiDB 只用了四天时间。如果我们逻辑地将数据写入系统,可能需要一个月或更长时间。如果我们有更多的硬件资源,我们可以更快地导入数据。

减少查询延迟

完成迁移后,我们测试了少量的读取流量。当 Moneta 应用程序首次上线时,我们发现查询延迟不符合我们的要求。为解决延迟问题,我们与 PingCap 工程师合作调整系统性能。

在此过程中,我们积累了宝贵的数据和数据处理知识:


  • 有些查询对查询延迟很敏感,有些则不然。我们部署了一个单独的 TiDB 数据库来处理对延迟敏感的查询。(其他非延迟敏感的查询在不同的 TiDB 数据库中处理。)这样,大型查询和对延迟敏感的查询在不同的数据库中处理,前者的执行不会影响后者。
  • 对于没有理想执行计划的查询,我们编写了 SQL 提示来帮助执行引擎选择最佳执行计划。
  • 我们使用低精度时间戳 Oracle( TSO)和预处理语句来减少网络往返。


评估资源

在我们尝试 TiDB 之前,我们没有分析我们需要多少硬件资源来支持 MySQL 端的相同数据量。


为了降低维护成本,我们在单主机 - 单从机拓扑中部署了 MySQL。相反,在 TiDB 中实现的 Raft 协议至少需要三个副本。

因此,我们需要更多的硬件资源来支持 TiDB 中的业务数据,我们需要提前准备机器资源。

一旦我们的数据中心设置正确,我们就可以快速完成对 TiDB 的评估。

对 TiDB 3.0 的期望


在知乎,反垃圾邮件和 Moneta 应用程序的架构相同。我们在用于生产数据的反垃圾邮件应用程序中尝试了 TiDB 3.0(TiDB 3.0.0-rc.1 和 TiDB 3.0.0-rc.2)的候选版本中的 Titan 和 Table Partition。

①Titan 缩短了延迟

反垃圾邮件应用程序一直受到严重的查询和写入延迟折磨。

我们听说 TiDB 3.0 将引入 Titan,一种键值存储引擎,用于在使用大值时减少  RocksDB(TiKV 中的底层存储引擎)的写入放大。为了尝试这个功能,我们在 TiDB 3.0.0-rc.2 发布后启用了 Titan。

image.png

在 RocksDB 和 Titan 中编写和查询延迟

统计数据显示,在我们启用 Titan 后,写入和查询延迟都急剧下降。这真是太惊人了!当我们看到统计数据时,我们无法相信自己的眼睛。

②表分区改进了查询性能

我们还在反垃圾邮件应用程序中使用了 TiDB 3.0 的表分区功能。使用此功能,我们可以按时将表分成多个分区。

当查询到来时,它将在覆盖目标时间范围的分区上执行。这大大提高了我们的查询性能。

让我们考虑一下如果我们将来在 Moneta 和反垃圾邮件应用程序中实施 TiDB 3.0 会发生什么。

③Moneta 应用程序中的 TiDB 3.0

TiDB 3.0 具有诸如 gRPC 中的批处理消息,多线程 Raftstore,SQL 计划管理和 TiFlash 等功能。我们相信这些将为 Moneta 应用增添光彩。


④gRPC 和多线程 Raftstore 中的批处理消息


Moneta 的写入吞吐量超过每秒 4 万次交易(TPS),TiDB 3.0 可以批量发送和接收 Raft 消息,并且可以在多个线程中处理 Region Raft 逻辑。我们相信这些功能将显著提高我们系统的并发能力


⑤SQL 计划管理


如上所述,我们编写了大量 SQL 提示,以使查询优化器选择最佳执行计划。

TiDB 3.0 添加了一个 SQL 计划管理功能,可以直接在 TiDB 服务器中将查询绑定到特定的执行计划。使用此功能,我们不需要修改查询文本以注入提示。


⑥TiFlash


在 TiDB DevCon 2019 上,我第一次听说 TiFlash 是 TiDB 的扩展分析引擎。

它使用面向列的存储技术来实现高数据压缩率,并在数据复制中应用扩展的 Raft 一致性算法以确保数据安全性。

由于我们拥有高写入吞吐量的海量数据,因此我们无法每天使用 ETL 将数据复制到 Hadoop 进行分析。但是对于 TiFlash,我们乐观地认为我们可以轻松分析我们庞大的数据量。


⑦反垃圾邮件应用程序中的 TiDB 3.0


与 Moneta 应用程序的巨大历史数据大小相比,反垃圾邮件应用程序具有更高的写入吞吐量。

但是,它仅查询过去 48 小时内存储的数据。在此应用程序中,数据每天增加 80 亿条记录和 1.5 TB。

由于 TiDB 3.0 可以批量发送和接收 Raft 消息,并且它可以在多个线程中处理 Region Raft 逻辑,因此我们可以用更少的节点管理应用程序。

以前,我们使用了七个物理节点,但现在我们只需要五个。即使我们使用商用硬件,这些功能也可提升性能。

下一步是什么


TiDB 是一个与 MySQL 兼容的数据库,因此我们可以像使用 MySQL 一样使用它。

由于 TiDB 的横向可扩展性,现在我们可以自由扩展我们的数据库,即使我们有超过一万亿的记录来应对。

到目前为止,我们已经在我们的应用程序中使用了相当多的开源软件。我们还学到了很多关于使用 TiDB 处理系统问题的知识。

我们决定参与开发开源工具,并参与社区的长期发展。基于我们与 PingCAP 的共同努力,TiDB 将变得更加强大。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
Java 数据库连接 数据库
强大:MyBatis ,三种流式查询方法
流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。
强大:MyBatis ,三种流式查询方法
|
存储 缓存 Oracle
|
12月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
Java 应用服务中间件 API
Vertx高并发理论原理以及对比SpringBoot
Vertx 是一个基于 Netty 的响应式工具包,不同于传统框架如 Spring,它的侵入性较小,甚至可在 Spring Boot 中使用。响应式编程(Reactive Programming)基于事件模式,通过事件流触发任务执行,其核心在于事件流 Stream。相比多线程异步,响应式编程能以更少线程完成更多任务,减少内存消耗与上下文切换开销,提高 CPU 利用率。Vertx 适用于高并发系统,如 IM 系统、高性能中间件及需要较少服务器支持大规模 WEB 应用的场景。随着 JDK 21 引入协程,未来 Tomcat 也将优化支持更高并发,降低响应式框架的必要性。
331 6
Vertx高并发理论原理以及对比SpringBoot
|
12月前
|
SQL 缓存 分布式计算
C#如何处理上亿级数据的查询效率
C#如何处理上亿级数据的查询效率
224 2
|
关系型数据库 MySQL API
MySQL上亿数据查询优化:实践与技巧
MySQL亿级数据查询优化涉及索引设计、分区表、查询语句优化和数据库架构调整。例如,通过为常用查询列创建索引、使用EXPLAIN分析查询计划、避免全表扫描和SELECT *,以及采用垂直拆分、水平拆分和读写分离来提升性能。分区表能减少查询数据量,API接口测试可验证优化效果。
774 0
|
存储 NoSQL 物联网
【MongoDB 专栏】MongoDB 在物联网(IoT)领域的应用
【5月更文挑战第11天】MongoDB,一种灵活可扩展的非关系型数据库,在物联网(IoT)领域中大放异彩。应对海量设备产生的多样化数据,MongoDB的文档型数据结构适应性强,适合存储设备信息及传感器读数。其实时更新、强大查询语言、索引机制和扩展性(通过分片技术)满足物联网的高实时性、复杂查询和数据增长需求。尽管面临数据安全和管理挑战,MongoDB已广泛应用于智能家居、工业 IoT 和智能交通等领域,并有望随着物联网技术进步和与其他领域的融合,如人工智能、大数据,持续发展。未来,优化数据质量、提升并发处理能力将是关键,MongoDB将在物联网的智能未来中扮演重要角色。
926 2
【MongoDB 专栏】MongoDB 在物联网(IoT)领域的应用
|
监控 搜索推荐 数据挖掘
Flink流处理与批处理大揭秘:实时与离线,一文让你彻底解锁!
【8月更文挑战第24天】Apache Flink 是一款开源框架,擅长流处理与批处理。流处理专攻实时数据流,支持无限数据流及事件驱动应用,实现数据的连续输入与实时处理。批处理则聚焦于静态数据集,进行一次性处理。两者差异体现在处理方式与应用场景:流处理适合实时性要求高的场景(例如实时监控),而批处理更适用于离线数据分析任务(如数据挖掘)。通过提供的示例代码,读者可以直观理解两种模式的不同之处及其实际应用。
1125 0
|
存储 固态存储 测试技术
优化后,ES 做到了几十亿数据检索 3 秒返回!
优化后,ES 做到了几十亿数据检索 3 秒返回!