【后端开发】系统设计101——通信协议,数据库与缓存,架构模式,微服务架构,支付系统(36张图)
文章目录
- 1、通信协议
- 通信协议
- REST API 对比 GraphQL(前端-web服务)
- grpc如何工作(后台-微服务)
- webhook和轮询(回调-通知系统)
- 如何提高API性能
- HTTP从1.0到3.0(从TCP到QUIC/UDP)
- API的发展史(SOAP-REST-GraphQL-RPC)
- 代码优先 vs API优先
- HTTP的响应代码
- API 网关是什么
- 如何设计有效和安全的 API?
- TCP/IP 封装
- 为什么 Nginx 被称为“反向”代理?
- 常见的负载均衡算法有哪些?
- URL、URI、URN - 你知道它们的区别吗?
- 2、数据库与缓存
- 云服务中不同数据库的便捷速查表
- 支撑数据库的8种数据结构
- SQL语句在数据库中是如何执行的?
- CAP定理
- 内存和存储的类型
- 可视化SQL查询
- SQL语言
- 数据无处不缓存
- Redis 为何如此快速?
- Redis 可以如何使用?
- 顶级缓存策略
- 3、架构模式
- MVC、MVP、MVVM、MVVM-C 和 VIPER
- 每位开发者都应该了解的18个关键设计模式
- 4、微服务架构
- 典型的微服务架构是什么样子的?
- 微服务最佳实践
- 常用于微服务的技术栈是什么?
- Kafka 为什么快
- 5、支付系统
- 如何学习支付系统?
- 为什么信用卡被称为“银行最赚钱的产品”?VISA/Mastercard是如何赚钱的?
- 当我们在商家店里刷信用卡时,VISA是如何工作的?
- 世界范围内的支付系统:印度的统一支付接口(UPI)
用图像和简单语言解释复杂系统。
参考资料:1, 2,3
文章目录
1、通信协议
通信协议
REST API 对比 GraphQL(前端-web服务)
grpc如何工作(后台-微服务)
webhook和轮询(回调-通知系统)
如何提高API性能
HTTP从1.0到3.0(从TCP到QUIC/UDP)
API的发展史(SOAP-REST-GraphQL-RPC)
代码优先 vs API优先
HTTP的响应代码
API 网关是什么
如何设计有效和安全的 API?
TCP/IP 封装
为什么 Nginx 被称为“反向”代理?
常见的负载均衡算法有哪些?
URL、URI、URN - 你知道它们的区别吗?
2、数据库与缓存
云服务中不同数据库的便捷速查表
支撑数据库的8种数据结构
SQL语句在数据库中是如何执行的?
CAP定理
内存和存储的类型
可视化SQL查询
SQL语言
数据无处不缓存
Redis 为何如此快速?
Redis 可以如何使用?
顶级缓存策略
3、架构模式
MVC、MVP、MVVM、MVVM-C 和 VIPER
每位开发者都应该了解的18个关键设计模式
4、微服务架构
典型的微服务架构是什么样子的?
微服务最佳实践
常用于微服务的技术栈是什么?
Kafka 为什么快
5、支付系统
如何学习支付系统?
为什么信用卡被称为“银行最赚钱的产品”?VISA/Mastercard是如何赚钱的?
当我们在商家店里刷信用卡时,VISA是如何工作的?
世界范围内的支付系统:印度的统一支付接口(UPI)
1、通信协议
通信协议
通信协议(Communication protocols)
架构风格定义了应用程序编程接口(API)的不同组件之间的相互交互方式。
因此,它们通过提供一种标准的设计和构建API的方法,确保了效率、可靠性和与其他系统的轻松集成。
以下是最常用的几种风格:
- RESTful(表现层状态转移):流行、易于实现、基于HTTP方法的协议。适用于Web服务。
- gRPC:现代化、高性能、使用Protocol Buffers(协议缓冲区)的协议。适用于微服务架构。
- Webhook:事件驱动、使用HTTP回调、异步的协议。在事件发生时通知系统。
- WebSocket:实时、双向、持久连接的协议。非常适合低延迟的数据交换。
- GraphQL:一种查询语言,用于请求特定的数据。减少网络开销,提供更快的响应。
- SOAP(简单对象访问协议):成熟、全面、基于XML的协议。适用于企业应用程序。
REST API 对比 GraphQL(前端-web服务)
REST:
- 使用标准的HTTP方法(如GET、POST、PUT、DELETE)进行CRUD操作。
- 在需要在独立服务/应用之间使用简单、统一的接口时表现良好。
- 缓存策略易于实现。
- 不足之处在于可能需要多次往返请求来组装来自不同端点的相关数据。
GraphQL:
- 为客户端提供单一的端点,以准确获取所需的数据。
- 客户端可以指定嵌套查询中需要的确切字段,服务器返回仅包含这些字段的优化负载。
- 支持用于修改数据的Mutations和用于实时通知的Subscriptions。
- 适用于从多个来源聚合数据,并且与快速变化的前端需求配合良好。
- 然而,它将复杂性转移到客户端,如果没有适当的保护措施,可能会允许滥用查询。
- 缓存策略可能比REST更复杂。
对比
- 在REST和GraphQL之间选择最佳方案取决于应用程序和开发团队的具体要求。
- 对于复杂或经常变化的前端需求,GraphQL是一个很好的选择。
- 而对于偏好简单和一致性契约的应用程序,REST更合适。
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或推送API,因为服务器向客户端发送HTTP请求。
在使用Webhook时,我们需要注意以下三点:
- 我们需要为外部服务设计适当的API来调用。
- 我们需要为安全原因在API网关中设置适当的规则。
- 我们需要在外部服务中注册正确的URL。
例子:
假设我们运营一家电商网站。客户通过API网关将订单发送到订单服务,该服务将订单传递给支付服务进行支付交易。
然后,支付服务与外部支付服务提供商(PSP)进行通信,以完成交易。
处理与外部PSP的通信有两种方法。
-
1、短轮询
在向PSP发送支付请求后,支付服务会不断向PSP询问支付状态,经过多轮后,PSP最终返回状态。
短轮询有两个缺点:
不断轮询状态会占用支付服务的资源。
外部服务直接与支付服务通信,存在安全漏洞。 -
2、Webhook
我们可以在外部服务中注册Webhook。这意味着:当您有关于该请求的更新时,请在某个URL上回调我。当PSP完成处理后,它将调用HTTP请求以更新支付状态。
通过这种方式,编程范式发生了改变,支付服务不再需要浪费资源来轮询支付状态。
如果PSP从未回调怎么办?我们可以设置一个定期作业,每小时检查一次支付状态。
如何提高API性能
-
分页:
当结果集较大时,分页是一种常见的优化方式。将结果流式返回给客户端,以提高服务的响应性。 -
异步日志记录:
同步日志记录每次调用都要处理磁盘,可能会减慢系统速度。异步日志记录会先将日志发送到无锁缓冲区,然后立即返回。日志将定期刷新到磁盘上。这可以显著减少I/O开销。 -
缓存:
我们可以将经常访问的数据缓存起来。客户端可以首先查询缓存,而不是直接访问数据库。如果缓存未命中,客户端可以从数据库中查询。像Redis这样的缓存将数据存储在内存中,因此数据访问速度比数据库快得多。 -
负载压缩
可以使用gzip等方式压缩请求和响应,以使传输的数据大小更小。这可以加快上传和下载速度。 -
连接池
在访问资源时,我们通常需要从数据库中加载数据。打开和关闭数据库连接会增加很大的开销。因此,我们应该通过一组打开的连接连接到数据库。连接池负责管理连接的生命周期。
HTTP从1.0到3.0(从TCP到QUIC/UDP)
HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC)
-
HTTP 1.0在1996年完成并完整记录。每个针对同一服务器的请求都需要单独的TCP连接。
-
HTTP 1.1于1997年发布。TCP连接可以保持打开以供重用(持久连接),但它不能解决HOL(head-of-line)阻塞问题。
HOL阻塞:当浏览器中允许的并行请求数量用完时,后续请求需要等待前面的请求完成。 -
HTTP 2.0于2015年发布。它通过请求多路复用解决了HOL问题,该技术在应用层消除了HOL阻塞,但在传输(TCP)层仍存在HOL问题。
如您在图表中所看到的,HTTP 2.0引入了HTTP“流”的概念:一种抽象,允许在同一TCP连接上多路复用不同的HTTP交换。每个流不需要按顺序发送。 -
HTTP 3.0的第一版草案于2020年发布。它是HTTP 2.0的拟议后继者。它使用QUIC而不是TCP作为底层传输协议,从而消除了传输层中的HOL阻塞。
QUIC基于UDP。它在传输层引入了流作为一等公民。QUIC流共享相同的QUIC连接,因此不需要创建新连接时进行额外的握手和慢启动,但是QUIC流是独立交付的,因此在大多数情况下影响一个流的数据包丢失不会影响其他流。
API的发展史(SOAP-REST-GraphQL-RPC)
随着时间的推移,不同的API架构风格被发布。每种风格都有其自己的标准化数据交换的模式。
您可以在图表中查看每种风格的用例。
代码优先 vs 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(弹性-Logstash-Kibana)堆栈进行日志记录和监控。我们有时会在API网关中缓存数据。
如何设计有效和安全的 API?
请注意,API设计不仅仅是URL路径设计。
大多数情况下,我们需要选择适当的资源名称、标识符和路径模式。
同样重要的是,在API网关中设计适当的HTTP标头字段或设计有效的速率限制规则。
TCP/IP 封装
数据是如何通过网络传输的?为什么OSI模型需要这么多层?
下面的图表展示了数据在网络传输过程中的封装和解封装过程。
-
第一步:当设备A通过HTTP协议向设备B发送数据时,首先在应用层添加HTTP头部。
-
第二步:然后在传输层将TCP或UDP头部添加到数据中,并封装为TCP段。头部包含源端口、目标端口和序列号。
-
第三步:接着在网络层将段封装为IP头部。IP头部包含源/目标IP地址。
-
第四步:在数据链路层为IP数据报添加MAC头部,包含源/目标MAC地址。
-
第五步:封装好的帧被发送到物理层,并以二进制位的形式在网络中传输。
-
第六至十步:当设备B从网络中接收到位流时,它执行解封装过程,这是封装过程的逆向处理。头部被逐层移除,最终设备B可以读取数据。
-
我们需要网络模型中的各层,因为每个层都专注于自己的职责。每个层都可以依赖头部进行处理指令,而不需要了解上一层数据的含义。
为什么 Nginx 被称为“反向”代理?
下面的图表展示了正向代理和反向代理之间的区别。
正向代理是位于用户设备和互联网之间的服务器。
正向代理通常用于:
- 保护客户端
- 绕过浏览限制
- 阻止访问某些内容
反向代理是一种服务器,它接收客户端的请求,将请求转发给Web服务器,并将结果返回给客户端,就好像代理服务器已经处理了请求一样。
反向代理适用于以下情况:
- 保护服务器
- 负载均衡
- 缓存静态内容
- 加密和解密SSL通信
常见的负载均衡算法有哪些?
静态算法
- 轮询(Round Robin)
将客户端请求按顺序发送到不同的服务实例。这些服务通常需要是无状态的。 - 粘性轮询(Sticky Round Robin)
这是轮询算法的一种改进。如果Alice的第一个请求发送到服务A,则后续请求也会发送到服务A。 - 加权轮询(Weighted Round Robin)
管理员可以为每个服务指定权重。权重高的服务处理的请求比其他服务多。 - 哈希(Hash)
此算法对传入请求的IP或URL应用哈希函数。请求基于哈希函数的结果路由到相关实例。
动态算法
- 最少连接数(Least Connections)
将新请求发送到并发连接最少的服务实例。 - 最短响应时间(Least Response Time)
将新请求发送到响应时间最快的服务实例。
URL、URI、URN - 你知道它们的区别吗?
-
URL
URL代表统一资源定位符,是HTTP的关键概念。它是Web上唯一资源的地址。它可以与其他协议一起使用,如FTP和JDBC。 -
URN
URN代表统一资源名称。它使用urn方案。URN不能用于定位资源。图表中给出的简单示例由命名空间和命名空间特定字符串组成。 -
URI
URI代表统一资源标识符。它标识Web上的逻辑或物理资源。URL和URN是URI的子类型。 URL定位资源,而URN命名资源。
URI由以下部分组成: scheme:[//authority]path[?query][#fragment]
2、数据库与缓存
云服务中不同数据库的便捷速查表
为项目选择合适的数据库是一项复杂的任务。众多的数据库选项,每种都适用于不同的用例,很容易让人产生选择疲劳。
我们希望这份速查表能够为您提供高层次的指引,帮助您找到与项目需求相符的合适服务,避免潜在的问题。
支撑数据库的8种数据结构
答案会根据您的用例而有所不同,下面这些因素都会影响您选择数据库索引格式的决策
- 数据索引,包括内存或磁盘
- 数据格式,包括数字、字符串、地理坐标等
- 系统,可能是写入密集型或读取密集型的
以下是一些用于数据索引的最流行的数据结构:
- Skiplist(跳表): 常见的内存索引类型,在Redis中使用。
- 哈希索引(Hash Index): “映射”数据结构(或“集合”)的常见实现方式。
- SSTable(Sorted String Table): 不可变的磁盘上“映射”实现方式。
- LSM树(Log-Structured Merge Tree): Skiplist + SSTable。具有高写入吞吐量。
- B树(B-Tree): 基于磁盘的解决方案。具有一致的读/写性能。
- 倒排索引(Inverted Index): 用于文档索引。在Lucene中使用。
- 后缀树(Suffix Tree): 用于字符串模式搜索。
- R树(R-Tree): 多维度搜索,例如寻找最近邻居。
SQL语句在数据库中是如何执行的?
图表展示了这个过程。请注意,不同数据库的架构是不同的,这个图表演示了一些常见的设计。
- 第一步 - 通过传输层协议(例如TCP)将SQL语句发送到数据库。
- 第二步 - SQL语句被发送到命令解析器,在那里经过语法和语义分析,然后生成一个查询树。
- 第三步 - 查询树被发送到优化器。优化器创建一个执行计划。
- 第四步 - 执行计划被发送到执行器。执行器从执行中检索数据。
- 第五步 - 访问方法提供了执行所需的数据提取逻辑,从存储引擎中检索数据。
- 第六步 - 访问方法决定SQL语句是否是只读的。如果查询是只读的(SELECT语句),则传递到缓冲管理器进行进一步处理。缓冲管理器在缓存或数据文件中查找数据。
- 第七步 - 如果语句是UPDATE或INSERT,则传递到事务管理器进行进一步处理。
- 第八步 - 在事务期间,数据处于锁定状态。这由锁管理器保证。它还确保了事务的ACID属性。
CAP定理
CAP定理是计算机科学中最著名的术语之一,但我相信不同的开发者对它有不同的理解。让我们来看看它是什么,以及为什么它可能令人困惑。
CAP定理指出,一个分布式系统不能同时提供以下三个特性:
- 一致性(Consistency): 所有客户端无论连接到哪个节点,都能够看到相同的数据。
- 可用性(Availability): 任何请求数据的客户端都能够在某些节点不可用的情况下获得响应。
- 分区容错性(Partition Tolerance): 分区指的是两个节点之间的通信中断。分区容错性意味着系统在网络分区的情况下仍然能够继续运行。
“三选二”这种简化形式确实有其用处,但这种简化也可能引起误解。
- 选择一个数据库并不容易。仅仅基于CAP定理来为选择提供理由是不够的。例如,公司之所以选择Cassandra作为聊天应用的存储系统,并不仅仅是因为它是一个AP系统。Cassandra之所以成为存储聊天消息的理想选择,是因为它具备一系列良好的特性。我们需要进行更深入的研究。
- “CAP只限制了设计空间中的一个小部分:在分区存在的情况下实现完美的可用性和一致性,而这种情况非常罕见。”这是来自于论文《CAP Twelve Years Later: How the “Rules” Have Changed》的引述。
- 该定理是关于100%的可用性和一致性。在没有网络分区的情况下,更现实的讨论应该是在延迟和一致性之间进行权衡。详细内容可以参考PACELC定理。
内存和存储的类型
可视化SQL查询
执行SQL语句涉及多个步骤,包括:
- 解析SQL语句并检查其有效性
- 将SQL转换为内部表示,例如关系代数
- 优化内部表示并创建利用索引信息的执行计划
- 执行计划并返回结果
SQL的执行非常复杂,涉及许多考虑因素,例如:
- 索引和缓存的使用
- 表连接的顺序
- 并发控制
- 事务管理
SQL语言
1986年,SQL(Structured Query Language,结构化查询语言)成为了一个标准。
在接下来的40年里,它成为了关系数据库管理系统中的主导语言。阅读最新的标准(ANSI SQL 2016)可能会耗费很多时间。我该如何学习它呢?
SQL语言有5个主要组成部分:
- DQL(数据查询语言):用于查询数据库中的数据,主要命令是SELECT(选择)。
- DDL(数据定义语言):用于定义数据库结构的语言,如CREATE(创建)、ALTER(修改)、DROP(删除)等。
- DML(数据操作语言):用于操作数据库中的数据,包括INSERT(插入)、UPDATE(更新)、DELETE(删除)等命令。
- DCL(数据控制语言):用于控制数据库访问权限的语言,包括GRANT(授权)、REVOKE(撤销)等命令。
- TCL(事务控制语言):用于管理数据库的事务,包括COMMIT(提交)、ROLLBACK(回滚)等命令。
作为后端工程师,你可能需要了解其中大部分内容。作为数据分析师,你可能需要深入了解DQL。请选择与你最相关的主题进行学习。
数据无处不缓存
在典型架构中我们会在哪些地方缓存数据?
在数据流中有多个层次。
- 客户端应用程序:浏览器可以缓存 HTTP 响应。我们第一次通过 HTTP 请求数据时,会在 HTTP 头中返回一个过期策略;我们再次请求数据时,客户端应用程序会首先尝试从浏览器缓存中检索数据。
- CDN:CDN 缓存静态网络资源。客户端可以从附近的 CDN 节点检索数据。
- 负载均衡器:负载均衡器也可以缓存资源。
- 消息基础设施:消息代理首先将消息存储在磁盘上,然后消费者按自己的节奏检索消息。根据保留策略,数据在 Kafka 集群中缓存一段时间。
- 服务:服务中有多个层次的缓存。如果数据未缓存在 CPU 缓存中,服务将尝试从内存中检索数据。有时服务还有第二级缓存,用于将数据存储在磁盘上。
- 分布式缓存:像 Redis 这样的分布式缓存在内存中保存多个服务的键值对。它比数据库提供更好的读写性能。
- 全文搜索:我们有时需要使用全文搜索,如 Elastic Search 用于文档搜索或日志搜索。数据的副本也被索引在搜索引擎中。
- 数据库:即使在数据库中,我们也有不同级别的缓存:
- WAL(预写式日志):在构建 B 树索引之前,数据首先写入 WAL。
- 缓冲池:分配给缓存查询结果的内存区域。
- 材料化视图:预先计算查询结果并将其存储在数据库表中,以获得更好的查询性能。
- 事务日志:记录所有事务和数据库更新。
- 复制日志:用于记录数据库集群中的复制状态。
Redis 为何如此快速?
有三个主要原因:
- Redis 是基于 RAM 的数据存储。与随机磁盘访问相比,RAM 访问速度至少快 1000 倍。
- Redis 利用 IO 多路复用和单线程执行循环以提高执行效率。
- Redis 利用了几种高效的低级数据结构。
问题:另一个流行的内存存储是 Memcached。您知道 Redis 和 Memcached 之间的区别吗?
- 如果有持久方面的需求或对数据类型和处理有要求的应该选择redis。
- 如果简单的key/value 存储应该选择memcached。
- memcache还可用于缓存其他东西,例如图片、视频等等
- Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;
- 虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;
- 灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;
Redis 可以如何使用?
Redis 不仅仅是缓存。
Redis 可以在各种场景中使用:
- 会话:我们可以使用 Redis 在不同的服务之间共享用户会话数据。
- 缓存:我们可以使用 Redis 缓存对象或页面,特别是热点数据。
- 分布式锁:我们可以使用 Redis 字符串在分布式服务之间获取锁。
- 计数器:我们可以计算文章的点赞数或阅读量。
- 速率限制器:我们可以为特定用户 IP 应用速率限制器。
- 全局 ID 生成器:我们可以使用 Redis Int 作为全局 ID。
- 购物车:我们可以使用 Redis Hash 表示购物车中的键值对。
- 计算用户留存:我们可以使用 Bitmap 表示用户每天的登录情况,并计算用户留存。
- 消息队列:我们可以使用 List 作为消息队列。
- 排名:我们可以使用 ZSet 对文章进行排序。
顶级缓存策略
设计大规模系统通常需要仔细考虑缓存。以下是经常使用的五种缓存策略
3、架构模式
MVC、MVP、MVVM、MVVM-C 和 VIPER
这些架构模式是在应用开发中最常用的,无论是在iOS还是Android平台上。
开发者们引入了这些模式以克服早期模式的局限性。那么,它们有何不同之处呢?
MVC,作为最古老的模式,可以追溯到近50年前。
- 每种模式都有一个“视图”(V),负责显示内容并接收用户输入。
- 大多数模式包括一个“模型”(M),用于管理业务数据。
- “控制器”、“展示者”和“视图模型”是在视图和模型(在VIPER模式中称为“实体”)之间进行调解的翻译器。
每位开发者都应该了解的18个关键设计模式
设计模式是对常见设计问题的可重用解决方案,它们使开发过程更加顺畅、高效。它们充当着构建更好软件结构的蓝图。
以下是一些最受欢迎的设计模式(18个):
- 抽象工厂模式:家族创造者 - 创建相关物品的组合。
- 建造者模式:乐高大师 - 逐步构建对象,保持创建和外观的分离。
- 原型模式:克隆制造者 - 创建完全准备好的示例的副本。
- 单例模式:唯一实例 - 一个只有一个实例的特殊类。
- 适配器模式:通用插头 - 连接具有不同接口的对象。
- 桥接模式:功能连接器 - 将对象的工作方式与其所做的事情链接起来。
- 组合模式:树构建者 - 形成简单和复杂部分的树状结构。
- 装饰器模式:定制者 - 在不改变核心的情况下为对象添加功能。
- 外观模式:一站式购物 - 用单一、简化的接口代表整个系统。
- 享元模式:节省空间 - 高效共享小的可重复使用的物品。
- 代理模式:替身演员 - 代表另一个对象,控制访问或行为。
- 职责链模式:请求中继 - 将请求通过一系列对象传递,直到被处理。
- 命令模式:任务包装 - 将请求转化为一个可执行操作的对象。
- 迭代器模式:集合探险家 - 逐个访问集合中的元素。
- 中介者模式:通信中心 - 简化不同类之间的交互。
- 备忘录模式:时光胶囊 - 捕捉和恢复对象的状态。
- 观察者模式:新闻广播 - 通知类关于其他对象的变化。
- 访问者模式:技艺嘉宾 - 为类添加新操作而不改变它。
4、微服务架构
典型的微服务架构是什么样子的?
典型的微服务架构
- 负载均衡器:将传入的流量分发到多个后端服务。
- CDN(内容分发网络):CDN 是一组地理分布的服务器,保存静态内容以便更快地传递。客户端首先在 CDN 中查找内容,然后转到后端服务。
- API 网关:处理传入的请求并将它们路由到相关服务。它与身份提供者和服务发现进行通信。
- 身份提供者:处理用户的身份验证和授权。
- 服务注册表和发现:微服务的注册和发现发生在此组件中,API 网关在此组件中查找相关服务以进行通信。
- 管理:此组件负责监视服务。
- 微服务:微服务在不同的域中设计和部署。每个域都有自己的数据库。API 网关通过 REST API 或其他协议与微服务进行通信,同一域内的微服务使用 RPC(远程过程调用)相互通信。
微服务的好处:
- 可以快速设计、部署和水平扩展。
- 每个域可以由专门的团队独立维护。
- 由于每个域都可以定制业务需求并得到更好的支持,因此业务需求可以在每个域中得到更好的支持。
微服务最佳实践
开发微服务的 9 个最佳实践。
当我们开发微服务时,需要遵循以下最佳实践:
- 1、为每个微服务使用单独的数据存储
- 2、保持代码处于相似的成熟度水平
- 3、为每个微服务分别构建
- 4、为每个微服务分配单一职责
- 5、部署到容器中
- 6、设计无状态服务
- 7、采用领域驱动设计
- 8、设计微前端
- 9、编排微服务
无状态服务1:
- 无状态服务(stateless service)对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本身不存储任何信息
- 有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的
常用于微服务的技术栈是什么?
微服务技术栈,包括开发阶段和生产阶段
Pre-Production
- 定义 API - 这建立了前端和后端之间的契约。我们可以使用 Postman 或 OpenAPI 来实现。
- 开发 - Node.js 或 React 用于前端开发,Java/Python/Go 用于后端开发。此外,我们需要根据 API 定义更改 API 网关的配置。
- 持续集成 - JUnit 和 Jenkins 用于自动化测试。代码被打包成 Docker 镜像并部署为微服务。
Production
- NGinx 是负载均衡器的常见选择。Cloudflare 提供 CDN(Content Delivery Network 内容分发网络)。
- 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对顺序I/O的依赖。
- 第二个决策让Kafka拥有性能优势的是其专注于效率:零拷贝原则。
零拷贝是一种节省应用程序上下文和内核上下文之间多次数据复制的快捷方式。
生产者和消费者之间的数据传输方式以及零拷贝的含义:
- 步骤1.1-1.3:生产者将数据写入磁盘
- 步骤2:消费者在没有零拷贝的情况下读取数据
2.1 数据从磁盘加载到操作系统缓存中
2.2 数据从操作系统缓存中复制到Kafka应用程序中
2.3 Kafka应用程序将数据复制到套接字缓冲区中
2.4 数据从套接字缓冲区中复制到网络卡中
2.5 网络卡将数据发送给消费者 - 步骤3:消费者使用零拷贝读取数据
3.1:数据从磁盘加载到操作系统缓存中
3.2 操作系统缓存通过sendfile()命令直接将数据复制到网络卡中
3.3 网络卡将数据发送给消费者
5、支付系统
如何学习支付系统?
如何学习支付系统
为什么信用卡被称为“银行最赚钱的产品”?VISA/Mastercard是如何赚钱的?
信用卡支付流程中的经济学:
- 1、持卡人支付100美元给商家购买商品。
- 2、商家通过使用信用卡获得更高的销售额,并需要向发卡行和卡网络提供支付服务进行补偿。收单行与商家签订一个名为“商家贴现费”的收费协议。
- 3-4. 收单行保留0.25美元作为收单成本费,1.75美元作为交换费支付给发卡行。商家贴现费应该覆盖交换费。
由于每个发卡行与每个商家协商费用效率低下,因此卡网络设置了交换费。
- 1、卡网络与每家银行设置网络评估和费用,每月银行向卡网络支付其服务费。例如,VISA每次刷卡收取0.11%的评估费和0.0195美元的使用费。
- 2、持卡人向发卡行支付其服务费用。
为什么发卡行需要获得补偿?
- 持卡人向发卡行支付费用之前,发卡行已向商家支付费用。
- 即使持卡人未向发卡行支付费用,发卡行仍需向商家支付费用。
- 发卡行还有其他运营成本,包括管理客户账户、提供对账单、欺诈检测、风险管理、清算和结算等。
当我们在商家店里刷信用卡时,VISA是如何工作的?
VISA、Mastercard和美国运通是信用卡结算和清算的卡网络。
收单行和发卡行可以是不同的银行。如果银行之间逐笔结算而没有中介,每家银行都必须与其他所有银行结算交易,这是非常低效的。
VISA在信用卡支付流程中的角色。
有两个涉及的流程:1、授权流程发生在客户刷卡时,2、捕获和结算流程发生在商家想要在一天结束时收到钱时。
1、授权流程
- 步骤0:发卡行向其客户发放信用卡。
- 步骤1:持卡人想要购买商品,在商家店内的POS终端刷信用卡。
- 步骤2:POS终端将交易发送至提供POS终端的收单行。
- 步骤3和4:收单行将交易发送至卡网络,也称为卡方案。卡网络将交易发送至发卡行进行批准。
- 步骤4.1、4.2和4.3:如果交易被批准,发卡行会冻结资金。批准或拒绝的结果将返回给收单行和POS终端。
2、捕获和结算流程
- 步骤1和2:商家想要在一天结束时收到钱,因此他们在POS终端上点击“捕获”。交易以批处理方式发送到收单行。收单行将带有交易的批处理文件发送到卡网络。
- 步骤3:卡网络对来自不同收单行的交易进行清算,并将清算文件发送给不同的发卡行。
- 步骤4:发卡行确认清算文件的正确性,并向相关的收单行转移资金。
- 步骤5:收单行然后将资金转移至商家的银行。
- 步骤4:卡网络清理来自不同收单行的交易。清算是一种互相抵消交易的净额过程,因此总交易次数减少。
在此过程中,卡网络承担与每家银行交流的负担,并获得服务费。
世界范围内的支付系统:印度的统一支付接口(UPI)
UPI是由印度国家支付公司开发的即时实时支付系统。
它占印度数字零售交易的60%。
UPI = 支付标记语言 + 可互操作支付标准。