架构
2020-11-13 16:59:09 0 举报
AI智能生成
架构
作者其他创作
大纲/内容
架构非功能性需求/复杂度的体现
高可用
缩短宕机时间
这个也是服务最核心的指标之一
FMEA
FMEA(Failure mode and effects anaylysis,故障模式与影响分析)又称失效模式与后果分析。
FMEA具体分析方法
1. 给出初始的架构图
2. 假设架构中某个部件发生故障
3. 分析此故障对系统功能造成的影响
4. 根据分析结果,判断架构是否需要优化
FMEA表格
储存高可用
主从复制
需要人工切换
主备复制
主备复制是和主从复制的区别是主备复制没有client读从,而主从复制会允许client读从机
数据分区
应对大的灾难,比如:水灾,地震。把数据备份到不同的地区
复制规则
集中式
集中复制到一个地方
互备式
不同地区互相备份
独立式
推荐使用
直接备份到指定的不同地区
主备/主从倒换:主从自动切换
互联式
最简单的做法:主从/主备复制的时候,主一直发送状态给从,如果从接受不到主的状态,就可以切换自己为主缺点:状态的可靠性要设计得够高,出现问题的可能性比较大
中介式
引入第三方仲裁,比如Zookeeper。Zookeeper本身是高可用的,用它来管理自己系统的高可用性。实现主从/主备自动切换master。
模拟式
主从/主备复制,然后从伪装自己是client,去读主,得到到为活,否则切自己为主。和互联式有点类似,也有着同样的问题。
主主复制
数据集群
数据集中集群
Zookeeper
适合数据不大的集群,数据量是单台机器能支撑的,比如Zookeeper集群推荐不超过5台。
数据离散集群
Hadoop
Elasticsearch
适合大数据集群,成千上百台机器。
计算高可用
主从
主备
ElasticJob
XXJob
异地多活
分类
同城异区
架构设计的时候可以当成同一个机房来使用
跨城异地
强一致性的业务不能跨机房
业务在数据不一致的情况下受影响小
跨国异地
面对不同地区的用户提供服务,或者只提供只读的业务。一般跨国是隔离的。比如:亚马逊中国,亚马逊美国
根据上面的分类得出结果:我们主要关注跨城异地的情况。
异地多活设计技巧
1. 保证核心业务的异地多活。
根据用户id或者用户ip等决定用户hash到哪个地区的服务
2. 核心数据最终一致性
3. 采用多种数据同步手段
异步多活设计步骤
1. 业务分级
2. 数据分类
3. 数据同步
4. 异常处理
容错模式:接口级故障应对方案
0. 出错恢复
1. 船舱隔离模式
在一个不断迭代的系统中,将每个节点的服务分为三组:
1. 准生产环境
内测使用
2. 灰度环境
部分普通用户的流量
3. 生产环境
大部分生产用户的流量
VIP商户的流量
这样就算有比较大的重构,也可以充分利用灰度环境进行隔离性的验证
2. 熔断模式
3. 限流模式
1) 计数器
2)令牌桶
3)信号量
4. 失效转移策略
1)快速失败策略
发送给失败的结果给使用方,让使用方自己决定怎么处理后续的操作。
失败的时候,很有可能只是一台机器有问题,采用重试的办法也许会成功,这中方法要求提供者的服务实现了幂等性。
2)备份服务
如果有备份的服务,则快速切换到备份服务
5. 服务降级
6. 排队
计算方式 :1 - (宕机时间 / 全年时间)
一致性
永远也不要在本地事务之中调用RPC/HTTP等远程服务,这样有可能拖长事务。因为占用太多数据库谅解,让服务器负载迅速增高,严重的时候有可能会压垮数据库。
理论
ACID
强一致性
在DDD的服务层/领域层一般追求强一致性。
CAP
C
A
可用性
P
分区可用
BASE
弱一致性
最终一致性
在DDD的应用层一般追求最终一致性
BASE分为三部分
1. BA: Basically Available
基本可用
2. S: Soft State
软状态,就是有一些中间状态。可能有其它的线程来扫描这些状态,然后推动这个记录走向下一步,或者回到初始数据。直到走到最终状态位置。
软状态,也称为补偿模式
3. E: Eventually Consistent
在一定的时间窗口内,数据达到最终一致性就可以了。
酸碱平衡
ACID英文是酸,BASE英文是碱我们称ACID+BASE为酸碱平衡理论。
BASE其实是为了解决ACID的强一致性问题在微服务系统之中难以实现的问题而提出的。
分布式一致性协议
国际开发标准组织Open Group定义了DTS(分布式事务处理模型)
模型包含四种角色
1. 应用程序
2. 事务管理器
统管全局
3. 资源管理器
4. 通信资源管理器
JEE规范定义了TX协议和XA协议
TX协议定义了应用程序和事务管理器之间的接口
XA协议定义了事务管理器和资源管理器之间的接口
JEE中EJB是事务管理器,JMS服务和关系型数据库则是资源管理器。
2PC
2PC把分布式事务分为了两个部分
都是由事务管理器发起的
1. 准备,写redo和undo日志
redo日志是为了防止宕机而写入的日志
undo是为了回滚而写入的日志
2. 提交
所有的参与者都成功则执行commit
否则执行undo
它会询问所有的参与者(资源管理器)是否都准备好了,只有所有的参与者都准备好了才会提交,否则回退到初始状态
缺点
1. 阻塞。准备和提交的过程都需要阻塞,意味着锁定资源。
2. 单点故障。如果事务管理器宕机,那么并且有些事务进入到了提交阶段,并且部分参与者已经成功提交,而部分没有。即使后面选举出新的事务管理器,也没办法处理这种情况。
3. 脑裂。如上单点故障,会出现有的参与者提交了事务,有的没提交,出现数据不一致。这种情况需要人工进行干预了。
3PC
3PC把分布式事务分为了三个部分
相对于2PC阶段引入了超时机制,超过一定的事件没收到消息,就默认执行成功了。
1. 询问阶段
相对于2PC多出来的阶段,询问所有的参与者是否能完成事务,回到是否即可。
2. 准备阶段
3. 提交阶段
3PC只是减轻了2PC的缺点的情况,不没有完全解决。
TCC协议
TCC协议将一个事务分为三个步骤
1. try : 应用程序发起try
主要是对业务系统做检测及资源预留。
2. confirm: TCC管理器(事务管理器)发起Confirm,如果其中出现任务问题包括超时都是cancel
redo 日志,undo日志 + 执行到磁盘
3. cancel
与3PC的区别是3PC的询问是事务管理器发起的,而TCC是应用服务器发起的,并且把2PC二阶段的undo独立成Cancel操作。TCC是简化版的3PC。但是还是没有解决脑裂/数据不一致的问题。比如有的参与者没接收到cancel的指令。但是TCC通过自动化Cancel,减少了部分人工干预的过程,将系统服务修复的数据不一致减少到最少。
因为多个参与者会引发性能问题,所以互联网的高并发系统一般是不会用2PC,3PC协议来解决分布式一致性的问题。
分布式一致性算法
Paxos
Raft
ZAB
实践
现实在互联网中的理论
MySQL,Oracle关系型数据库,支持强一致性。如果数据库分片分到同一个数据库,也执行强一致性。
如果分不到一个数据库就解决不了强一致性问题,就需要BASE理论来设计服务。 设立中间状态/软状态,系统自动推动服务向下走或者是人工干预。
现实中的系统一般只需要设计达到最终一致性即可,不需要一定实现分布式一致性协议,因为性能不大好。
互联网中最多使用TCC模式,不过TCC模式有点臃肿。
互联网中实践方案
将相关的业务表分片到同一个数据库中,利用数据库的ACID实现事务的一致性
业务补偿模式
查询模式
提供个接口,可以查询业务的中间状态,一般搭配下面的模式使用。
异步确保模式
对于b style=\
定期校验模式
在金融系统中经常见到,金融系统涉及资金,必须确保资金的正确性。现金对账、商户交易对账、手续费对账等 。都需要使用第三方系统进行核对,校验。
这种模式是基于BASE理论,都是追求最终一致性。实现的时候都是记录中间状态,然后用中间状态去查询然后补偿业务。所谓补偿就是数据还没修正到该有的状态,需要往下推或者回退到初始状态。
可靠事件模式/可靠消息模式
比如RocketMQ的事务消息。
事务消息的使用方式
https://blog.csdn.net/prestigeding/article/details/81318980
可靠消息发送
尽最大努力保证发送消息成功
1. 发送消息失败,则将消息保存到数据库,标记为发送失败状态。定时任务加载出来重新发送
这种情况也有可能出现消息发送失败,因为刚刚执行到上一步宕机了,mq刚刚没发送出去,下面两种方式就不会出现消息丢失了。
考虑使用RocketMq提供的事务消息
2. 发送消息不过成功失败都先保存到数据库一封,标记为未发送。定时任务load发送。
3. 发送消息前,先发送一个消息到第三方消息管理器,不一定是MySQL,可以是ES/redis等,让它持久化到数据库。重复2的步骤。
消息有可能重复发送因为有同步调用超时和异步调用超时这一说法。
一致性问题
1. 秒杀下单和扣库存的一致性问题
方法:将下单和库存分片到同一个库中,然后用数据库的事务来解决一致性问题
2. 同步调用超时
系统a同步调用系统b,系统a调用超时能自己感应知道。但是系统a无法确定系统b调用是否成功,这个时候一定要考虑幂等性。
而且如果正常调用了之后,结果返回给系统a,但是网络原因系统a没收到或者接收超时,然后系统a又重新发起调用,这个时候怎么保证最后结果的一致性?也是幂等性问题。
3. 异步回调超时
系统a异步调用系统b,系统b执行完之后通知系统a,但是网络原因系统a没接收到系统b的结果通知。这个时候怎么保证一致性/幂等性?
4. 系统之间状态不一致
比如修改用户姓名,用户姓名在系统很多个地方都冗余了。怎么保证一致性呢?
1. 定期检查模式2. 异步确保模式都能解决这个问题
这两个调用如果是对性能要求不是很高,可以用查询模式来解决。在提供的方法中,先去查询相应的数据是否修改了,修改了则不需要再执行一次。如果是对性能要求高,并且执行修改某个状态等。考虑使用 UPDATE SET xxx=123 where xxx=old_value也可以考虑使用缓存做个过滤,比如订单支付,我将订单号保存在redis之中,下次多个请求过来的时候,如果我发现了redis已经有这个订单号了,就不处理这个这个请求了。
这里也会引发一个幂等性的问题:幂等性也要考虑顺序性,比如你接受到了a请求,处理完成,返回结果,但是接收方没接收到。然后处理了b请求,两个请求是对同一条记录进行修改,然后a请求超时又发送一个a请求过来。这种情况建议引入一个时间戳(这也是为什么支付交易中经常看到时间戳的原因),检查到a请求在b请求之后,并且是同样的业务,可能需要丢弃a。或者检查a请求是否完成,再处理a。当然,如果是多个服务器同时发起的请求,就无法使用时间戳做处理了,也可以使用左边描述的缓存做过滤
同步和异步的选择
短小精悍的逻辑建议使用同步处理。
比如计算某个值,查询某个值不需要经过数据库
耗时较长的业务逻辑建议使用异步调用
同步超时的解决方案
两状态
三状态
异步超时的解决方案
mq消息
缓存的一致性问题
缓存和数据库数据不一致
缓存追求的都只能追求弱一致性。目前没听说过有强一致性的缓存。
本地环境之间的本地环境不一致
如果对性能要求不是很高就用分布式缓存,没必要用本地缓存。
读的时候,先读缓存再读数据库;写的时候,先写数据库再写缓存。
缓存的数据不正确
写缓存的时候,数据一定要完整正确,如果有部分有效,部分失效。缓存就失去意义了,宁愿查回数据库。
写缓存的时候要校验数据
高性能
指服务节点的吞吐量和响应时间
储存高性能
1)读写分离
主从同步复制存在延时的可能性,延时可能达到1s,如果有大量数据同步达到1min都有可能
解决延时的方案
1)写之后读操作在1min之内在master进行
缺点:不能百分之百解决这个问题,并且新来的人员对这种机制不熟悉,容易引起bug
2)读从机失败之后从主机再读一次
缺点:很多二次读写会增加master的压力。比如:黑客暴力破解账户,master顶不住崩溃。
3)关键业务的读写放在master,其他的放在slave
缺点:复杂度高
2)分库分表
3)NoSQL
K-V 储存
Redis
文档数据库
MongoDB
列式数据库
HBase
全文搜索引擎
计算高性能
I/O模型
Reactor
集群高性能
负载均衡
DNS负载均衡
系统的负载均衡
硬件负载均衡(f5或a10)
机器级别的负载均衡
Ngnix 7层负载均衡
应用的负载均衡
LVS是Linux内核的4层负载均衡
负载均衡算法
轮询
加权轮询
负载最低优先
Hash类型
源地址Hash
ID Hash
可伸缩
垂直伸缩
水平伸缩
可伸缩往往指的是横向扩展能力,就是增加服务节点能让服务能力线性增加。如果不能就用百分比来衡量
缓存
性能上 本地缓存 > 分布式缓存
缓存的三大问题
1)缓存穿透
2)缓存雪崩
3)缓存击穿
缓存热点
缓存预热
可扩展
可拔插
组件重用
安全性
数据安全
加密
熔断
防攻击
硬件成本
项目投入
复杂度
其它
可监控
可测试性
可灰度
可预览
可Mock
可拆解
鲁棒性
容错性
可恢复性
可维护
易于维护
运营,扩展
可重用性
可移植
解耦
易用性
可操作性
架构
概念
架构是为了应对软件系统复杂度而提出的一个解决方案,架构是为了解决问题而来。
架构设计原则
1. 合适原则
合适优先于业界领先
2. 简单原则
简单优于复杂
3. 演化原则
演化优于一步到位
Architecture Tradeoff Analysis Method(ATAM)
架构权衡分析方法
评估架构的一种方法
非功能质量需求具体指标
1. 应用服务器
1. 部署结构
高可用策略
I/O模型(NIO,BIO)
线程池模型
1)线程池中线程数量
多业务混合部署
2. 容量和性能
1)每天的请求量。
2)各个接口的访问峰值
3)平均访问时间
4)最大访问时间
5)在线的用户量
6)请求的大小
7)网卡的I/O流量
8)磁盘的负载
9)内存的使用情况
10)CPU的使用情况
3. 其它指标
GC收集器的选型和配置
2. 数据库
1)复制模式
主从拷贝的方式
2)失效转移策略
3)容灾策略
4)归档策略
5)读写分离策略
6)分库分表策略
7)静态数据和半静态数据是否使用缓存
8)缓存穿透压垮数据库的情况
9)缓存失效
10)缓存数据预热
1)当前的数据容量
2)每天的数据增量(预估容量)
3)每秒读的峰值
4)每秒写的峰值
5)每秒事务的峰值
1)查询是否走索引
2)有没有大数据量的查询和范围查询
3)有没有多表关联,关联是否用到索引
4)有没有用到悲观锁,是否可以改成乐观锁,是否可以利用数据库内置的行锁
5)事务和一致性级别
6)jdbc数据源类型
7)连接数配置
8)储存过程
9)分库分表
代理
客户端
水平分表
垂直分表
伸缩策略
3. 缓存
1. 部署架构
1)复制模型
canal
3)持久化策略
4)淘汰策略
5)线程模型
6)预热方法
7)哈希分片策略
1)缓存内容的大小
2)缓存内容的数量
3)缓存内容的过期时间
4)缓存的数据结构
5)每秒的读峰值
6)每秒的写峰值
1)冷热数据对比
2)是否有可能发生缓存穿透
3)是否有大对象
4)是否使用缓存实现分布式锁
5)是否使用了缓存知此的脚步比如Lua
6)是否避免了 Race Condition
7)缓存分片
集群
4. 消息队列
1) 复制模型
2)失效转移
3)持久策略
1)每天的平均数据增量
2)消息持久的过期时间
5)每条消息的大小
6)平均延时
7)最大延时
1)消费者线程池模型
2)哈希分片策略
3)消息可靠性的投递
4)消费者的处理流程和持久机制
容量评估
架构设计流程
1. 识别复杂度
将主要的复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序。优先解决最重要的复杂度问题。
2. 设计备选方案
常见的错误
1)设计最优秀的方案
1)). 合适原则
2)). 简单原则
3)). 演化原则
2)只做一个方案
备选方案的数量以3~5个为最佳
备选方案差异要比较明显
备选方案的技术不要局限于已经熟悉的技术
3)备选方案过于详细
正确的做法
备选阶段只关心技术选型,而不是技术细节,技术选型的差异要比较明显。
3. 评估和选择备选方案
根据自己的实际情况决定,建议的做法
360度环评
1)列出我们需要关注的质量属性点/非功能性需求
2)根据质量属性点/非功能性需求的纬度去评估每个备选方案
3)综合挑选适合自己的最优方案
错误的做法
1)) 数量对比法:简单地看哪个方案的优点多就选哪个。
2))加权法:每个质量/需求点加上一个权重。
正确做法
按优先级选择
罗列出优先级,按照从高到底匹配选择自己的方案
4. 详细设计方案
例子
0 条评论
回复 删除
下一页