系统高可用及密码验证算法

本文是架构师训练营第11周课后作业。作业原题是:

  1. 导致系统不可用的原因有哪些?保障系统稳定高可用的方案有哪些?请分别列举并简述。
  2. 请用你熟悉的编程语言写一个用户密码验证函数,Boolean checkPW(String 用户 ID,String 密码明文,String 密码密文)返回密码是否正确 boolean 值,密码加密算法使用你认为合适的加密算法。

第一题

对于导致系统不可用原因,可以从以下几方面进行分析:硬件故障、软件 BUG、系统发布、并发压力、网络攻击和外部灾害等。

为保障系统稳定高可用,可使用以下解决方案。

1、解耦——高内聚低耦合的组件设计原则,面向对象设计原则,面向对象设计模式,领域驱动设计建模使代码边界更清晰,且可扩展性可维护性更好,能快速分析问题产生原因并解决。

2、隔离——业务与子系统隔离,微服务与中台架构,生产者消费者隔离,虚拟机与容器隔离,需要注意的是,解耦是逻辑层面,隔离是物理层,以防止问题扩散开来。

3、异步——多线程编程,反应式编程,异步通信网络编程,事件驱动异步架构,如果部分失败再通过补偿系统或机制进行处理,整个系统还能保持可用。

4、备份(冗余)——集群,数据库复制,互联网中任何一个服务器不能是单点(例如 Doris 的管理控制台没有做备份,当管理控制台失效的时候,并不影响系统的正常运行)

5、Failover(失效转移)——数据库主主失效转移,负载均衡失效转移,数据库主主由外部服务器去确认谁是 master,比如 Zookeeper。而Zookeeper 通过自身集群策略提供高可用。

6、幂等——事件失败的时候可重复提交。

7、事务补偿——执行业务逻辑逆操作,使事务回滚到事务前状态。

8、重试——远程服务可能会由于线程阻塞、垃圾回收或者网络抖动,而无法及时返回响应,调用者可以通过重试的方式修复单次调用的故障。上游调用者超时时间要大于下游调用者超时时间之和。

9、熔断——当某个服务出现故障,响应延迟或者失败了增加,继续调用整个服务会导致调用者请求阻塞,资源消耗增加,进而出现服务级联失效,这种情况下使用断路器阻断对故障服务的调用。断路器三种状态:关闭,打开,半开。

10、限流——高并发场景,访问量超过了系统的承受力,可以通过限流进行保护。限流会丢弃部分用户的请求,以保证整个系统的可用,保证大部分用户可以访问。丢车保帅的做法。 限流算法:计数器(固定窗口)算法,计数器(滑动窗口)算法,令牌桶算法(固定速率生产),漏桶算法(固定速率消费),自适应限流(实时自动评估QPS,业务流量的不确定性)

11、降级——某些非核心功能也会给系统产生非常大的压力,比如电商的确认收货功能,即便不主动确认收货,系统也会到时自动确认收货。比如像淘宝双11的时候,可以采用将确认收货、评价这些非核心功能关闭的降级策略,降低低价值的资源消耗。

12、异地多活——前面的方法主要针对系统层面的,异地多活主要针对系统外部的不可控因素。比如地震、火灾、停电、战争地区。例如维基百科三个数据中心:澳大利亚,韩国,欧洲。

第二题

由于我对 C# 比较熟悉,现使用 C# 基于 AES 算法实现密码校验,附上关键代码。

class Program 
{ 
   static void Main(string[] args) 
   { 
       var userId = "123456"; 
       var passwordText = "admin123"; 
       var passwordSecret = "arbn4YMOwvQM9F+ROPjpcg=="; 
       var checkResult = CheckPassword(userId, passwordText, passwordSecret); 
       if (checkResult) 
       { 
           Console.WriteLine("密码校验正确"); 
       } 
       else 
       { 
           Console.WriteLine("密码校验错误!"); 
       } 
       Console.ReadLine(); 
   } 
   /// <summary> 
   /// 验证密码是否正确 
   /// </summary> 
   /// <param name="userId">用户Id</param> 
   /// <param name="plainText">密码明文</param> 
   /// <param name="secretText">密码密文</param> 
   /// <returns></returns> 
   static bool CheckPassword(string userId, string plainPassword, string secretPassword) 
   { 
       var salt = "gsKxGZ012HLL3MI5";  //盐 
       var key = $"{userId}-{salt}"; 
       var keyByte = Encoding.UTF8.GetBytes(ToMd5(key)); 
       var plainPasswordByte = Encoding.UTF8.GetBytes(plainPassword); 
       using (var symmetricKey = new RijndaelManaged()) 
       { 
           symmetricKey.Key = keyByte; 
           symmetricKey.Mode = CipherMode.ECB; 
           symmetricKey.Padding = PaddingMode.PKCS7; 
           using (var encryptor = symmetricKey.CreateEncryptor()) 
           { 
               var resultByte = encryptor.TransformFinalBlock(plainPasswordByte, 0, plainPasswordByte.Length); 
               var resultSecret = Convert.ToBase64String(resultByte, 0, resultByte.Length); 
               return secretPassword == resultSecret; 
           } 
       } 
   } 
   /// <summary> 
   /// 转化为MD5 
   /// </summary> 
   /// <param name="text">字串</param> 
   /// <returns></returns> 
   static string ToMd5(string text) 
   { 
       using (var md5 = MD5.Create()) 
       { 
           var inputBytes = Encoding.UTF8.GetBytes(text); 
           var hashBytes = md5.ComputeHash(inputBytes); 
           var sb = new StringBuilder(); 
           foreach (var hashByte in hashBytes) 
           { 
               sb.Append(hashByte.ToString("x2"));//x2为小写32位,X2为大写32位 
           } 
           return sb.ToString(); 
       } 
   } 
}

《系统高可用及密码验证算法》的相关评论

发表评论

必填项已用 * 标记,邮箱地址不会被公开。