第9章 高可用与稳定性 "高并发" 是为了让系统变得 "有效率",高可用和稳定是是为了让系统变得 "更稳定"。9.1 多副本 对于网关和应用服务器这种无状态的服务,做多副本比较简单,加机器就行;但对于缓存和数据库这种有状态的,如果做多个副本,会存在数据同步问题。1.本地缓存多副本一种常用的方法是利用消息中间件(如kafka)的Pub/Sub机制,每台机器都订阅消息。一条消息发送出去,每台机器都会收到这台消息,然后更新自己的本地缓存。2.Redis多副本Redis Cluster 提供了 master-slave 之间的复制机制,当master宕机后可以切换到slave。当然,切换需要间隔时间(一般为十几秒),同时因为是异步复制,切换之后可能会丢失少量的数据。如果是宕机redis,则需要业务人员自己部署两套,自己做双写和切换。补充:无论是本地缓存,还是redis集中式缓存,既然本身的定位是 "缓存",意味着业务场景对数据不是强一致性的要求,所以此处主要考虑的是 "高可用性",而没有数据一致性的保证。3.MySQL多副本对于mysql,master-slave 之间用的最多的是异步复制或半异步复制,同步复制性能太差。对于异步复制,如果slave超时后还未返回,也会退化为异步复制。所以,无论是异步复制,还是半异步复制,都不能百分百的保证master和slave中的数据完全一致。实际上,一般都会选择牺牲一定的数据一致性来保证可用性。少量的数据不一致,可以通过后续的人工修复解决;如果服务不可用,尤其在流量大的时候,带来的损失往往远大于少量数据不一致的损失。另外,还会有一些监控,如果发现某个slave延迟太大,则直接摘除,避免延迟太大的slave被选为主库。4.消息中间件多副本对于kafka类的消息中间件,一个 Partition 通常至少会指定三个副本,为此kafka专门设计了一种 ISR 的算法,在多个副本之间做消息的同步。9.2 隔离、限流、熔断和降级 1.隔离隔离是指将系统或资源分隔开,在系统发生故障时能够限定传播范围和影响范围,即发生故障后不会出现滚雪球效应,从而把故障的影响限定在一个范围内。1.数据隔离从数据的重要性角度来说,一个公司或业务的数据肯定有非常重要,次重要,不重要之分,在数据库的存储中,把这些数据所在的物理库彻底分开。这也对应着业务的拆分和分库。从这个角度来说,业务的拆库和数据的隔离,其实是从不同的角度说同一个事情。2.机器隔离对一个服务来说,有很多调用者。这些调用者也有一个重要性等级排序。对于那些最核心的几个调用者,可以专门为其准备一组机器,这样其他的调用者不会影响该调用者的服务。又或者,本来是一个核心服务,因为某种原因在上面增加了一个新功能(新接口),这个新功能只是为某个调用方使用,可以把调用方隔离出来,不影响现有功能。成熟的RPC框架往往有隔离的功能,根据调用方的标识(ID),把来自某个调用方的请求都发送到一组固定的机器中,无需业务人员写代码,用一个简单的配置即可搞定。3.线程池隔离首先要注意设置客户端的超时时间,如果超时时间很长,一旦某个服务延迟很大,就容易打垮服务。为此,可以使用线程池隔离,为每个rpc调用单独准备一个线程池(一般2~10个线程)。当线程池中没有空闲线程,并且线程池内部的队列已经满了的情况下,线程池会直接抛出异常,拒绝新请求,从而保证线程不会被阻塞。还有一个场景,比如一个rpc服务对外提供了很多接口,绝大部分接口都处理的很快,有极个别接口的业务逻辑很复杂,处理的很慢,则在rpc服务内部可以为其准备单独的一个线程池。这样一来,虽然这个接口很慢,但只是它自己慢,不会影响其他。4.信号量隔离信号量隔离是 Hystrix 提出的另外一种隔离方法,它比线程池隔离要轻量。一个机器能开的线程数是有限的,线程池太多会导致线程太多,线程切换的开销很大。而使用信号量隔离不会额外增加线程池,只在调用线程内部执行。信号量本质上是一个数字,记录了当前访问某个资源的并发线程数,在线程访问资源之前获得该信号量,当访问结束时,释放信号量。一旦信号量达到最大的阈值,线程获取不到该信号量,会丢弃请求,而不是阻塞在那里等待信号量。2.限流限流可以分为技术层面的限流和业务层面的限流。技术层面的限流比较通用,各种业务场景都可以用到;业务层面的限流需要根据具体的业务场景做开发。1.技术层面的限流一种是限制并发数,也就是根据系统的最大资源进行限制,比如数据库连接池,线程池,nginx的 limit_conn模块;另外一种是限制速率(qps),比如Guava的RateLimiter,nginx的 limit_req 模块。限制速率的这种方式对于服务的接口调用非常有用。比如通过压力测试可以知道服务的qps是2000,就可以限流为2000qps。当调用方超过了这个数字,会直接拒绝提供服务。这样一来,即使突然有大量请求进来,服务也不会被压垮,虽然部分请求被拒绝了,但保证了其他服务正常运行。2.业务层面的限流比如秒杀系统,一个商品的库存只有100件,现在有2w人抢购,没必要放2w人进来,只需要放前500个进来,后面的人直接返回已售完即可。针对这种场景,可以做一个限流系统,或者叫售卖的资格系统(票据系统),票据系统放了500张票,每来一个人,领一张票据。领到票据的人进入后面的业务系统进行抢购;对于抢不到的人,则返回售完。在具体实现上,有的用redis,有的用nginx+lua。3.限流算法限制并发数的计算原理很简单,系统只需要维护正在使用的资源数或空闲数,比如数据库的连接数,线程池的线程数。限制速率的算法稍微复杂点,常用的有漏桶算法和令牌桶算法。漏桶算法:1.漏桶的容量是固定的,流出的速率是恒定的;2.流入的速率是任意的;3.如果桶是空的,则不需流出;4.如果流入的数据包超出了桶的容量,则流入的数据包溢出了(被丢弃),而漏桶的容量不变。令牌桶算法:1.令牌桶的容量也是固定的,向里流入令牌的速率是恒定的;2.当令牌桶满时,新加入的令牌会被丢弃;3.当一个请求达到后,从桶中取出一个令牌。如果能取到令牌,则处理该请求;4.如果取不到令牌,则该请求要么被丢弃,要么排队。区别:对比两个算法会发现,二者的原理刚好相反,一个是流出速率保持恒定,一个是流入速率保持恒定。二者的用途有一定区别,令牌桶限制的是平均流入速率,而不是瞬时速率,因为可能出现一段时间没有请求来,令牌桶塞满了令牌,然后短时间突发流量过来,一瞬时从桶里拿几个令牌出来;漏桶有点类似于消息队列,起到了削峰的作用,平滑了突发流入速率。3.熔断熔断有两种策略:1.一种是根据请求失败率对于客户端调用的某个服务,如果服务在短时间内大量超时或者抛错,则客户端直接开启熔断,也就是不再调用此服务。然后过了一段时间,再把熔断打开,如果还是不行,则继续熔断。这就是 "快速失败(Fail Fast)" 策略。2.一种是根据请求响应时间当资源的平均响应时间超过阈值后,资源进入准降级状态。接下来如果持续进入5个请求,且他们的RT持续超过该阈值,那么在接下来的时间窗口内,对这个方法的调用都会自动的返回。与限流对比:限流是服务端限流,根据其能力上限设置一个过载保护;而熔断是调用端对自己做的一个保护。能熔断的服务肯定不是核心链路上的必选服务。如果是的话,则服务如果超时或者宕机,前端就不能用了,而不是熔断。所以,说熔断其实也是降级的一种方式。4.降级降级是一种兜底的方案,是在系统出故障之后的一个尽力而为的措施。相比限流,熔断两个偏技术的词汇,降级则是一个更加偏业务的词汇。因为在现实中,虽然任何的一个业务或者系统都有很多功能,但并不要求这些功能一定100%可用,或者完全不可用。其中存在一定的灰度空间。比如对于微信或者QQ,有文字通信,语音通信,视频通信,对带宽的要求是从小到大。网络发生故障时,可以优先保证文字通信可用。总之,会尽最大的努力提高服务,哪怕是有损服务,也比完全不提供服务强。还有电商的千人前面,可能靠的是推荐系统。如果推荐系统挂了,可以准备一个静态的商品列表。降级不是一个纯粹的技术手段,而是根据业务场景具体分析,看哪些功能可以降级,降级到什么程度,哪些宁愿不可用也不能降级。9.3 灰度发布与回滚 如果一个系统在线上的代码不动,不更新,理论上可以稳定的一直运行下去。频繁的变更是导致系统不稳定的一个直接因素。既然无法避免系统变更,我们能做的就是让这个过程
尽可能的 平滑,受控,这就是灰度与回滚策略。1.新功能上线的灰度当一个新功能上线时,可以先将一部分流量导入这个新的功能,如果验证没有问题,再一点点增加流量,最终让所有流量都切换到这个新功能上。具体办法有很多,比如可以按 user_id 划分流量,按 user_id 的最后几位数字对用户进行分片,一片片的灰度把流量导入到新功能上;或者用户有很多属性,标签,按其中的标签设置用户白名单,再一点点导入流量。2.旧系统重构的灰度同上。3.回滚一种是安装包回滚,这种办法比较简单,不需要额外开发代码,发现线上有问题,统一部署之前的安装版本;另一种是功能回滚,在开发新功能的时候,也开发了相应的配置开关,一旦有问题,则关闭开关,让所有流量都进入老的系统。9.4 监控体系与日志报警 1.监控体系1.资源监控   如cpu,内存,磁盘,带宽,端口等。2.系统监控如:1.最前端url访问的失败率以及具体某次访问的失败链路;2.rpc接口的失败率以及具体某次请求的失败链路;3.rpc接口的平均响应时间,最大响应时间,95线,99线;4.db 的 long sql;5.如果使用的是 Java,JVM的 young GC,full GC 的回收频率,回收时间等。3.业务监控根据业务具体分析。把业务系统再扩展一下,就变成了对账系统。2.日志报警如果说业务指标的监控是基于统计数据的一个监控,日志报警则是对某一次具体的请求的处理过程的监控。在输出日志的过程中,最容易出现的问题可能有:1.日志等级不分2.关键日志漏打

9.软件架构设计:大型网站技术架构与业务架构融合之道 --- 高可用与稳定性相关推荐

  1. 软件架构设计 大型网站技术架构与业务架构融合之道

    前言 架构是一种综合能力,而不是某一方面的技能.也正因为如此,本书提供的是一个全面的解决方案.方法论.成体系的设计思维.因此,本书将从基础技术谈起,再到高层技术.再到业务.管理,提供一个架构能力的全局 ...

  2. 读书笔记 之《软件架构设计: 大型网站技术架构与业务架构融合之道》

    大家好呀,我是小菜~ 帅哥美女,知道你们时间宝贵,那么就由小菜为你读好一本书,读一本好书,取其精华,与你共享~! 本文主要分享 <软件架构设计:大型网站技术架构与业务架构融合之道> 如有需 ...

  3. 读书笔记-大型网站技术架构

    1. 大型网站架构演化 1.1 大型网站软件系统的特点 大型互联网应用系统的特点 -高并发,大流量 -高可用 -海量数据 -用户分布广泛,网络情况复杂 -完全环境恶劣 -需求快速变更,发布频繁 -渐进 ...

  4. 大型网站的演化之路——读《大型网站技术架构》

    大型网站的演化之路--读<大型网站技术架构> ____ author:姚毛毛的博客 & 妖生 01 大型网站or软件有什么特点? 高并发.大流量,微信都日活10亿了 7×24的高可 ...

  5. 大型网站技术架构核心原理剖析,文末附知识图谱下载

    什么是软件架构 维基百科定义:软件架构是指有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计. 软件架构5大要素: 性能 可用性 伸缩性 扩展性 安全性 可以通过考察这5大要素来衡量 ...

  6. 《大型网站技术架构:核心原理与案例分析》

    大型网站架构演化 大型网站软件系统的特点 大网站架构演化发展历程 初始阶段的网站架构 应用服务和数据服务分离 使用缓存改善网站性能 使用应用服务器集群改善网站的并发处理能力 数据库读写分离 使用反向代 ...

  7. 《大型网站技术架构》《K8S进阶实战》等书籍!送45本!读完工资多个0!

    学习如逆水行舟,不进则退.所以又来给各位读者送书了,这次送45本技术书,内容涉及深度学习.Python.Dubbo.Flutter等. 感谢本次活动的赞助商『电子工业出版社博文视点』 另外!急于购书的 ...

  8. 小白入门:大型网站技术架构负载均衡技术介绍及学习资源推荐

    十年间,负载均衡的前沿技术层出不穷,令用户眼花缭乱.经常在技术网站.文档中出现的"四层负载均衡"."七层负载均衡"字眼有什么含义?有什么区别?对客户网络有哪些不 ...

  9. 读书笔记-大型网站技术架构(核心原理与案例分析)

    一.大型网站架构演化 1.1 大型网站软件系统的特点 高并发.大流量:高可用:海量数据:用户分布广泛,网络情况复杂:安全环境恶劣:需求快速变更,发布频繁:渐进式发展: 1.2 大型网站架构演化发展历程 ...

  10. 大型网站技术架构:核心原理与案例分析阅读笔记二

    大型网站技术架构:核心原理与案例分析阅读笔记二 网站架构设计时可能会存在误区,其实不必一味追随大公司的解决方案,也不必为了技术而技术,要根据本公司的实际情况,制定适合本公司发展的网站架构设计,否则会变 ...

最新文章

  1. python encoding报错_python用requests递归查询页面 报错 ChunkedEncodingError
  2. Flask之DButils
  3. 【错误记录】Android Studio 编译报错 ( VirtualApp 编译 NDK 报错 | Error:A problem occurred configuring project ‘: )
  4. CV-机器视觉、图像处理方面的书籍
  5. HTML第十章作业代码,HTML教程10第十章.doc
  6. 核心动画03-图标抖动.mp4
  7. mysql upload_关于mysql数据库里的 upload子查询问题
  8. php将文件夹压缩成zip文件,将文件夹压缩成zip文件的php代码_php实例
  9. mysql shell
  10. pythonweb接口优化_python-web后台限制接口调用频率
  11. Convolutional Neural Networks卷积神经网络(二)
  12. delphi 7 mdi子窗体。。。无法更改以命令对象为源的记录集对象的 ActiveConnection 属性。...
  13. html5 figure 标签
  14. Flink学习之flink sql
  15. linux系统下安装oracle客户端
  16. Delphi学习第二课
  17. css面试精讲之防止高度坍塌的4种方式
  18. Linux添加路由的方法
  19. 派生类的构造函数xu(c++)
  20. 507 Lusir的游戏 二分 数论 [代码源][namomo spring camp]每日一题div2

热门文章

  1. 【BZOJ2655】—calc(拉格朗日插值+生成函数+dp)
  2. es elasticsearch-head安装
  3. 06.Android之消息机制问题
  4. Java实现文件批量重命名
  5. 【OPPO主题制作系列 - 01】-- 写个小工具自动打包Theme文件
  6. 【转】JMeter学习(十八)JMeter测试Java(二)
  7. 1006 小明与隔壁老王之间不得不说的故事(简单)
  8. Premiere Pro After Effects插件开发调试方法
  9. halcon学习笔记——(6)单摄像机标定
  10. 在线订餐系统php心得体会_基于php的网上订餐系统的设计与实现论文.doc