- 文集信息
- 目录大纲
- 最新文档
- 知识宇宙
文集详情
文集导读
系统设计 101
使用视觉对象和简单术语解释复杂系统。
无论您是在准备系统设计面试,还是只想了解系统在表面下是如何工作的,我们都希望此存储库能帮助您实现这一目标。
目录
通信协议
体系结构样式定义应用程序编程接口 (API) 的不同组件如何相互交互。因此,它们通过提供设计和构建 API 的标准方法,确保效率、可靠性以及与其他系统的轻松集成。以下是最常用的样式:
-
肥皂:
成熟、全面、基于 XML
最适合企业应用程序
-
宁静:
流行的、易于实现的 HTTP 方法
Web 服务的理想选择
-
GraphQL 中:
查询语言、请求特定数据
减少网络开销,加快响应速度
-
gRPC 中:
现代、高性能的 Protocol Buffers
适用于微服务架构
-
WebSocket 的 URL:
实时、双向、持久连接
非常适合低延迟数据交换
-
Webhook 的:
事件驱动、HTTP 回调、异步
在事件发生时通知系统
REST API 与 GraphQL
在 API 设计方面,REST 和 GraphQL 各有优缺点。
下图显示了 REST 和 GraphQL 之间的快速比较。
休息
- 使用标准 HTTP 方法(如 GET、POST、PUT、DELETE )进行 CRUD 操作。
- 当您需要在单独的服务/应用程序之间使用简单、统一的接口时,效果很好。
- 缓存策略很容易实现。
- 缺点是它可能需要多次往返才能从不同的端点收集相关数据。
图形QL
- 为客户提供单个终端节点,以精确查询所需的数据。
- 客户端指定嵌套查询中所需的确切字段,服务器返回仅包含这些字段的优化负载。
- 支持用于修改数据的 Mutations 和用于实时通知的 Subscriptions。
- 非常适合聚合来自多个来源的数据,并很好地满足快速发展的前端需求。
- 但是,它将复杂性转移到客户端,并且如果没有得到适当的保护,可能会允许滥用查询
- 缓存策略可能比 REST 更复杂。
REST 和 GraphQL 之间的最佳选择取决于应用程序和开发团队的具体要求。GraphQL 非常适合复杂或经常变化的前端需求,而 REST 则适合首选简单且一致的合同的应用程序。
这两种 API 方法都不是灵丹妙药。仔细评估要求和权衡对于选择正确的样式很重要。REST 和 GraphQL 都是公开数据和为现代应用程序提供支持的有效选项。
gRPC 的工作原理是什么?
RPC(Remote Procedure Call,远程过程调用)之所以称为“远程”,是因为在微服务架构下,当服务部署到不同的服务器时,它可以实现远程服务之间的通信。从用户的角度来看,它的作用类似于本地函数调用。
下图说明了 gRPC 的整体数据流。
第 1 步:从客户端进行 REST 调用。请求正文通常为 JSON 格式。
第 2 步 - 第 4 步:订单服务(gRPC 客户端)接收 REST 调用,对其进行转换,然后对支付服务进行 RPC 调用。gRPC 将客户端存根编码为二进制格式,并将其发送到低级传输层。
第 5 步:gRPC 通过 HTTP2 通过网络发送数据包。由于二进制编码和网络优化,据说 gRPC 的速度比 JSON 快 5 倍。
步骤 6 - 8:支付服务(gRPC 服务器)从网络接收数据包,对其进行解码,然后调用服务器应用程序。
步骤 9 - 11:结果从服务器应用程序返回,并被编码并发送到传输层。
步骤 12 - 14:订单服务接收数据包,对其进行解码,并将结果发送到客户端应用程序。
什么是 Webhook?
下图显示了轮询和 Webhook 之间的比较。
假设我们运行一个电子商务网站。客户端通过 API 网关将订单发送到订单服务,该网关将转到支付服务进行支付交易。然后,支付服务与外部支付服务提供商 (PSP) 通信以完成交易。
有两种方法可以处理与外部 PSP 的通信。
1. 短轮询
向 PSP 发送付款请求后,支付服务不断询问 PSP 有关付款状态的信息。经过几轮后,PSP 终于以状态返回。
短轮询有两个缺点:
- 状态的持续轮询需要来自支付服务的资源。
- 外部服务直接与支付服务通信,从而产生安全漏洞。
2. 网络钩子
我们可以向外部服务注册一个 webhook。这意味着:当您有请求的更新时,通过某个 URL 给我回电。PSP 完成处理后,将调用 HTTP 请求来更新付款状态。
这样,编程范式就改变了,支付服务不再需要浪费资源来轮询支付状态。
如果 PSP 从未回电怎么办?我们可以设置一个家政工作来每小时检查一次付款状态。
Webhook 通常称为反向 API 或推送 API,因为服务器向客户端发送 HTTP 请求。我们在使用 webhook 时需要注意 3 件事:
- 我们需要为外部服务设计一个合适的 API。
- 出于安全原因,我们需要在 API 网关中设置适当的规则。
- 我们需要在外部服务中注册正确的 URL。
如何提高 API 性能?
下图显示了提高 API 性能的 5 个常见技巧。
分页
当结果的大小较大时,这是一种常见的优化。结果是流回客户端以提高服务响应能力。
异步日志记录
同步日志记录处理每个调用的磁盘,并且可能会降低系统速度。异步日志记录首先将日志发送到无锁缓冲区,然后立即返回。日志将定期刷新到磁盘。这大大降低了 I/O 开销。
缓存
我们可以将经常访问的数据存储到缓存中。客户端可以先查询缓存,而不是直接访问数据库。如果存在缓存未命中,客户端可以从数据库中查询。Redis 等缓存将数据存储在内存中,因此数据访问比数据库快得多。
有效载荷压缩
可以使用 gzip 等对请求和响应进行压缩,以便传输的数据大小要小得多。这加快了上传和下载的速度。
连接池
在访问资源时,我们经常需要从数据库中加载数据。打开关闭的数据库连接会增加大量开销。因此,我们应该通过一个开放连接池连接到数据库。连接池负责管理连接生命周期。
HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC)
每一代 HTTP 解决了什么问题?
下图说明了主要功能。
-
HTTP 1.0 于 1996 年完成并完整记录。对同一服务器的每个请求都需要单独的 TCP 连接。
-
HTTP 1.1 于 1997 年发布。TCP 连接可以保持开放状态以供重用(持久连接),但它并不能解决 HOL(队头)阻塞问题。
HOL 阻塞 - 当浏览器中允许的并行请求数用完时,后续请求需要等待前一个请求完成。
-
HTTP 2.0 于 2015 年发布。它通过请求多路复用解决了 HOL 问题,从而消除了应用程序层的 HOL 阻塞,但 HOL 仍然存在于传输 (TCP) 层。
如图所示,HTTP 2.0 引入了 HTTP“流”的概念:一种允许将不同的 HTTP 交换多路复用到同一 TCP 连接上的抽象。每个流不需要按顺序发送。
-
HTTP 3.0 初稿于 2020 年发布。它是 HTTP 2.0 的拟议后继者。它使用 QUIC 而不是 TCP 作为底层传输协议,从而消除了传输层中的 HOL 阻塞。
QUIC 基于 UDP。它在传输层将流作为一等公民引入。QUIC 流共享相同的 QUIC 连接,因此不需要额外的握手和缓慢启动来创建新的连接,但 QUIC 流是独立交付的,因此在大多数情况下,影响一个流的丢包不会影响其他流。
SOAP 与 REST 与 GraphQL 与 RPC
下图说明了 API 时间线和 API 样式的比较。
随着时间的推移,不同的 API 架构风格被发布。它们中的每一个都有自己的标准化数据交换模式。
您可以在图中查看每种样式的用例。
代码优先与 API 优先
下图显示了代码优先开发和 API 优先开发之间的区别。为什么我们要考虑 API 优先设计?
- 微服务增加了系统复杂性,我们有单独的服务来服务于系统的不同功能。虽然这种架构有助于解耦和职责分离,但我们需要处理服务之间的各种通信。
最好在编写代码并仔细定义服务的边界之前考虑系统的复杂性。
- 不同的功能团队需要使用相同的语言,专门的功能团队只负责他们自己的组件和服务。建议组织通过 API 设计使用相同的语言。
我们可以在编写代码之前模拟请求和响应以验证 API 设计。
- 提高软件质量和开发人员生产力由于我们已经消除了项目开始时的大部分不确定性,因此整体开发过程更加顺畅,软件质量也大大提高。
开发人员也对这个过程感到满意,因为他们可以专注于功能开发,而不是协商突然的变化。
在项目生命周期结束时出现意外的可能性会降低。
因为我们首先设计了 API,所以可以在开发代码的同时设计测试。在某种程度上,我们在使用 API 优先开发时也有 TDD(测试驱动设计)。
HTTP 状态代码
HTTP 的响应代码分为五类:
信息 (100-199) 成功 (200-299) 重定向 (300-399) 客户端错误 (400-499) 服务器错误 (500-599)
API 网关有什么作用?
下图显示了详细信息。
第 1 步 - 客户端向 API 网关发送 HTTP 请求。
第 2 步 - API 网关解析并验证 HTTP 请求中的属性。
第 3 步 - API 网关执行允许列表/拒绝列表检查。
第 4 步 - API 网关与身份提供商通信以进行身份验证和授权。
步骤 5 - 速率限制规则应用于请求。如果超过限制,则请求将被拒绝。
步骤 6 和 7 – 现在请求已通过基本检查,API 网关通过路径匹配查找要路由到的相关服务。
第 8 步 - API 网关将请求转换为适当的协议,并将其发送到后端微服务。
步骤 9-12:API 网关可以正确处理错误,如果错误需要更长的时间才能恢复(熔断),则进行处理。它还可以利用 ELK (Elastic-Logstash-Kibana) 堆栈进行日志记录和监控。我们有时会在 API 网关中缓存数据。
我们如何设计有效且安全的 API?
下图显示了带有购物车示例的典型 API 设计。
请注意,API 设计不仅仅是 URL 路径设计。大多数时候,我们需要选择适当的资源名称、标识符和路径模式。在 API 网关中设计正确的 HTTP 标头字段或设计有效的速率限制规则同样重要。
TCP/IP 封装
如何通过网络发送数据?为什么 OSI 模型中需要这么多层?
下图显示了在通过网络传输时如何封装和解封装数据。
步骤 1:当设备 A 通过 HTTP 协议通过网络向设备 B 发送数据时,首先在应用层添加一个 HTTP 头。
第 2 步: 然后将 TCP 或 UDP 标头添加到数据中。它在传输层封装到 TCP 分段中。标头包含源端口、目标端口和序列号。
第 3 步:然后在网络层使用 IP 报头封装分段。IP 标头包含源/目标 IP 地址。
步骤 4:IP 数据报在数据链路层添加 MAC 报头,其中包含源/目标 MAC 地址。
第 5 步:封装的帧被发送到物理层,并以二进制位的形式通过网络发送。
步骤 6-10:当设备 B 从网络接收到比特时,它执行解封装过程,这是对封装过程的反向处理。标头被逐层删除,最终,设备 B 可以读取数据。
我们需要网络模型中的层,因为每个层都专注于自己的职责。每一层都可以依赖 header 进行处理指令,不需要知道最后一层数据的含义。
为什么 Nginx 被称为“反向”代理?
下图显示了正向代理和反向代理之间的区别。
转发代理是位于用户设备和 Internet 之间的服务器。
正向代理通常用于:
- 保护客户端
- 规避浏览限制
- 阻止访问某些内容
反向代理是接受来自客户端的请求,将请求转发到 Web 服务器,并将结果返回给客户端的服务器,就像代理服务器已处理请求一样。
反向代理适用于:
- 保护服务器
- 负载均衡
- 缓存静态内容
- 加密和解密 SSL 通信
常见的负载均衡算法有哪些?
下图显示了 6 种常见算法。
- 静态算法
-
循环赛
客户端请求按顺序发送到不同的服务实例。这些服务通常要求是无状态的。
-
粘性循环
这是对 round-robin 算法的改进。如果 Alice 的第一个请求转到服务 A,则以下请求也会转到服务 A。
-
加权循环
管理员可以为每个服务指定权重。权重较高的 Broker 处理的请求比其他 Broker Advisor Advisor Advisor Advisor S Advisor S 的请求更多。
-
散 列
此算法对传入请求的 IP 或 URL 应用哈希函数。根据哈希函数结果将请求路由到相关实例。
- 动态算法
-
最少的连接
将新请求发送到并发连接最少的服务实例。
-
最短响应时间
将新请求发送到响应时间最快的服务实例。
URL、URI、URN - 您知道其中的区别吗?
下图显示了 URL、URI 和 URN 的比较。
- URI
URI 代表统一资源标识符。它标识 Web 上的逻辑或物理资源。URL 和 URN 是 URI 的子类型。URL 查找资源,而 URN 命名资源。
URI 由以下部分组成: scheme:[//authority]path[?query][#fragment]
- 网址
URL 代表统一资源定位器,这是 HTTP 的关键概念。它是 Web 上唯一资源的地址。它可以与 FTP 和 JDBC 等其他协议一起使用。
- 瓮
URN 代表统一资源名称。它使用 urn 方案。URN 不能用于查找资源。图中给出的一个简单示例由命名空间和特定于命名空间的字符串组成。
如果您想了解有关该主题的更多详细信息,我建议您阅读 W3C 的澄清。
CI/CD
简单解释 CI/CD 管道
第 1 部分 - 使用 CI/CD 的 SDLC
软件开发生命周期 (SDLC) 包括几个关键阶段:开发、测试、部署和维护。CI/CD 可以自动化和集成这些阶段,以实现更快、更可靠的发布。
当代码被推送到 git 存储库时,它会触发自动化的构建和测试过程。运行端到端 (e2e) 测试用例以验证代码。如果测试通过,代码可以自动部署到暂存/生产环境。如果发现问题,则代码将发送回开发部门进行错误修复。这种自动化为开发人员提供了快速反馈,并降低了生产中出现错误的风险。
第 2 部分 - CI 和 CD 之间的区别
持续集成 (CI) 可自动执行构建、测试和合并过程。每当提交代码时,它都会运行测试,以便及早发现集成问题。这鼓励了频繁的代码提交和快速反馈。
持续交付 (CD) 可自动执行基础架构更改和部署等发布流程。它确保可以通过自动化工作流程随时可靠地发布软件。CD 还可以自动执行生产部署之前所需的手动测试和批准步骤。
第 3 部分 - CI/CD 管道
典型的 CI/CD 管道有几个相互连接的阶段:
- 开发人员将代码更改提交到源代码管理
- CI 服务器检测更改并触发构建
- 代码经过编译和测试(单元、集成测试)
- 向开发人员报告的测试结果
- 成功后,构件将部署到暂存环境
- 在发布之前,可以在暂存时进行进一步测试
- CD 系统将批准的更改部署到生产环境中
Netflix 技术堆栈(CI/CD 管道)
规划:Netflix 工程团队使用 JIRA 进行规划,使用 Confluence 进行文档编制。
编码:Java 是后端服务的主要编程语言,而其他语言则用于不同的用例。
构建:Gradle 主要用于构建,构建 Gradle 插件以支持各种用例。
打包:软件包和依赖项打包到 Amazon 系统映像 (AMI) 中以供发布。
测试:测试强调生产文化对构建混沌工具的关注。
部署:Netflix 使用其自建的 Spinnaker 进行灰度部署。
监控:监控指标集中在 Atlas 中,使用 Kayenta 检测异常。
事件报告:根据优先级分派事件,并使用 PagerDuty 进行事件处理。
架构模式
MVC、MVP、MVVM、MVVM-C 和 VIPER
这些架构模式是应用程序开发中最常用的模式之一,无论是在 iOS 还是 Android 平台上。开发人员引入它们是为了克服早期模式的局限性。那么,它们有何不同呢?
- MVC 是最古老的模式,其历史可以追溯到近 50 年前
- 每个模式都有一个 “视图” (V) 负责显示内容和接收用户输入
- 大多数模式都包含用于管理业务数据的 “模型” (M)
- “Controller”、“presenter” 和 “view-model” 是在视图和模型(VIPER 模式中的 “entity”) 之间进行调解的转换器
每个开发人员都应该知道的 18 个关键设计模式
模式是常见设计问题的可重用解决方案,可实现更顺畅、更高效的开发过程。它们是构建更好的软件结构的蓝图。以下是一些最流行的模式:
- 抽象工厂:Family Creator - 创建相关项的组。
- 生成器:Lego Master - 逐步构建对象,将创建和外观分开。
- 原型:克隆制作工具 - 创建完全准备好的示例的副本。
- Singleton: One and Only - 只有一个实例的特殊类。
- 适配器:通用插头 - 连接具有不同接口的事物。
- Bridge:函数连接器 - 将对象的工作方式与其功能联系起来。
- 复合:树构建器 - 形成简单和复杂零件的树状结构。
- Decorator: Customizer - 在不更改对象核心的情况下向对象添加功能。
- Facade: One-Stop-Shop - 代表具有单一简化界面的整个系统。
- Flyweight:节省空间 - 高效共享可重复使用的小物品。
- Proxy: Stand-In Actor (代理:替身角色) - 表示另一个对象,控制访问或操作。
- 责任链:请求中继 - 通过对象链传递请求,直到得到处理。
- 命令:任务包装器 - 将请求转换为对象,以备操作。
- Iterator: Collection Explorer - 逐个访问集合中的元素。
- Mediator: Communication Hub - 简化不同类之间的交互。
- Memento: Time Capsule - 捕获和恢复对象的状态。
- Observer: News Broadcaster - 通知类其他对象中的更改。
- 访客:熟练访客 - 向类添加新操作而不更改类。
数据库
云服务中不同数据库的精美备忘单
为您的项目选择合适的数据库是一项复杂的任务。许多数据库选项(每个选项都适用于不同的使用案例)可能很快导致决策疲劳。
我们希望此备忘单提供高级指导,以确定符合您的项目需求并避免潜在陷阱的正确服务。
注意:Google 的数据库用例文档有限。尽管我们尽最大努力查看可用的内容并得出最佳选项,但某些条目可能需要更准确。
为数据库提供支持的 8 种数据结构
答案会因您的使用案例而异。数据可以在内存或磁盘上建立索引。同样,数据格式也各不相同,例如数字、字符串、地理坐标等。系统可能写入繁重或读取繁重。所有这些因素都会影响您对数据库索引格式的选择。
以下是一些用于索引数据的最流行的数据结构:
- Skiplist:一种常见的内存中索引类型。用于 Redis
- 哈希索引:“Map”数据结构(或“Collection”)的一种非常常见的实现
- SSTable:不可变的磁盘 “Map” 实现
- LSM 树:Skiplist + SSTable。高写入吞吐量
- B 树:基于磁盘的解决方案。一致的读/写性能
- 倒排索引:用于文档索引。用于 Lucene
- 后缀树:用于字符串模式搜索
- R 树:多维搜索,例如查找最近的邻居
SQL 语句在数据库中是如何执行的?
下图显示了该过程。请注意,不同数据库的架构是不同的,该图演示了一些常见的设计。
第 1 步 - 通过传输层协议(例如 TCP)将 SQL 语句发送到数据库。
第 2 步 - 将 SQL 语句发送到命令解析器,在那里进行语法和语义分析,然后生成查询树。
第 3 步 - 将查询树发送到优化器。优化器创建执行计划。
第 4 步 - 将执行计划发送给执行程序。执行程序从执行中检索数据。
第 5 步 — 访问方法提供执行所需的数据获取逻辑,从存储引擎检索数据。
第 6 步 - 访问方法确定 SQL 语句是否为只读。如果查询是只读的(SELECT 语句),则会将其传递给缓冲区管理器进行进一步处理。缓冲区管理器 在高速缓存或数据文件中查找数据。
第 7 步 - 如果语句是 UPDATE 或 INSERT,则将其传递给事务管理器进行进一步处理。
第 8 步 — 在事务期间,数据处于锁定模式。这是由 lock manager 保证的。它还确保事务的 ACID 属性。
CAP 定理
CAP 定理是计算机科学中最著名的术语之一,但我敢打赌,不同的开发人员有不同的理解。让我们来看看它是什么以及为什么它会令人困惑。
CAP 定理指出,分布式系统不能同时提供这三种保证中的两种以上。
一致性:一致性意味着所有客户端都同时看到相同的数据,无论它们连接到哪个节点。
可用性:可用性意味着即使某些节点关闭,任何请求数据的客户端也会得到响应。
Partition Tolerance:分区表示两个节点之间的通信中断。分区容错性意味着无论存在网络分区,系统仍可继续运行。
“2 of 3”公式可能很有用,但这种简化可能会产生误导。
-
选择数据库并不容易。仅仅根据 CAP 定理来证明我们的选择是不够的。例如,公司不会仅仅因为它是一个 AP 系统就选择 Cassandra 用于聊天应用程序。有一系列良好的特性使 Cassandra 成为存储聊天消息的理想选择。我们需要更深入地挖掘。
-
“CAP 只禁止设计空间的一小部分:在存在分区的情况下实现完美的可用性和一致性,这种情况很少见”。引自论文:CAP 十二年后:“规则”是如何改变的。
-
该定理是大约 100% 的可用性和一致性。更现实的讨论是在没有网络分区时延迟和一致性之间的权衡。有关更多详细信息,请参阅 PACELC 定理。
CAP 定理真的有用吗?
我认为它仍然很有用,因为它让我们对一系列权衡讨论敞开心扉,但这只是故事的一部分。在选择合适的数据库时,我们需要更深入地挖掘。
内存和存储的类型
可视化 SQL 查询
SQL 语句由数据库系统分几个步骤执行,包括:
- 解析 SQL 语句并检查其有效性
- 将 SQL 转换为内部表示形式,例如关系代数
- 优化内部表示并创建利用索引信息的执行计划
- 执行计划并返回结果
SQL 的执行非常复杂,涉及许多注意事项,例如:
- 索引和缓存的使用
- 表联接的顺序
- 并发控制
- 交易管理
SQL 语言
1986 年,SQL(结构化查询语言)成为标准。在接下来的 40 年里,它成为关系数据库管理系统的主导语言。阅读最新标准 (ANSI SQL 2016) 可能非常耗时。我该如何学习它?
SQL 语言有 5 个组成部分:
- DDL:数据定义语言,例如 CREATE、ALTER、DROP
- DQL:数据查询语言,如 SELECT
- DML:数据操作语言,例如 INSERT、UPDATE、DELETE
- DCL:数据控制语言,如 GRANT、REVOKE
- TCL:事务控制语言,如 COMMIT、ROLLBACK
对于后端工程师,您可能需要了解大部分内容。作为数据分析师,您可能需要对 DQL 有很好的了解。选择与您最相关的主题。
缓存
数据缓存在任何地方
此图说明了我们在典型体系结构中缓存数据的位置。
流程中有多个层次。
- 客户端应用程序:浏览器可以缓存 HTTP 响应。我们第一次通过 HTTP 请求数据,并在 HTTP 标头中返回数据并带有过期策略;我们再次请求数据,客户端应用程序首先尝试从浏览器缓存中检索数据。
- CDN:CDN 缓存静态 Web 资源。客户端可以从附近的 CDN 节点检索数据。
- Load Balancer:Load Balancer 也可以缓存资源。
- 消息收发基础设施:消息代理首先将消息存储在磁盘上,然后使用者按照自己的节奏检索消息。根据保留策略,数据将在 Kafka 集群中缓存一段时间。
- 服务:服务中有多个缓存层。如果数据未缓存在 CPU 缓存中,则服务将尝试从内存中检索数据。有时,该服务具有二级缓存,用于在磁盘上存储数据。
- 分布式缓存:Redis 等分布式缓存在内存中保存多个服务的键值对。它提供的读/写性能比数据库好得多。
- 全文搜索:我们有时需要使用全文搜索(如 Elastic Search)进行文档搜索或日志搜索。数据副本也会在搜索引擎中建立索引。
- 数据库:即使在数据库中,我们也有不同级别的缓存:
- WAL(Write-ahead Log):在构建 B 树索引之前,先将数据写入 WAL
- Bufferpool:分配给缓存查询结果的内存区域
- 物化视图:预先计算查询结果并将其存储在数据库表中,以提高查询性能
- Transaction log:记录所有事务和数据库更新
- 复制日志:用于记录数据库集群中的复制状态
为什么 Redis 这么快?
如下图所示,主要有 3 个原因。
- Redis 是基于 RAM 的数据存储。RAM 访问至少比随机磁盘访问快 1000 倍。
- Redis 利用 IO 多路复用和单线程执行循环来提高执行效率。
- Redis 利用了几种高效的低级数据结构。
问:另一种流行的内存存储是 Memcached。你知道 Redis 和 Memcached 之间的区别吗?
您可能已经注意到此图表的样式与我之前的帖子不同。请让我知道你更喜欢哪一个。
如何使用 Redis?
Redis 不仅仅是缓存。
Redis 可用于各种场景,如图所示。
-
会期
我们可以使用 Redis 在不同服务之间共享用户会话数据。
-
缓存
我们可以使用 Redis 来缓存对象或页面,尤其是热点数据。
-
分布式锁
我们可以使用 Redis 字符串在分布式服务之间获取锁。
-
计数器
我们可以计算文章的点赞数或阅读量。
-
速率限制器
我们可以为某些用户 IP 应用速率限制器。
-
全局 ID 生成器
我们可以将 Redis Int 用于全局 ID。
-
购物车
我们可以使用 Redis Hash 来表示购物车中的键值对。
-
计算用户留存率
我们可以使用 Bitmap 来表示用户每天的登录量并计算用户留存率。
-
消息队列
我们可以将 List 用于消息队列。
-
排名
我们可以使用 ZSet 对文章进行排序。
热门缓存策略
设计大型系统通常需要仔细考虑缓存。 以下是经常使用的五种缓存策略。
微服务架构
典型的微服务架构是什么样的?
下图显示了典型的微服务架构。
- Load Balancer:这将在多个后端服务之间分配传入流量。
- CDN(内容交付网络):CDN 是一组地理上分散的服务器,用于保存静态内容以加快交付速度。客户端首先在 CDN 中查找内容,然后进入后端服务。
- API Gateway:处理传入请求并将其路由到相关服务。它与身份提供商和服务发现通信。
- Identity Provider(身份提供商):处理用户的身份验证和授权。
- 服务注册和发现:微服务注册和发现在此组件中进行,API网关在此组件中寻找相关服务进行对话。
- Management:此组件负责监视服务。
- 微服务:微服务在不同的域中设计和部署。每个域都有自己的数据库。API 网关通过 REST API 或其他协议与微服务通信,同一域中的微服务使用 RPC(远程过程调用)相互通信。
微服务的优势:
- 它们可以快速设计、部署和水平扩展。
- 每个域都可以由专门的团队独立维护。
- 因此,可以在每个域中自定义业务需求,并得到更好的支持。
微服务最佳实践
一张图片胜过千言万语:开发微服务的 9 个最佳实践。
在开发微服务时,我们需要遵循以下最佳实践:
- 为每个微服务使用单独的数据存储
- 将代码保持在相似的成熟度级别
- 每个微服务的单独构建
- 为每个微服务分配一个职责
- 部署到容器中
- 设计无状态服务
- 采用域驱动设计
- 设计微前端
- 编排微服务
微服务通常使用什么技术堆栈?
您将在下面找到一个图表,其中显示了用于开发阶段和生产的微服务技术堆栈。
▶️前期生产
- 定义 API - 这在前端和后端之间建立合同。为此,我们可以使用 Postman 或 OpenAPI。
- 开发 - Node.js 或 React 在前端开发中很受欢迎,而 java/python/go 在后端开发中很受欢迎。此外,我们还需要根据 API 定义更改 API 网关中的配置。
- 持续集成 - 用于自动化测试的 JUnit 和 Jenkins。代码打包到 Docker 映像中并部署为微服务。
▶️生产
- NGinx 是负载均衡器的常见选择。Cloudflare 提供 CDN(内容交付网络)。
- API 网关 - 我们可以将 spring boot 用于网关,并使用 Eureka/Zookeeper 进行服务发现。
- 微服务部署在云上。我们有 AWS、Microsoft Azure 或 Google GCP 选项。 缓存和全文搜索 - Redis 是缓存键值对的常见选择。Elasticsearch 用于全文搜索。
- 通信 - 为了让服务相互通信,我们可以使用消息传递基础设施 Kafka 或 RPC。
- 持久性 - 我们可以将 MySQL 或 PostgreSQL 用于关系数据库,将 Amazon S3 用于对象存储。如有必要,我们还可以将 Cassandra 用于宽列存储。
- 管理和监控 - 为了管理如此多的微服务,常见的运营工具包括Prometheus、Elastic Stack和Kubernetes。
为什么 Kafka 速度很快
有许多设计决策有助于 Kafka 的性能。在这篇文章中,我们将重点介绍两个。我们认为这两项的分量最大。
- 第一个是 Kafka 对 Sequential I/O 的依赖。
- 为 Kafka 提供性能优势的第二个设计选择是它对效率的关注:零拷贝原则。
该图说明了数据如何在生产者和使用者之间传输,以及零拷贝的含义。
- 步骤 1.1 - 1.3:创建者将数据写入磁盘
- 第 2 步:消费者读取数据而不进行零拷贝
2.1 数据从磁盘加载到操作系统缓存
2.2 数据从 OS 缓存复制到 Kafka 应用程序
2.3 Kafka 应用程序将数据复制到 socket 缓冲区
2.4 数据从 socket buffer 复制到网卡
2.5 网卡将数据发送给消费者
- 第 3 步:使用者使用零副本读取数据
3.1:数据从磁盘加载到操作系统缓存 3.2 操作系统缓存通过 sendfile() 命令直接将数据复制到网卡中 3.3 网卡向消费者发送数据
零拷贝是在应用程序上下文和内核上下文之间保存多个数据副本的快捷方式。
支付系统
如何学习支付系统?
为什么信用卡被称为“银行最赚钱的产品”?VISA/Mastercard 如何赚钱?
下图显示了信用卡支付流程的经济效益。
1. 持卡人向商家支付 100 美元购买产品。
2. 商家从使用销量较高的信用卡中受益,需要补偿发卡机构和卡组织提供支付服务。收单银行与商家设置一笔费用,称为“商家折扣费”。
3 - 4.收单行保留 0.25 USD 作为收单加价,并向发卡行支付 1.75 USD 作为交换费。商家折扣费应包括交换费。
交换费由卡组织设置,因为每个发卡行与每个商家协商费用的效率较低。
5. 卡组织与每家银行设置卡组织评估和费用,银行每月向卡组织支付其服务费用。例如,VISA 对每次刷卡收取 0.11% 的评估费,外加 0.0195 USD 的使用费。
6. 持卡人向发卡行支付其服务费用。
为什么要赔偿发卡行?
- 即使持卡人未能向发卡行付款,发卡行也会向商家付款。
- 发卡行先向商家付款,然后持卡人向发卡行付款。
- 发行人还有其他运营成本,包括管理客户账户、提供声明、欺诈检测、风险管理、清算和结算等。
当我们在商家的商店刷信用卡时,VISA 是如何运作的?
VISA、Mastercard 和 American Express 充当资金清算和结算的卡网络。收单银行和发卡银行可能 – 而且通常是 – 不同的。如果银行在没有中介的情况下逐一结算交易,则每家银行都必须与所有其他银行结算交易。这是相当低效的。
下图显示了 VISA 在信用卡支付流程中的角色。涉及两个流。当客户刷信用卡时,将发生授权流。当商家想在一天结束时获得资金时,就会发生捕获和结算流程。
- 授权流程
第 0 步:发卡银行向其客户发行信用卡。
第 1 步:持卡人想要购买产品并在商家商店的销售点 (POS) 终端刷信用卡。
第 2 步:POS 终端将交易发送给提供 POS 终端的收单银行。
第 3 步和第 4 步:收单银行将交易发送到卡组织,也称为卡组织。卡组织将交易发送给发卡行进行审批。
步骤 4.1、4.2 和 4.3:如果交易获得批准,发卡行将冻结款项。批准或拒绝将发送回收单行以及 POS 终端。
- 捕获和结算流程
第 1 步和第 2 步:商家想在一天结束时收款,因此他们在 POS 终端上点击“捕获”。交易将批量发送给收单行。收单行将包含发生业务的批处理文件发送到卡组织。
第 3 步:卡组织对从不同收单机构收集的交易进行清算,并将清算文件发送给不同的发卡行。
第 4 步:发卡行确认清算文件的正确性,并将资金转给相关的收单银行。
第 5 步:然后收单银行将钱转入商家的银行。
第 4 步:卡组织清算来自不同收单银行的交易。清算是相互抵消交易净额结算的过程,因此总交易数量减少。
在此过程中,卡组织承担了与每家银行通信的负担,并收取服务费作为回报。
全球支付系统系列(第 1 部分):印度的统一支付接口 (UPI)
什么是 UPI?UPI 是由印度国家支付公司开发的即时实时支付系统。
它占当今印度数字零售交易的 60%。
UPI = 支付加价语言 + 可互操作支付标准
开发运营
DevOps 与 SRE 与 Platform Engineering。有什么区别?
DevOps、SRE 和平台工程的概念出现于不同的时期,并由各种个人和组织开发。
DevOps 作为一个概念是由 Patrick Debois 和 Andrew Shafer 于 2009 年在敏捷会议上提出的。他们试图通过促进协作文化和整个软件开发生命周期的共同责任来弥合软件开发和运营之间的差距。
SRE,即站点可靠性工程,由 Google 在 2000 年代初率先提出,旨在解决管理大规模复杂系统方面的运营挑战。Google 开发了 SRE 实践和工具,例如 Borg 集群管理系统和 Monarch 监控系统,以提高其服务的可靠性和效率。
平台工程是一个较新的概念,它建立在 SRE 工程的基础之上。平台工程的确切起源尚不清楚,但通常将其理解为 DevOps 和 SRE 实践的延伸,其重点是提供支持整个业务视角的全面产品开发平台。
值得注意的是,虽然这些概念出现在不同的时期。它们都与提高软件开发和运营中的协作、自动化和效率的更广泛趋势有关。
什么是 k8s (Kubernetes)?
K8s 是一个容器编排系统。它用于容器部署和管理。它的设计受到 Google 内部系统 Borg 的极大影响。
k8s 集群由一组运行容器化应用程序的工作机器(称为节点)组成。每个集群至少有一个 worker 节点。
worker 节点托管作为应用程序工作负载组件的 Pod。控制平面管理集群中的 worker 节点和 Pod。在生产环境中,控制平面通常跨多台计算机运行,一个集群通常运行多个节点,从而提供容错和高可用性。
- Control Plane 组件
-
API 服务器
API 服务器与 k8s 集群中的所有组件通信。Pod 上的所有操作都是通过与 API 服务器通信来执行的。
-
调度
调度器监视 Pod 工作负载,并在新创建的 Pod 上分配负载。
-
控制器管理器
控制器管理器运行控制器,包括 Node Controller、Job Controller、EndpointSlice Controller 和 ServiceAccount Controller。
-
Etcd
etcd 是一个键值存储,用作 Kubernetes 所有集群数据的后备存储。
- 节点
-
豆荚
Pod 是一组容器,是 k8s 管理的最小单元。Pod 有一个应用于 Pod 中每个容器的 IP 地址。
-
Kubelet
在集群中的每个节点上运行的代理。它确保容器在 Pod 中运行。
-
Kube 代理
Kube-proxy 是在集群中的每个节点上运行的网络代理。它路由从服务进入节点的流量。它将工作请求转发到正确的容器。
Docker 与 Kubernetes。我们应该使用哪一个?
什么是 Docker ?
Docker 是一个开源平台,允许您在隔离的容器中打包、分发和运行应用程序。它专注于容器化,提供封装应用程序及其依赖项的轻量级环境。
什么是 Kubernetes ?
Kubernetes 通常称为 K8s,是一个开源容器编排平台。它提供了一个框架,用于跨节点集群自动部署、扩展和管理容器化应用程序。
两者有何不同?
Docker:Docker 在单个操作系统主机上的单个容器级别运行。
您必须手动管理每个主机,并且为多个相关容器设置网络、安全策略和存储可能很复杂。
Kubernetes:Kubernetes 在集群级别运行。它跨多个主机管理多个容器化应用程序,为负载均衡、扩展和确保应用程序所需状态等任务提供自动化。
简而言之,Docker 专注于容器化和在单个主机上运行容器,而 Kubernetes 则专注于跨主机集群大规模管理和编排容器。
Docker 是如何工作的?
下图显示了 Docker 的架构以及当我们运行 “docker build”、“docker pull” 时它是如何工作的 和 “docker run” 的 API 操作。
Docker 架构中有 3 个组件:
-
Docker 客户端
docker 客户端与 Docker 守护程序通信。
-
Docker 主机
Docker 守护程序侦听 Docker API 请求并管理 Docker 对象,例如映像、容器、网络和卷。
-
Docker 注册表
Docker 注册表存储 Docker 镜像。Docker Hub 是任何人都可以使用的公共注册表。
我们以 “docker run” 命令为例。
- Docker 从注册表中提取镜像。
- Docker 将创建一个新容器。
- Docker 为容器分配读写文件系统。
- Docker 会创建一个网络接口,将容器连接到默认网络。
- Docker 启动容器。
胃肠道
Git 命令的工作原理
首先,必须确定代码的存储位置。通常的假设是只有两个位置 - 一个在远程服务器(如 Github)上,另一个在我们的本地计算机上。但是,这并不完全准确。Git 在我们的机器上维护了三个本地存储,这意味着我们的代码可以在四个地方找到:
- 工作目录:我们编辑文件的地方
- 暂存区域:保存文件以供下次提交的临时位置
- Local repository:包含已提交的代码
- Remote repository:存储代码的远程服务器
大多数 Git 命令主要在这四个位置之间移动文件。
Git 是如何工作的?
下图显示了 Git 工作流程。
Git 是一个分布式版本控制系统。
每个开发人员都维护主存储库的本地副本,并编辑和提交到本地副本。
提交速度非常快,因为该操作不与远程存储库交互。
如果远程存储库崩溃,则可以从本地存储库恢复文件。
Git 合并与 Git 变基
有什么区别?
当我们将更改从一个 Git 分支合并到另一个 Git 分支时,我们可以使用 'git merge' 或 'git rebase'。下图显示了这两个命令的工作原理。
Git 合并
这将在 main 分支中创建新的提交 G'。G' 将 main 分支和 feature 分支的历史记录联系起来。
Git 合并是非破坏性的。main 分支和 feature 分支都不会更改。
Git 变基
Git rebase 将功能分支历史记录移动到主分支的头部。它会为功能分支中的每个提交创建新的提交 E'、F' 和 G'。
rebase 的好处是它具有线性提交历史记录。
如果不遵循 “git rebase 的黄金法则” ,Rebase 可能会很危险。
Git Rebase 的黄金法则
永远不要在公共分支上使用它!
云服务
不同云服务的精美备忘单(2023 年版)
什么是云原生?
下图显示了自 1980 年代以来架构和流程的演变。
组织可以使用云原生技术在公有云、私有云和混合云上构建和运行可扩展的应用程序。
这意味着这些应用程序旨在利用云功能,因此它们具有弹性负载且易于扩展。
云原生包括 4 个方面:
-
开发过程
这已经从瀑布式发展到敏捷发展到 DevOps。
-
应用程序架构
该架构已从整体式转变为微服务。每项服务都设计为小型,以适应云容器中的有限资源。
-
部署 & 打包
应用程序过去部署在物理服务器上。然后在 2000 年左右,对延迟不敏感的应用程序通常部署在虚拟服务器上。使用云原生应用程序,它们被打包到 Docker 镜像中并部署在容器中。
-
应用程序基础架构
这些应用程序大规模部署在云基础设施上,而不是自托管服务器上。
开发人员生产力工具
可视化 JSON 文件
嵌套的 JSON 文件难以阅读。
JsonCrack 从 JSON 文件生成图形图,并使其易于阅读。
此外,生成的逻辑示意图可以作为图像下载。
自动将代码转换为架构图
它有什么作用?
- 用 Python 代码绘制云系统架构。
- 图表也可以直接在 Jupyter Notebook 中呈现。
- 不需要设计工具。
- 支持以下提供商:AWS、Azure、GCP、Kubernetes、阿里云、Oracle Cloud 等。
Linux的
Linux 文件系统说明
Linux 文件系统过去类似于一个无组织的城镇,人们可以在他们喜欢的地方建造房屋。但是,在 1994 年,引入了文件系统层次结构标准 (FHS) 以使 Linux 文件系统井然有序。
通过实施 FHS 等标准,软件可以确保在各种 Linux 发行版之间实现一致的布局。尽管如此,并非所有 Linux 发行版都严格遵守此标准。它们通常包含自己独特的元素或满足特定要求。 要精通此标准,您可以从探索开始。使用诸如 “cd” 之类的命令进行导航,使用 “ls” 之类的命令列出目录内容。将文件系统想象成一棵树,从根 (/) 开始。随着时间的推移,它将成为您的第二天性,将您转变为熟练的 Linux 管理员。
您应该知道的 18 个最常用的 Linux 命令
Linux 命令是与操作系统交互的指令。它们帮助管理文件、目录、系统进程和系统的许多其他方面。您需要熟悉这些命令,以便有效地导航和维护基于 Linux 的系统。
下图显示了常用的 Linux 命令:
- ls - 列出文件和目录
- cd - 更改当前目录
- mkdir - 创建新目录
- rm - 删除文件或目录
- cp - 复制文件或目录
- mv - 移动或重命名文件或目录
- chmod - 更改文件或目录权限
- grep - 在文件中搜索模式
- find - 搜索文件和目录
- tar - 操作 tar 压缩包存档文件
- vi - 使用文本编辑器编辑文件
- cat - 显示文件内容
- top - 显示进程和资源使用情况
- ps - 显示过程信息
- kill - 通过发送信号终止进程
- du - 估计文件空间使用情况
- ifconfig - 配置网络接口
- ping - 测试主机之间的网络连接
安全
HTTPS 的工作原理是什么?
安全超文本传输协议 (HTTPS) 是超文本传输协议 (HTTP) 的扩展。HTTPS 使用传输层安全性 (TLS) 传输加密数据。如果数据在网上被劫持,劫持者得到的只是二进制代码。
如何加密和解密数据?
第 1 步 - 客户端(浏览器)和服务器建立 TCP 连接。
第 2 步 - 客户端向服务器发送“客户端问候”。该消息包含一组必要的加密算法(密码套件)和它可以支持的最新 TLS 版本。服务器以 “server hello” 作为响应,以便浏览器知道它是否可以支持算法和 TLS 版本。
然后,服务器将 SSL 证书发送到客户端。证书包含公钥、主机名、到期日期等。客户端验证证书。
第 3 步 - 验证 SSL 证书后,客户端生成会话密钥并使用公钥对其进行加密。服务器接收加密的会话密钥并使用私有密钥对其进行解密。
第 4 步 - 现在客户端和服务器都持有相同的会话密钥(对称加密),加密数据在安全的双向通道中传输。
为什么 HTTPS 在数据传输过程中会切换到对称加密?主要有两个原因:
-
安全性:非对称加密只有一种方式。这意味着,如果服务器尝试将加密数据发送回客户端,任何人都可以使用公钥解密数据。
-
服务器资源:非对称加密增加了相当多的数学开销。它不适合长时间传输数据。
Oauth 2.0 用简单的术语进行了解释。
OAuth 2.0 是一个功能强大且安全的框架,它允许不同的应用程序代表用户安全地相互交互,而无需共享敏感凭据。
OAuth 中涉及的实体是用户、服务器和身份提供者 (IDP)。
OAuth 令牌有什么作用?
使用 OAuth 时,您将获得一个代表您的身份和权限的 OAuth 令牌。此令牌可以执行一些重要操作:
单点登录 (SSO):使用 OAuth 令牌,您只需一次登录即可登录多个服务或应用程序,让生活更轻松、更安全。
跨系统授权:OAuth 令牌允许您在各种系统之间共享您的授权或访问权限,因此您不必在任何地方单独登录。
访问用户配置文件:具有 OAuth 令牌的应用程序可以访问您允许的用户配置文件的某些部分,但它们不会看到所有内容。
请记住,OAuth 2.0 旨在保护您和您的数据安全,同时让您的在线体验在不同的应用程序和服务之间无缝且轻松。
前 4 种身份验证机制形式
-
SSH 密钥:
加密密钥用于安全地访问远程系统和服务器
-
OAuth 令牌:
提供对第三方应用程序上的用户数据的有限访问权限的令牌
-
SSL 证书:
数字证书可确保服务器和客户端之间的安全加密通信
-
凭据:
用户身份验证信息用于验证和授予对各种系统和服务的访问权限
会话、Cookie、JWT、令牌、SSO 和 OAuth 2.0 - 它们是什么?
这些术语都与用户身份管理有关。当您登录网站时,您需要声明您是谁(身份证明)。验证您的身份 (身份验证),并授予您必要的权限 (授权)。过去已经提出了许多解决方案,并且列表还在不断增长。
从简单到复杂,以下是我对用户身份管理的理解:
-
WWW-Authenticate 是最基本的方法。浏览器会要求您输入用户名和密码。由于无法控制登录生命周期,它现在很少使用。
-
对登录生命周期的更精细控制是 session-cookie。服务器维护会话存储,浏览器保留会话的 ID。Cookie 通常仅适用于浏览器,对移动应用程序不友好。
-
为了解决兼容性问题,可以使用 Token。客户端将令牌发送到服务器,服务器验证令牌。缺点是 Token 需要加密和解密,可能很耗时。
-
JWT 是表示令牌的标准方式。此信息是经过数字签名的,因此可以验证和信任。由于 JWT 包含签名,因此无需在服务器端保存会话信息。
-
通过使用 SSO(单点登录),您只需登录一次并登录到多个网站。它使用 CAS(集中身份验证服务)来维护跨站点信息。
-
通过使用 OAuth 2.0,您可以授权一个网站访问您在另一个网站上的信息。
如何将密码安全地存储在数据库中以及如何验证密码?
不宜做的事情
-
以纯文本形式存储密码不是一个好主意,因为任何具有内部访问权限的人都可以看到它们。
-
直接存储密码哈希是不够的,因为它被修剪为预计算攻击,例如 rainbow 表。
-
为了缓解预计算攻击,我们对密码进行加盐处理。
什么是盐?
根据 OWASP 指南,“盐是作为哈希过程的一部分添加到每个密码中的唯一随机生成字符串”。
如何存储密码和盐?
- 哈希结果对于每个密码都是唯一的。
- 密码可以使用以下格式存储在数据库中:hash(password + salt)。
如何验证密码?
要验证密码,它可以经历以下过程:
- 客户端输入密码。
- 系统从数据库中获取相应的 salt。
- 系统将盐附加到密码并对其进行哈希处理。我们将哈希值称为 H1。
- 系统比较 H1 和 H2,其中 H2 是存储在数据库中的哈希值。如果它们相同,则密码有效。
向 10 岁的孩子解释 JSON Web 令牌 (JWT)
假设您有一个名为 JWT 的特殊框。在此框中,有三个部分:标头、有效负载和签名。
标题就像盒子外面的标签。它告诉我们它是什么类型的盒子以及如何固定它。它通常以一种称为 JSON 的格式编写,这只是一种使用大括号 { } 和冒号 : 来组织信息的方法。
有效负载就像您要发送的实际消息或信息。它可以是您的姓名、年龄或您要共享的任何其他数据。它也以 JSON 格式编写,因此易于理解和使用。 现在,签名是确保 JWT 安全的原因。它就像一个只有发件人知道如何创建的特殊印章。签名是使用密码创建的,有点像密码。此签名可确保任何人在发件人不知情的情况下无法篡改 JWT 的内容。
当您要将 JWT 发送到服务器时,请将标头、有效负载和签名放在框中。然后你把它发送到服务器。服务器可以轻松读取标头和有效负载,以了解您是谁以及您想要做什么。
Google Authenticator(或其他类型的 2 因素身份验证器)如何运作?
启用 2 因素身份验证后,Google Authenticator 通常用于登录我们的帐户。它如何保证安全性?
Google Authenticator 是一种基于软件的身份验证器,可实现两步验证服务。下图提供了详细信息。
涉及两个阶段:
- 阶段 1 - 用户启用 Google 两步验证。
- 阶段 2 - 用户使用身份验证器登录等。
让我们看看这些阶段。
第一阶段
步骤 1 和 2:Bob 打开网页以启用两步验证。前端请求密钥。身份验证服务为 Bob 生成密钥并将其存储在数据库中。
第 3 步:身份验证服务将 URI 返回到前端。URI 由密钥颁发者、用户名和密钥组成。URI 以 QR 码的形式显示在网页上。
第 4 步:然后,Bob 使用 Google Authenticator 扫描生成的二维码。密钥存储在身份验证器中。
第 2 阶段第 1 步和第 2 步:Bob 想使用 Google 两步验证登录网站。为此,他需要密码。每 30 秒,Google Authenticator 使用 TOTP(基于时间的一次性密码)算法生成一个 6 位数的密码。Bob 使用密码进入网站。
步骤 3 和 4:前端将 Bob 输入的密码发送到后端进行身份验证。身份验证服务从数据库中读取密钥,并使用与客户端相同的 TOTP 算法生成 6 位密码。
步骤 5:鉴权服务将客户端和服务端生成的两个密码进行比对,并将比对结果返回给前端。只有当两个密码匹配时,Bob 才能继续执行登录过程。
此身份验证机制是否安全?
-
密钥可以被其他人获得吗?
我们需要确保密钥是使用 HTTPS 传输的。身份验证器客户端和数据库存储密钥,我们需要确保密钥已加密。
-
6 位密码会被黑客猜到吗?
不。密码有 6 位数字,因此生成的密码有 100 万种可能的组合。此外,密码每 30 秒更改一次。如果黑客想在 30 秒内猜出密码,他们需要每秒输入 30,000 个组合。
真实案例研究
Netflix 的技术堆栈
本文基于许多 Netflix 工程博客和开源项目的研究。如果您发现任何不准确的地方,请随时通知我们。
移动和 Web:Netflix 已采用 Swift 和 Kotlin 来构建原生移动应用程序。对于其 Web 应用程序,它使用 React。
前端/服务器通信:Netflix 使用 GraphQL。
后端服务:Netflix 依赖于 ZUUL、Eureka、Spring Boot 框架和其他技术。
数据库: Netflix 使用 EV 缓存、Cassandra、CockroachDB 和其他数据库。
消息收发/流式处理:Netflix 使用 Apache Kafka 和 Fink 进行消息收发和流式处理。
视频存储:Netflix 使用 S3 和 Open Connect 进行视频存储。
数据处理:Netflix 利用 Flink 和 Spark 进行数据处理,然后使用 Tableau 对其进行可视化。Redshift 用于处理结构化数据仓库信息。
CI/CD:Netflix 使用 JIRA、Confluence、PagerDuty、Jenkins、Gradle、Chaos Monkey、Spinnaker、Atlas 等各种工具进行 CI/CD 流程。
Twitter 架构 2022
是的,这就是真正的 Twitter 架构。它由 Elon Musk 发布,并由我们重新绘制以提高可读性。
Airbnb 微服务架构在过去 15 年的演变
Airbnb 的微服务架构经历了 3 个主要阶段。
巨石 (2008 - 2017)
Airbnb 最初是一个面向房东和房客的简单市场。这是在 Ruby on Rails 应用程序 - 整体式应用程序中构建的。
挑战是什么?
- 令人困惑的团队所有权 + 无主代码
- 部署缓慢
微服务 (2017 - 2020)
微服务旨在解决这些挑战。在微服务架构中,关键服务包括:
- 数据获取服务
- 业务逻辑数据服务
- 编写工作流服务
- UI 聚合服务
- 每个服务都有一个拥有团队
挑战是什么?
人类难以管理数百个服务和依赖项。
微观 + 宏观服务(2020 年至今)
这就是 Airbnb 现在正在努力的工作。micro 和 macroservice 混合模型侧重于 API 的统一。
Monorepo 与 Microrepo。
哪个最好?为什么不同的公司选择不同的选项?
Monorepo 并不新鲜;Linux 和 Windows 都是使用 Monorepo 创建的。为了提高可扩展性和构建速度,Google 开发了其内部专用工具链,以更快地扩展它,并制定了严格的编码质量标准以保持其一致性。
Amazon 和 Netflix 是微服务理念的主要大使。这种方法自然会将服务代码分离到单独的存储库中。它的扩展速度更快,但以后可能会导致治理痛点。
在 Monorepo 中,每个服务都是一个文件夹,每个文件夹都有一个 BUILD 配置和 OWNERS 权限控制。每个服务成员都负责自己的文件夹。
另一方面,在 Microrepo 中,每个服务都负责其存储库,通常为整个存储库设置构建配置和权限。
在 Monorepo 中,无论您的企业如何,依赖项都在整个代码库中共享,因此当发生版本升级时,每个代码库都会升级其版本。
在 Microrepo 中,依赖项在每个存储库中受到控制。企业根据自己的计划选择何时升级其版本。
Monorepo 有一个签入标准。Google 的代码审查流程以设定高标准而闻名,无论业务如何,都能确保 Monorepo 的质量标准一致。
Microrepo 可以设定自己的标准,也可以通过结合最佳实践来采用共享标准。它可以更快地为业务扩展,但代码质量可能略有不同。 Google 工程师构建了 Bazel,Meta 构建了 Buck。还有其他可用的开源工具,包括 Nx、Lerna 等。
多年来,Microrepo 提供了更多受支持的工具,包括用于 Java 的 Maven 和 Gradle、用于 NodeJS 的 NPM 和用于 C/C++ 的 CMake 等。
您将如何设计 Stack Overflow 网站?
如果你的答案是本地服务器和单体式应用(在下图的底部),你很可能会通过面试,但这就是它在现实中的构建方式!
人们认为它应该是什么样子
面试官可能期待的是图片的顶部。
- 微服务用于将系统分解为多个小组件。
- 每个服务都有自己的数据库。大量使用缓存。
- 服务被分片。
- 这些服务通过消息队列异步地相互通信。
- 该服务是使用 CQRS 的事件溯源实现的。
- 展示分布式系统中的知识,如最终一致性、CAP 定理等。
它实际上是什么
Stack Overflow 仅使用 9 个本地 Web 服务器提供所有流量,而且它是在单体上!它有自己的服务器,不在云上运行。
这与我们现在所有流行的信念相反。
为什么 Amazon Prime Video 监控从无服务器转变为整体式?如何节省 90% 的成本?
下图显示了迁移前后的架构比较。
什么是 Amazon Prime 视频监控服务?
Prime Video 服务需要监控数千个直播流的质量。监控工具会自动实时分析流并识别质量问题,例如块损坏、视频冻结和同步问题。这是提高客户满意度的重要过程。
有 3 个步骤:媒体转换器、缺陷检测器和实时通知。
-
旧架构有什么问题?
旧架构基于 Amazon Lambda,这有利于快速构建服务。但是,在大规模运行架构时,它并不划算。最昂贵的两个操作是:
-
编排工作流 – AWS Step Functions 按状态转换向用户收费,编排每秒执行多个状态转换。
-
分布式组件之间的数据传递 – 中间数据存储在 Amazon S3 中,以便下一阶段可以下载。当下载量很大时,下载可能会很昂贵。
-
单体架构节省 90% 的成本
整体式架构旨在解决成本问题。仍然有 3 个组件,但媒体转换器和缺陷检测器部署在同一进程中,节省了通过网络传递数据的成本。令人惊讶的是,这种部署架构更改方法节省了 90% 的成本!
这是一个有趣且独特的案例研究,因为微服务已成为科技行业的首选和时尚选择。很高兴看到我们正在就架构的发展进行更多讨论,并就其优缺点进行更诚实的讨论。将组件分解为分布式微服务是有成本的。
-
亚马逊领导人对此有何看法?
Amazon 首席技术官 Werner Vogels:“构建可演进的软件系统是一种策略,而不是一种信仰。以开放的心态重新审视你的建筑是必须的。
前 Amazon 可持续发展副总裁 Adrian Cockcroft:“Prime Video 团队遵循了一条我称之为无服务器优先的道路......我不提倡仅限无服务器”。
Disney Hotstar 如何在锦标赛期间捕获 50 亿个表情符号?
-
客户端通过标准 HTTP 请求发送表情符号。您可以将 Golang Service 视为典型的 Web 服务器。选择 Golang 是因为它很好地支持并发。Golang 中的线程是轻量级的。
-
由于写入量非常大,因此使用 Kafka(消息队列)作为缓冲区。
-
表情符号数据由名为 Spark 的流处理服务聚合。它每 2 秒聚合一次数据,这是可配置的。需要根据间隔进行权衡。较短的间隔意味着 emoji 可以更快地交付给其他客户端,但这也意味着需要更多的计算资源。
-
聚合数据将写入另一个 Kafka。
-
PubSub 使用者从 Kafka 中提取聚合的表情符号数据。
-
表情符号通过 PubSub 基础设施实时交付给其他客户端。PubSub 基础设施很有趣。Hotstar 考虑了以下协议:Socketio、NATS、MQTT 和 gRPC,并使用 MQTT 达成和解。
LinkedIn 采用了类似的设计,每秒获得 100 万个赞。
Discord 如何存储数万亿条消息
下图显示了 Discord 消息存储的演变:
MongoDB ➡️ Cassandra ➡️ ScyllaDB
2015 年,Discord 的第一个版本构建在单个 MongoDB 副本之上。2015 年 11 月左右,MongoDB 存储了 1 亿条消息,RAM 无法再保存数据和索引。延迟变得不可预测。消息存储需要移动到另一个数据库。Cassandra 被选中了。
2017 年,Discord 拥有 12 个 Cassandra 节点,存储了数十亿条消息。
截至 2022 年初,它有 177 个节点,包含数万亿条消息。此时,延迟是不可预测的,并且维护操作变得过于昂贵而无法运行。
导致此问题的原因有以下几种:
- Cassandra 将 LSM 树用于内部数据结构。读取比写入更昂贵。在具有数百个用户的服务器上,可能会有许多并发读取,从而导致热点。
- 维护集群(例如压缩 SSTables)会影响性能。
- 垃圾回收暂停会导致显著的延迟峰值
ScyllaDB 是用 C++ 编写的 Cassandra 兼容数据库。Discord 重新设计了其架构,拥有整体式 API、用 Rust 编写的数据服务和基于 ScyllaDB 的存储。
ScyllaDB 中的 p99 读取延迟为 15 毫秒,而 Cassandra 中的 p99 读取延迟为 40-125 毫秒。p99 写入延迟为 5 毫秒,而 Cassandra 为 5-70 毫秒。
YouTube、TikTok 直播或 Twitch 上的视频直播如何运作?
直播与常规直播不同,因为视频内容是通过互联网实时发送的,通常只有几秒钟的延迟。
下图说明了为实现此目的,幕后发生了什么。
第1步: 原始视频数据由麦克风和摄像头捕获。数据被发送到服务器端。
第2步: 对视频数据进行压缩和编码。例如,压缩算法将背景和其他视频元素分开。压缩后,视频被编码为 H.264 等标准。此步骤后,视频数据的大小要小得多。
第 3 步: 编码后的数据被分成更小的片段,通常长度为几秒钟,因此下载或流式传输所需的时间要少得多。
第 4 步:将分段后的数据发送到流式处理服务器。流媒体服务器需要支持不同的设备和网络条件。这称为“自适应比特率流”。这意味着我们需要在第 2 步和第 3 步中生成不同比特率的多个文件。
步骤 5:将直播数据推送到 CDN(内容分发网络)支持的边缘服务器。数百万观众可以从附近的边缘服务器观看视频。CDN 显著降低了数据传输延迟。
第 6 步: 观众的设备对视频数据进行解码和解压缩,并在视频播放器中播放视频。
步骤 7 和 8:如果需要存储视频以供重播,则编码数据将发送到存储服务器,观众可以稍后从该服务器请求重播。
直播流的标准协议包括:
- RTMP(实时消息传递协议):它最初由 Macromedia 开发,用于在 Flash 播放器和服务器之间传输数据。现在,它用于通过 Internet 流式传输视频数据。请注意,Skype 等视频会议应用程序使用 RTC(实时通信)协议以降低延迟。
- HLS(HTTP Live Streaming):需要 H.264 或 H.265 编码。Apple 设备仅接受 HLS 格式。
- DASH (Dynamic Adaptive Streaming over HTTP):DASH 不支持 Apple 设备。
- HLS 和 DASH 都支持自适应比特率流式处理。
许可证
本作品采用 CC BY-NC-ND 4.0 协议
目录大纲
最新文档
知识宇宙
正在加载知识图谱...



































































