当前位置: 首页 > news >正文

什么是系统设计

  每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领域的领跑者。点击订阅,与未来同行! 订阅:https://rengongzhineng.io/

许多系统设计建议反而适得其反。例如,LinkedIn 风格的“你一定没听说过消息队列”的观点似乎专为新人打造;又比如 Twitter 上流行的“如果你在数据库里存布尔值,你就是个糟糕的工程师”的狡猾建议。即便是公认优秀的系统设计书籍,比如《Designing Data‑Intensive Applications》,也不一定能解决大多数工程师在实际中遇到的问题。

在作者看来,什么是系统设计?如果将软件设计比作如何组合代码行,那么系统设计就是如何组装服务。软件设计的基本原语是变量、函数、类等,而系统设计的基本原语则是应用服务器、数据库、缓存、队列、事件总线、代理(proxy)等构件。

在这篇文章中,概括自己关于良好系统设计所知的关键要点,尽管很多具体判断还需依赖经验,这些写作是将能够传达的尽可能写下来。


识别良好设计

良好的系统设计往往毫不起眼:长期无故障运行才是它的标志。如果你总想“嗯,这比预想得简单”,或者“系统这一部分从来不用操心,它就很好”,那就是好设计。反之,夸张、炫技的系统往往掩盖了设计本身的问题:分布式一致性协议、CQRS、事件驱动通信等复杂结构,可能只是用来补偿底层的糟糕决策,如果不是过度设计,就要认真反思。这种复杂设计若非演进而来,只会制造更多问题。


状态与无状态设计

状态是最难处理的软件设计挑战。一旦存储任何持续信息,就要面对复杂的读写协调;而若不存储状态,系统则是“无状态”的。例如,GitHub 内部实现的 PDF 转 HTML 渲染服务就是一个无状态服务。无状态组件可以轻易恢复,例如通过容器的自动重启;但一旦状态组件(如数据库)出现问题,就需要人工干预,如数据格式异常、存储空间耗尽等。

因此,应极力减少系统中的状态组件,集中状态管理于单一服务。多个服务不应直接写同一表,而应通过 API 调用或事件机制,将写入逻辑集中到一个负责写的服务。如果可能,也应尽量统一读取逻辑,但在某些情况下,直接快速读取某个表会比 RPC 调用更轻量、更实用。


数据库设计

状态多,数据库设计就尤为关键:

  • 表结构与索引:表结构应清晰可读;极端灵活(如所有字段都存在 JSON 或 key-value 存储)会将解析逻辑转移到应用层并带来性能负担。根据查询需求创建复合索引,确保高基数字段优先,以提升查效率。索引虽有益,但过多会增加写操作的成本。

  • 访问瓶颈:高并发时,数据库常是瓶颈。避免在应用中拼接多个查询,而应通过 JOIN 等方式让数据库完成更多逻辑处理。若 ORM 内部循环触发多次查询,就会引发严重性能问题。在少数复杂查询中,将一个查询拆为多个简化查询,有时在数据库执行效率上更优。

  • 读写分离:尽量让读请求落在数据库副本,减少主写节点负担,除非对一致性要求极高(副本有延迟)。在更新记录后若马上使用,可先将数据保存在内存而不再立刻查询,规避副本同步延迟问题。

  • 写入高峰处理:写操作和事务更容易压垮数据库。若服务存在批量导入等需求,应实现节流机制,避免瞬间大量请求导致系统拥塞崩溃。


快速操作 与 慢操作的分离

响应用户请求时,应尽可能快;但是某些操作(如 PDF 转 HTML)本身耗时较长。推荐做法是:先处理用户的关键部分,比如只渲染 PDF 的第一页输出,其他页面通过后台任务异步生成。

后台任务 是系统设计的重要原语。标准架构由队列(如 Redis)与任务执行器组成。通过将 {job_name, params} 入队来提交任务,任务执行器从队列读取并执行;也可定时调度执行(用于清理、报表生成等)。这是处理耗时操作的常用路径。

如果任务计划时间较远(如延迟一个月),不应使用 Redis 队列,这样不可靠且难以查询。此类场景可使用数据库持久表,设置参数列与执行时间戳字段,然后每日调度扫描执行。


缓存机制

当某些操作重复且耗时时(如多用户调用计费 API 获取当前价格),频繁请求会影响性能和成本,此时引入缓存是常见解决方案。缓存可放在应用内存,也可使用共享缓存系统,如 Redis 或 Memcached。

但缓存带来状态性和一致性问题。不要在未优化查询时匆忙缓存,先考虑为数据库查询添加索引或其他优化措施,避免缓存“必需性”。对于体积大或长期存储的结果(如大客户周报),可结合定时任务与文档存储(如 S3)作为持久缓存。


事件系统

除了缓存与后台任务,大多数技术公司还会部署事件总线(如 Kafka)。事件本质上是“某件事情发生了”的消息,而不是执行任务指令。例如“新账户创建”事件可以触发发送欢迎邮件、滥用扫描、账户初始化等不同处理流程。

事件系统适用于生产者无需关心消费者行为、或者事件量大但对时效性要求较低的情况。否则直接使用 API 调用往往更清晰、便于排查,因为所有日志集中可见。


推送 vs 拉取

当数据需要从一个地方传递给多个接收方时,可通过拉取或推送方式:

  • 拉取:客户端主动获取数据。这虽然直观,但可能导致频繁拉取重复数据(例如邮箱刷新行为)。

  • 推送:服务方在数据变更时主动下发更新,例如 GMail 的新邮件即时推送。

后台服务间推送数据往往更高效,尤其是接收方数量有限。若服务规模巨大(如服务百万用户),推送与拉取都需横向扩展:推送模式需消息队列与多个处理节点;拉取模式则需高性能缓存层支持高频读取。


热路径设计

系统中路径很多,但真正关键的是“热路径”——处理量最大、最关键的路径。在按使用量计费系统中,决定是否计费与计算用户行为的模块,就属于热路径。这部分设计方案有限,且极易因错误导致灾难级后果。相比之下,错误设置页面虽糟糕,但影响范围较小。


日志 与 指标监控

如何确定系统是否有问题?作者建议在出错路径上广泛记录日志,例如记录返回 422 的具体判断条件、计费决策的原因等。这虽然增加代码冗余,但在排查客户问题时极有帮助。

还应监控系统运行状态,包括:CPU/内存、队列长度、请求/任务的均时延、p95、p99 等关键性能指标。尤其是 p95/p99 延迟,虽少量请求慢,但往往来自重要客户,影响极大,平均值不足以反映问题严重性。


熔断、重试 与 优雅降级

系统失败时如何处理?重试机制需谨慎,避免盲目重试导致下游系统过载。应使用熔断器(circuit breaker)机制:连续失败时暂缓请求,让服务恢复。同时,写操作重试风险更大,需使用幂等性键(idempotency key)避免重复处理。

还需明确降级策略。例如,当用于限流的 Redis 不可用时,是“开放”(fail open)让请求通过,还是“关闭”(fail closed)拒绝请求,要根据功能区分:限流应开放,而认证功能必须关闭以防止权限泄漏。其他功能则需权衡设计。


总结:匠心设计来自朴素架构

文章最后强调,许多系统设计问题如微服务拆分、容器 vs VM、链路追踪、API 设计均未深入讨论。原因包括这些问题的重要性有限、或过于明显、不便简述。作者强调:优秀的系统设计不是靠花哨技巧,而是将成熟、稳定的组件恰当地组合。大型公司往往已有通用组件(事件总线、缓存服务等)可用,真正优质的系统设计看起来像“什么都没做”,但日久无恙运行。真正需要复杂、自创数据结构的场景极少,而日常运维的永远是朴素、稳健的“无趣”设计。

http://www.lryc.cn/news/625096.html

相关文章:

  • 电竞酒店和高校宿舍对AI云电竞游戏盒子的需求有什么不同?
  • 从虚拟到现实:数字孪生赋能智能制造
  • docker部署flask并迁移至内网
  • 前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
  • css word-pass
  • 强化学习-CH2 状态价值和贝尔曼等式
  • 【新手易混】find 命令中 -perm 选项的知识点
  • Unity2022打包安卓报错的奇葩问题
  • 云原生俱乐部-docker知识点归纳(1)
  • 2-4〔O҉S҉C҉P҉ ◈ 研记〕❘ 漏洞扫描▸AWVS(WEB扫描)
  • PyTorch数据处理工具箱详解|深入理解torchvision与torch.utils.data
  • 嵌入式设备Lwip协议栈实现功能
  • 28、企业安防管理(Security)体系构建:从生产安全到日常安保的全方位防护
  • 如何将 LM Studio 与 ONLYOFFICE 结合使用,实现安全的本地 AI 文档编辑
  • 【完整源码+数据集+部署教程】海洋垃圾与生物识别系统源码和数据集:改进yolo11-RVB
  • 遥感机器学习入门实战教程 | Sklearn 案例②:PCA + k-NN 分类与评估
  • 在开发后端API的时候,哪些中间件比较实用
  • 【音视频】ISP能力
  • python实现pdfs合并
  • [矩阵置零]
  • 【HarmonyOS】应用设置全屏和安全区域详解
  • C++/Java双平台表单校验实战:合法性+长度+防重复+Tab顺序四重守卫
  • html页面打水印效果
  • Android使用Kotlin协程+Flow实现打字机效果
  • 【React Hooks】封装的艺术:如何编写高质量的 React 自-定义 Hooks
  • 构建者设计模式 Builder
  • 开源im即时通讯软件开发社交系统全解析:安全可控、功能全面的社交解决方案
  • 使用 Zed + Qwen Code 搭建轻量化 AI 编程 IDE
  • FlycoTabLayout CommonTabLayout 支持Tab选中字体变大 选中tab的加粗效果首次无效的bug
  • Redis-缓存-穿透-布隆过滤器