写点什么

第十一周 安全稳定 作业 「架构师训练营 3 期」

用户头像
feiyun123
关注
发布于: 2021 年 02 月 07 日

一、导致系统不可用的原因有哪些?保障系统稳定高可用的方案有哪些?请分别列举并简述。


1、影响系统不可用的原因:


  • 硬件故障


  • 软件 bug


  • 系统发布


  • 并发压力


  • 网络攻击


  • 外部灾害


2、保障系统稳定高可用的方案:


解耦


  • 高内聚、低耦合的组件设计原则

  • 面向对象基本设计原则

  • 面向对象设计模式

  • 领域驱动设计建模


隔离


  • 业务与子系统隔离

  • 微服务与中台架构

  • 生产者消费者隔离

  • 虚拟机与容器隔离


异步


  • 多线程编程

  • 反应式编程

  • 异步通信网络编程

  • 事件驱动异步架构


备份


  • 集群设计

  • 数据库复制

  • CAP 原理


Failover(失效转移)


数据库主主失效转移

负载均衡失效转移

如何确认失效,需要转移?

设计无状态的服务


幂等


应用调用服务失败后,会将调用请求重新发送到其他服务器,但是这个失败可能是虚假

的失败。比如服务已经处理成功,但是因为网络故障应用没有收到响应,这时应用重新

提交请求就导致服务重复调用,如果这个服务是一个转账操作,就会产生严重后果。

服务重复调用有时候是无法避免的,必须保证服务重复调用和调用一次产生的结果相同,

即服务具有幂等性。有些服务天然具有幂等性,比如将用户性别设置为男性,不管设置

多少次,结果都一样。但是对于交易等操作,问题就会比较复杂,需要通过交易编号等

信息进行服务调用有效性校验,只有有效的操作才继续执行。


事务补偿


传统事务的 ACID

  • 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性

(Durability)

分布式事务的 BASE

  • 基本可用(Basic Availability )、 软状态(Soft-state)、 最终一致性(Eventual consistency)

事务补偿:通过执行业务逻辑逆操作,使事务回滚到事务前状态


重试


远程服务可能会由于线程阻塞、垃圾回收或者网络抖动,而无法及时返还响应,调用者

可以通过重试的方式修复单次调用的故障。 • 上游调用者超时时间要大于下游调用者超时时间之和。


熔断


当某个服务出现故障,响应延迟或者失败率增加,继续调用这个服务会导致调用者请求

阻塞,资源消耗增加,进而出现服务级联失效,这种情况下使用断路器阻断对故障服务

的调用。

  • 断路器三种状态:关闭,打开,半开


限流


在高并发场景下,如果系统的访问量超过了系统的承受能力,可以通过限流对系统进行

保护。限流是指对进入系统的用户请求进行流量限制,如果访问量超过了系统的最大处

理能力,就会丢弃一部分的用户请求,保证整个系统可用,保证大部分用户是可以访问

系统的。这样虽然有一部分用户的请求被丢弃,产生了部分不可用,但还是好过整个系

统崩溃,所有的用户都不可用要好。

限流的几种算法


  • 计数器算法(固定窗口,滑动窗口) • 令牌桶算法


  • 漏桶算法


计数器(固定窗口)算法


使用计数器在周期内累加访问次数,当达到设定的限流值时,触发限流策略。下一个周期开始

时,进行清零,重新计数。

固定窗口算法的临界点问题:假设 1min 内服务器的负载能力为 100,因此一个周期的访问量限

制在 100,然而在第一个周期的最后 5 秒和下一个周期的开始 5 秒时间段内,分别涌入 100 的访问

量,虽然没有超过每个周期的限制量,但是整体上 10 秒内已达到 200 的访问量,已远远超过服务

器的负载能力


计数器(滑动窗口)算法


将时间周期分为 N 个小周期,分别记录每个小周期内访问次数,并且根据时间滑动删除

过期的小周期。

假设时间周期为 1min,将 1min 再分为 2 个小周期,统计每个小周期的访问数量,则可以

看到,第一个时间周期内,访问数量为 75,第二个时间周期内,访问数量为 100,超过

100 的访问则被限流掉了


令牌桶算法


以固定的速度向令牌桶中增加令牌,直到令牌桶满,请求到达时向令牌桶请求令牌,如

获取到令牌则通过请求,否则触发限流策略


漏桶算法


访问请求到达时直接放入漏桶,如当前容量已达到限流值,则进行丢弃。漏桶以固定的

速率进行释放访问请求,直到漏桶为空。


自适应限流


没有提前的人工评估, 便没有提前的评估过时与人的评估疏漏/错误 ! • 实时自动评估 QPS

  • 业务流量的不确定性与技术方案的自适应性天生一对!


降级


有一些系统功能是非核心的,但是它也给系统产生了非常大的压力,比如说在电商系统

中有确认收货这个功能,即便我们不去确认收货,系统也会超时自动确认收货。

但实际上确认收货这个操作是一个非常重的操作,因为它会对数据库产生很大的压力:

它要进行更改订单状态,完成支付确认,并进行评价等一系列操作。如果在系统高并发

的时候去完成这些操作,那么会对系统雪上加霜,使系统的处理能力更加恶化。

解决办法就是在系统高并发的时候,比如说像淘宝双 11 的时候,当天可能整天系统都处

于一种极限的高并发访问压力之下,这时候就可以将确认收货、评价这些非核心的功能

关闭,将宝贵的系统资源留下来,给正在购物的人,让他们去完成交易。


异地多活


如果整个数据中心都不可用,比如说数据中心所在城市遭遇了地震,机房遭遇了火灾或

者停电,这样的话,不管我们的设计和系统多么的高可用,系统依然是不可用的。

为了解决这个问题,同时也为了提高系统的处理能力和改善用户体验,很多大型互联网

应用都采用了异地多活的多机房架构策略,也就是说将数据中心分布在多个不同地点的

机房里,这些机房都可以对外提供服务,用户可以连接任何一个机房进行访问,这样每

个机房都可以提供完整的系统服务,即使某一个机房不可使用,系统也不会宕机,依然

保持可用。

异地多活的难点是数据一致。


二、请用你熟悉的编程语言写一个用户密码验证函数,Boolean checkPW(String 用户 ID,String 密码明文,String 密码密文),返回密码是否正确 boolean 值,密码加密算法使用你认为合适的加密算法。


 public boolean checkPW(String userId, String pwd, String pwdEncode) {
boolean b = StringUtils.isEmpty(userId) || StringUtils.isEmpty(pwd) || StringUtils.isEmpty(pwdEncode);
if (b) {
return false;
}
String solt = getSoltByUserId(userId);
if (StringUtils.isEmpty(solt)) {
return false;
}
if (!pwdEncode.equals(SecureUtil.md5(pwd + solt))) {
return false;
}
return true;
}
复制代码


用户头像

feiyun123

关注

还未添加个人签名 2019.09.28 加入

还未添加个人简介

评论

发布
暂无评论
第十一周 安全稳定 作业 「架构师训练营 3 期」