关于构建一个高可用性系统的一些措施
1、何为高可用性系统
高可用性系统是指一个系统经过专门的设计,从而达到最长使用时间,最少停机时间,保持其高度可用性。一般的标准有几个九来表示。当九越多,系统的高可用性系统越高。
2、如何去建设一个高可用性系统
建设高可用性系统主要分为两个方面考虑,第一,提高系统自身的性能(内功);第二提高系统的防御能力。
内功:
1)主要有防止缓存穿透或者雪崩。
2)然后编写代码时提高编码质量,减少bug;并且提高测试质量,压测、自动化测试等。
3)最后发布时采用灰度发布,灰度发布是在黑与白之间,发布完成后先使一部分用户先使用新代码,没有问题后在过渡到所有用户。
4)对于机器或者机房宕机的话,采用多机房、多部署方式。
5)对于突增大流量或者秒杀这种活动,通常采用限流的方式。
6) 依赖服务故障,采用解耦的方式,比如采用消息中间件来实现解耦功能。
7)其他还有降级、熔断等方式。
3、具体分析一下各种方式
缓存 :缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;
防止缓存穿透和雪崩:
使用双缓存、缓存失效时间或者互斥锁;具体的实现方式见https://www.cnblogs.com/yebingluo/p/10153468.html。
扩展:
垂直扩展:在同一逻辑单元增加资源提升系统处理能力。比如机器内存不够,就为机器增加内存。这种方法比较简单,但是不能解决单点故障问题。
水平扩展:通过增加多个相同的逻辑单元,我理解是部署在多台机器上,一台机器出现了故障,另一台机器可以继续工作。该种方式解决了单点问题也提升了系统处理能力,但是比较复杂,维护也比较麻烦,设计分布式的一些问题。比如常我们在部署应用服务器的时候,都会部署多台,然后使用 nginx 来做负载均衡,nginx 使用心跳机制来检测服务器的正常与否,无响应的服务就从集群中剔除。这样的集群中每台服务器的角色是相同的,同时提供一样的服务。 然后数据库会采用主从分离,写操作只发生在主库,并且主库宕机后,多个从库中的一个从库可以升级成为主库。
隔离:是对业务和系统所占的资源进行隔离,防止一个业务占用了太多的资源。隔离分为:线程池隔离,不同的业务使用不同的线程池,避免低优先级的任务阻塞高优先级的任务。或者高优先级的任务过多,导致低优先级任务永远不会执行 ;进程隔离;机房隔离:为了避免单个机房网络问题或断电;读写隔离:一方面,将对实时性要求不高的读操作,放到 DB 从库上执行,有利于减轻 DB 主库的压力。另一方面,将一些耗时离线业务 sql 放到 DB 从库上执行,能够减少慢 sql 对 DB 主库的影响,保证线上业务的稳定可靠。
解耦:对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护成本越高,因此对象的设计应使模块之间的耦合度尽量小。解耦一般有两种方法;第一是模块之间通过接口交互,这样方式,只要约定接口的参数和返回值不变,其他的内容变化都不会影响接口的使用。第二是通过消息中间件的方式,将同步调用改为异步调用,比如借钱流程,将放款的结果通过mq消息发送给调用方。常用的消息中间件为kafka和RabbitMQ以及RocketMQ。
限流:限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页或告知资源没有了)、排队或等待(比如秒杀、评论、下单)、降级(返回兜底数据或默认数据,如商品详情页库存默认有货)。常用的限流有漏斗桶算法、令牌桶算法、滑动窗口计数法等。
降级:业务降级,是指牺牲非核心的业务功能,保证核心功能的稳定运行。简单来说,要实现优雅的业务降级,需要将功能实现拆分到相对独立的不同代码单元,分优先级进行隔离。在后台通过开关控制,降级部分非主流程的业务功能,减轻系统依赖和性能损耗,从而提升集群的整体吞吐率。
降级往往需要兜底方案的配合,比如系统不可用的时候,对用户进行提示,安抚用户。提示虽然不起眼,但是能够有效的提升用户体验。
熔断:我理解是程序出现了问题,暂时性关闭程序通过某种熔断框架来操作,等解决问题后打开。
重试:超时和失败重试
测试:模块级自动化测试,减少bug数量。
灰度发布 & 回滚
总结:
技术 | 解决什么问题 |
---|---|
扩展 | 通过冗余部署,避免单点故障 |
隔离 | 避免业务之间的相互影响 2. 机房隔离避免单点故障 |
解耦 | 减少依赖,减少相互间的影响 |
限流 | 遇到突发流量时,保证系统稳定 |
降级 | 牺牲非核心业务,保证核心业务的高可用 |
熔断 | 减少不稳定的外部依赖对核心服务的影响 |
自动化测试 | 通过完善的测试,减少发布引起的故障 |
灰度发布 | 灰度发布是速度与安全性作为妥协,能够有效减少发布故障 |
4、补充一下与高可用系统息息相关的高吞吐量系统
如何构建一个高吞吐量的系统呢,主要有三点:1、缓冲 2、缓存 3、对象复用(数据库连接池等)