成为工程师 - 如何提升系统写性能(下)

简介: 成为工程师 - 如何提升系统写性能(下)

今日内容




今天我们接着上一篇文章的内容。继续来讲如何提升【写性能】。


下面这张图是我们上次给出关于提升写性能的概览图:



打钩的部分是已经在上一篇文章说讲完了的。今天,我们把剩下来的四种方式给讲完。他们分别是【异步法】【批量插入】【文件法】和【缓存法】。


01使用优化 - 异步法


异步法,顾名思义就是:将同步的过程转换为异步的过程


这种转换的作用在于:将一个很长的同步过程拆成一个或多个步骤,通过类似消息管道进行串联。同时也利用消息管道的重发能力进行补偿。


一个标准的异步化过程如下图这样:



大家跟着这个图的序号看一遍,这个图中显示了两个过程:


第一个过程:将收到的请求写入queue中,然后返回成功。


第二个过程:从queue中消费消息,继而进行后面的写动作。


这里的核心是:使用queue来缓冲所有的写请求


但是这里有个问题。因为第一步已经返回了用户成功,但是queue中的消息可能存在丢失、溢出、消费过慢的问题。这就导致了用户看到的结果和实际情况不一致。



那我们要怎么解决这个问题呢?我们可以使用下图这种方案来进行优化。



一样,大家跟着这个图中的序号看一遍。这个图和上一个图的区别在于两点。


第一,引入了一个cache。当我们把消息写到消息管道中后,我们就用cache记录一下他的状态。然后在这个消息真正被消费时,从缓存中删除这个状态。


第二,用户的第一阶段动作做完后,返回用户受理状态,而非成功。


用户可以发起请求状态的查询。我们可以根据cache中的情况,给用户返回状态。cache中如果还有,就说明请求处理中,cache中如果没有,就说明请求处理完了。


一般来说,写入动作都会伴有单据的生成。如果你的单据查询量不大的话,也可以不用引入cache。收到用户的查询请求后,直接查询数据库中单据状态返回。


02使用优化 - 批量插入


顾名思义,批量插入的含义就是将原来多个动作一起执行。就像下图这样:



那批量为什么会快呢?很多人没有思考过这个问题。


你想,虽然是把多个请求放在一起请求。但传输的数据量并没有变少,数据库处理的数据也没有变少。为什么批量就变快了呢?


批量的变快的原因是:


第一,可以减少加锁的次数。本来1个请求加1次锁,现在100个请求加1次锁。


第二,批量更新往往可以用上数据库对批量数据操作的优化

那如何实现单笔变批量?


01内存聚合


第一种方式,我把它称之为内存聚合。我们来看下面这张图。



上图中,多个请求过来,写到内存的queue中。然后每个线程循环检查自己的状态。系统中有另一个模块,定时从queue中捞取批量请求一起执行。


这种方式看着很有设计感,但其实并不常用。


因为这种设计有一定的复杂度。并且“请求不释放”、“queue中消息不消费”、“反复轮询请求状态”都容易给系统带来问题。


我把这个方案放在这里,主要是和大家探讨一种技术设计思路,但并不推荐使用。不过话说回来,在操作系统中常能见到这样的设计,所以操作系统真的很厉害。


02流水聚合


流水聚合法简单说就是:将需要处理的请求先入库,然后再批量捞取执行


我们看下面这个图:



这个图中,我们先把请求的流水落库,然后通过定时任务捞取所有的流水,并在内存中统一计算结果,然后更新数据库,标记原流水状态,结束。


敏感的同学一定已经发现,这个方案中也使用了异步的思想。只是在异步的思想上又叠加了批量处理的思想。


这种方案最大的好处就是:写流水是不锁库。但劣势就是:数据更新较慢,会有时延


但这里有个问题,如果写入请求的并发量实在太大了。DB就是写请求也扛不住,怎么办呢?


03使用优化 - 文件法


如果数据库扛不住写入请求,那就换个思路,不用DB了,咱们直接写文件。


文件法和批量流水本质一样,都是使用异步的思路。也分为上下两个阶段。


我们先看第一个阶段:写文件



一阶段做的事情非常简单,就是将请求进来的内容记录到文件中。


接下来我们看二阶段。二阶段其实也非常简单,就像下图这样。



二阶段就是:定时任务起来,服务去读取日志信息,然后执行写入动作


但这里有个问题。如果文件实在太大的话,这样的执行方式非常的低效。你想,用文件的方式就说明数据量一定小不了。


所以,我们更典型的方式会使用如下这种:



大家务必跟着我的序号来看


第一阶段,会有拆分服务去读取大文件,并把它拆分成小文件存储到分布式文件系统上。然后把分片文件的写入地址等塞到queue里去。


第二阶段,写入服务从queue里读取文件信息,然后处理一个一个小文件。解析其中的内容,并写到数据库里去。


这里的重点是:第一个阶段只能由单个线程去拆文件,以防止文件拆重。第二个阶段则可以用很多的服务器去一起捞取分片文件处理,以此来提高处理速度


这是大厂处理文件的典型方式。熟悉大数据解决方的同学一定也会觉得很熟悉。没错,hadoop也是这么处理大文件解析的。


这背后,其实是使用了经典的【分而治之】的思想。


04使用优化 - 缓存法


在上一篇文章中我有提到,写性能比读性能难的原因之一是:不能使用缓存。这是我故意留下的一个“错误”。


今天我们提到,缓存中间件也配有持久化方案。只是他的持久化方案不能保证数据完全安全。

但是,我们所有的场景都需要保证数据一点都不能丢吗?


如果有场景可以容忍一定程度的数据丢失,那缓存来当做数据库使用其实是可以的。比如点赞数、弹幕数、播放数、在线人数等这样的计数类需求。


这类需求往往请求量可能很大,但可以容忍在极端情况下有一小部分计数值的丢失。


那既然是把缓存当做DB来用。我们就要看看怎么来做持久化。


持久化的作用主要有两种:一个是故障的恢复,另一个是数据保存


对于“故障恢复”来说,如果没有特别的要求,可以就依赖缓存中间件自己提供的能力。

对于“数据保存”来说,如果你有这个容量,持续放在缓存中也是可以的,但如果缓存容量不够,一些较冷的数据想放在硬盘上。你就需要定时的去把缓存数据刷到数据库中,并且在需要的时候再实时刷进缓存。


下面是一张整体的示意图:



05性能小结


到这里,我们把读写性能都讲完了。


我们讲了很多的内容,但比这些内容更重要的是背后的设计思想。在这里我就和大家一起再来梳理一下。


我们直接来看下面我画的这张图。



【避免重复计算】重复的活儿不重复干,用空间换时间。

【减少无谓步骤】只为重要的事情付出时间。

【避免过程阻塞】能不等就不等,异步是个宝。

【引入更多资源】找人来干活,死磕不是办法。

【数据职责分离】只供读还是只供写,供全局还是供局部。

【合理技术选型】审时度势,先做选择。

【配合产品方案】产研是一家,问题一起扛。


今日小结


今天我们继续讲了【写性能】的提升方式。其中包括:“使用异步的方式”、“使用批量的方式”、“使用文件的方式”以及“使用缓存的方式”。

相关文章
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
223 10
|
存储 自然语言处理 算法
ES高频面试问题:一张图带你读懂 Elasticsearch 中“正排索引(正向索引)”和“倒排索引(反向索引)”区别
ES高频面试问题:一张图带你读懂 Elasticsearch 中“正排索引(正向索引)”和“倒排索引(反向索引)”区别
ES高频面试问题:一张图带你读懂 Elasticsearch 中“正排索引(正向索引)”和“倒排索引(反向索引)”区别
|
10月前
|
监控 搜索推荐 API
淘宝店铺详情API接口的开发、应用与收益
淘宝开放平台提供了丰富的API接口,帮助开发者获取海量的商品和店铺数据。本文聚焦于淘宝店铺详情API接口的开发、应用及收益。首先,开发者需注册账号并创建应用以获取API密钥。接着,通过阅读接口文档,使用Python等语言编写代码调用API,处理返回的数据。该接口广泛应用于竞品分析、数据分析、价格监控、个性化推荐等领域,为开发者带来提高用户体验、降低运营成本、增加收入等多方面收益。同时,开发者需注意遵守法律法规、请求频率限制及数据安全等问题,确保合法合规地使用接口资源。
272 4
|
10月前
|
自然语言处理 搜索推荐 数据挖掘
淘宝商品描述 API 接口的开发、应用与收益
淘宝商品描述API接口的开发与应用涵盖注册成为开发者、了解API规范、选择开发工具及语言(如Python)和实现代码调用。该接口可用于优化电商平台商品展示、同步数据、竞品分析、智能客服及个性化推荐,从而提高销售转化率、降低运营成本并拓展业务机会。通过自动化处理和数据分析,企业能更精准地满足消费者需求,提升竞争力。
219 9
|
12月前
|
IDE PHP 开发工具
除了Xdebug,还有哪些常用的PHP调试工具?
这些调试工具各有特点,开发者可以根据自己的需求和习惯选择适合的工具。在实际开发中,结合多种工具的使用往往能够更全面、更深入地进行调试,提高开发效率和代码质量。同时,随着技术的不断发展,新的调试工具也在不断涌现,开发者需要保持学习和关注,以便及时掌握最新的调试技术和工具。
357 1
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
388 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
|
10月前
|
存储 缓存 安全
网安入门之PHP后端基础
PHP 是一种服务器端脚本语言,广泛用于动态网站和Web应用程序开发。其文件扩展名为`.php`,支持嵌入HTML、CSS和JavaScript。PHP代码由Web服务器解析后返回给浏览器。PHP是弱类型语言,变量以`$`开头,支持字符串、整数、浮点数、布尔值、数组、对象等类型。PHP具有跨平台、开源、丰富的扩展库等特点。常用超全局变量如`$_GET`、`$_POST`、`$_SESSION`等处理用户输入和会话数据。HTTP请求方法GET和POST在数据传输方式、长度限制、安全性等方面有显著差异。
网安入门之PHP后端基础
|
10月前
|
前端开发 Java 程序员
2025年了,PHP 还是“世界上最好的语言”吗?
“PHP是全世界最好的语言”源自2001年PHP官方文档,本为积极评价,后因PHP性能、安全等问题成为技术圈知名梗。Ruby调侃自己是程序员最好的朋友,其他语言如Go、Java、Python则低调介绍优势。前端CSS预处理语言Sass高调自称最成熟强大,Less则低调表示仅比CSS多一点。2025年TIOBE指数显示,PHP已跌至13名,Python位居第一。尽管PHP难回巅峰,但其早期辉煌仍值得怀念。
547 3
|
11月前
|
设计模式 存储 缓存
前端必须掌握的设计模式——策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,旨在将多分支复杂逻辑解耦。每个分支类只关心自身实现,无需处理策略切换。它避免了大量if-else或switch-case代码,符合开闭原则。常见应用场景包括表单验证、风格切换和缓存调度等。通过定义接口和上下文类,策略模式实现了灵活的逻辑分离与扩展。例如,在国际化需求中,可根据语言切换不同的词条包,使代码更加简洁优雅。总结来说,策略模式简化了多条件判断,提升了代码的可维护性和扩展性。
|
12月前
|
JSON 数据挖掘 API
如何使用PHP开发1688商品详情API接口
本文详细介绍了如何使用PHP开发1688商品详情API接口,涵盖从注册账号、申请权限、配置环境到代码实现的全过程。通过设置请求头、参数及生成签名,利用cURL或GuzzleHttp库发送请求并处理响应,最终实现商品详情数据的获取与应用,助力电商发展。
151 1