架构学习笔记
程序员文章站
2022-05-31 19:59:40
...
架构设计的主要目的是为了解决软件系统复杂度带来的问题
当我们对这样一个系统进行架构设计的时候,首先应识别其复杂度到底体现在哪里。
复杂度来源:
高性能
单机性能,集群性能
高可用
计算(轮询,分发)的高可用,存储的高可用
高扩展
提炼出一个“抽象层”和一个“实现层”,依赖接口,不要依赖具体实现
低成本
低成本与高性能相冲突
安全
功能安全,常见的 XSS 攻击、CSRF 攻击、SQL 注入、Windows 漏洞、密码**等
架构安全
防火墙
规模
功能越来越多,导致系统复杂度指数级上升
数据越来越多,系统复杂度发生质变
架构设计的三个原则
1,合适原则
人力物力,合适优于业界领先
2,简单原则
简单优于复杂
3,演化原则
版本迭代,演进,演化优于一步到位
架构设计流程
1,排除法识别复杂度
对于架构师来说,关注的不是一天的数据,而是 1 秒的数据,即 TPS 和 QPS
2,设计架构的备选方案
3,详细方案设计
高性能数据库集群
1,读写分离
2,分库分表
3,NoSQL
高性能缓存架构
1,更新锁
对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新
2,后台更新
后台线程除了定时更新缓存,还要频繁地去读取缓存(例如,1 秒或者 100 毫秒读取一次),如果发现缓存被“踢了”就立刻更新缓存,这种方式实现简单,但读取时间间隔不能设置太长,因为如果缓存被踢了,缓存读取间隔时间又太长,这段时间内业务访问都拿不到真正的数据而是一个空的缓存值,用户体验一般。业务线程发现缓存失效后,通过消息队列发送一条消息通知后台线程更新缓存。可能会出现多个业务线程都发送了缓存更新消息,但其实对后台线程没有影响,后台线程收到消息后更新缓存前可以判断缓存是否存在,存在就不执行更新操作。这种方式实现依赖消息队列,复杂度会高一些,但缓存更新更及时,用户体验更好。
高可用
一致性
A read is guaranteed to return the most recent write for a given client.
对某个指定的客户端来说,读操作保证能够返回最新的写操作结果
可用性
A non-failing node will return a reasonable response within a reasonable amount of time (no error or timeout).
非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)
分区容错性
The system will continue to function when network partitions occur.
当出现网络分区后,系统能够继续“履行职责”
FMEA 方法:排除架构可用性隐患的利器
应对接口级的故障
1,降级(丢车保帅):停掉非核心业务
2,熔断(保险丝):按策略停掉服务间的调用
3,限流(我只能处理这么多):
基于请求限流(系统外部):
根据阈值来限制访问量,负载均衡系统,网关系统,抢购系统。
基于资源限流(系统内部):
常见的内部资源有:连接数、文件句柄、线程数、请求队列等