【OS】系统设计
系统设计
是根据系统分析的结果,运用系统科学的思想和方法,设计出能最大限度满足所要求的目标或目的的新系统的过程。
0 概述
性能指标
- 响应时间:指某个请求从发出到接收到响应消耗的时间。
- 吞吐量:指系统在单位时间内可以处理的请求数量。
- 并发用户数:指系统能同时处理的并发用户请求数量。
性能优化
- 集群:将多台服务器组成集群,使用负载均衡将请求转发到集群中,避免单一服务器的负载压力过大导致性能降低。
- 缓存
- 异步
特性
- 伸缩性:指不断向集群中添加服务器来缓解不断上升的用户并发访问压力和不断增长的数据存储需求。
- 扩展性:指的是添加新功能时对现有系统的其它应用无影响,这就要求不同应用具备低耦合的特点。
- 安全性:要求系统在应对各种攻击手段时能够有可靠的应对措施。
- 可用性:冗余、监控、服务降级。
1 分布式
分布式锁
- 数据库的唯一索引:获得锁时向表中插入一条记录,释放锁时删除这条记录。唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否处于锁定状态。
- Redis 的 SETNX 指令
- Redis 的 RedLock 算法
- Zookeeper 的有序节点
分布式事务
指事务的操作位于不同的节点上,需要保证事务的 ACID 特性。
分布式锁和分布式事务区别:
- 锁问题的关键在于进程操作的互斥关系。
- 事务问题的关键在于事务涉及的一系列操作需要满足 ACID 特性。
两阶段提交(Two-phase Commit,2PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。分为准备阶段和提交阶段。
本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。
CAP:分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项。在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际上是要在可用性和一致性之间做权衡。
幂等性:一个操作任意多次执行所产生的影响均与一次执行的影响相同。
BASE:基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)。BASE 理论是对 CAP 中一致性和可用性权衡的结果——即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
分布式一致性协议:Paxos、Raft
2 集群
负载均衡
- 集群中的应用服务器(节点)通常被设计成无状态,用户可以请求任何一个节点。
- 负载均衡器会根据集群中每个节点的负载情况,将用户请求转发到合适的节点上。
- 负载均衡器可以用来实现高可用以及伸缩性
- 运行过程:根据负载均衡算法得到转发的节点;进行转发。
负载均衡算法
- 轮询(Round Robin)
- 加权轮询(Weighted Round Robbin)
- 最少连接(least Connections)
- 加权最少连接(Weighted Least Connection)
- 随机算法(Random)
- 源地址哈希法 (IP Hash)
转发
- HTTP 重定向
- DNS 域名解析
- 反向代理服务器
- 网络层:在操作系统内核进程获取网络数据包,根据负载均衡算法计算源服务器的 IP 地址,修改请求数据包的目的 IP 地址,进行转发。
- 链路层:在链路层根据负载均衡算法计算源服务器的 MAC 地址,修改请求数据包的目的 MAC 地址,进行转发。
3 攻击技术
- 跨站脚本攻击(Cross-Site Scripting, XSS),可以将代码注入到用户浏览的网页上,这种代码包括 HTML 和 JavaScript。
- 跨站请求伪造(Cross-site request forgery,CSRF),是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。
- XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户浏览器的信任。
- SQL 注入攻击:服务器上的数据库运行非法的 SQL 语句,主要通过拼接来完成。
- 拒绝服务攻击(denial-of-service attack,DoS),亦称洪水攻击,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。
- 分布式拒绝服务攻击(distributed denial-of-service attack,DDoS),指攻击者使用两个或以上被攻陷的电脑作为“僵尸”向特定的目标发动“拒绝服务”式攻击。
4 缓存
- 命中率:当某个请求能够通过访问缓存而得到响应时,称为缓存命中。缓存命中率越高,缓存的利用率也就越高。
- 最大空间:缓存通常位于内存中
- 淘汰策略
- FIFO(First In First Out):先进先出策略
- LRU(Least Recently Used):最近最久未使用策略
- LFU(Least Frequently Used):最不经常使用策略
- 缓存位置
- 浏览器
- 网络服务提供商(ISP)
- 反向代理
- 本地缓存
- 分布式缓存
- 数据库缓存
- Java 缓冲池
- CPU 多级缓存
- 缓存问题
- 缓存穿透:指的是对某个一定不存在的数据进行请求,该请求将会穿透缓存到达数据库。
- 缓存雪崩:指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都到达数据库。
- 缓存一致性:要求数据更新的同时缓存数据也能够实时更新。
- 缓存 “无底洞” 现象:指的是为了满足业务要求添加了大量缓存节点,但是性能不但没有好转反而下降了的现象。
- 数据份不
- 哈希分布就是将数据计算哈希值之后,按照哈希值分配到不同的节点上。
- Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题。
- 将数据划分为多个连续的部分,按数据的 ID 或者时间分布到不同节点上。
- 哈希分布就是将数据计算哈希值之后,按照哈希值分配到不同的节点上。
内容分发网络(Content distribution network,CDN)是一种互连的网络系统,它利用更靠近用户的服务器从而更快更可靠地将 HTML、CSS、JavaScript、音乐、图片、视频等静态资源分发给用户。
5 消息队列
消息模型
- 点对点:消息生产者向消息队列中发送了一个消息之后,只能被一个消费者消费一次。
- 发布/订阅:消息生产者向频道发送一个消息之后,多个消费者可以从该频道订阅到这条消息并消费。
使用场景(为什么使用)
- 异步处理:发送者将消息发送给消息队列之后,不需要同步等待消息接收者处理完毕,而是立即返回进行其它操作。
- 流量削锋:在高并发的场景下,如果短时间有大量的请求到达会压垮服务器。可以将请求发送到消息队列中,服务器按照其处理能力从消息队列中订阅消息进行处理。
- 应用解耦:通过使用消息队列,一个模块只需要向消息队列中发送消息,其它模块可以选择性地从消息队列中订阅消息从而完成调用。
消息队列的缺点
- 系统可用性降低
- 系统复杂性增加
- 一致性问题
主流消息队列
特性 | ActiveMQ | RabbitMQ | RocketMQ | kafka |
---|---|---|---|---|
开发语言 | java | erlang | java | scala |
单机吞吐量 | 万级 | 万级 | 10 万级 | 10 万级 |
时效性 | ms 级 | us 级 | ms 级 | ms 级以内 |
可用性 | 高(主从架构) | 高(主从架构) | 非常高(分布式架构) | 非常高(分布式架构) |
可靠性 | 有较低的概率丢失数据 | 基本不丢 | 参数优化配置后 0 丢失 | 参数优化配置后 0 丢失 |
功能特性 | 成熟的产品,在很多公司得到应用 有较多的文档 各种协议支持较好 | 并发能力很强,性能极好,延时很低 管理界面较丰富 | MQ 功能比较完备,扩展性佳 | 只支持主要的 MQ 功能,在大数据领域应用广。 |
重复消费的原因及解决办法
- 因为网络传输等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。
- 解决:
- 如果该消息用做数据库的 insert 操作,给这个消息一个唯一主键,如果出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
- 准备一个第三方介质,来做消费记录。如给消息分配一个全局 id。
可靠性保证
- 发送端:在本地数据库建一张消息表,利用本地数据库的事务机制。
- 接收端:保证接收端处理消息的业务逻辑具有幂等性;保证消息具有唯一编号。
6 RPC
RPC(Remote Procedure Call Protocol)远程过程调用协议。是分布式系统常见的一种通信方法。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
RPC 的主要目标是让构建分布式应用更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制让使用者不必显式的区分本地调用和远程调用。
RPC 核心
- Call ID 映射:在 RPC 中,所有的函数都必须有自己的一个 ID。这个 ID 在所有进程中都是唯一确定的。
- 序列化和反序列化:客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。
- 网络传输:TCP 协议是 RPC 的基石。
主流的 RPC 框架
- 服务治理型:dubbo、dubbox、motan
多语言型:gRPC、thrift
- I/O 模型
- 传统的阻塞 I/O(Blocking I/O)
- 非阻塞 I/O(Non-blocking I/O)
- I/O 多路复用(I/O multiplexing)
- 异步 I/O(Asynchronous I/O)