架构之路

一、架构师需要解决的主要问题:

1.1 服务拆分和集群架构

随着系统复杂的加剧,为了降低业务耦合,提高容错性,滤清职责,避免冗余,而提出服务拆分,如比较火的为服务架构。服务拆分的代价,如分布式事务,服务治理,服务监控等问题。

1.2 服务治理和RPC的使用

目前比较流行的服务治理框架(服务注册发现,服务扩容,服务升级和降级)有Spring Cloud和Dubbo等,但是要解决这些框架的服务超时和重试等引起的系统雪崩。

1.3 服务调用跟踪问题

a.跟踪每一次请求的这个调用链;
b.收集调用链上每个服务的执行耗时,整合各个服务的日志。

为避免对业务代码的侵入和性能的影响,一般采用Filter拦截器和异步实现。另外要实现监控界面可视化和数据分析时效性。目前有EagleEye,Watchman,Hydra和Zipkin等。

二、流量控制

流量控制保护系统的可用性,让系统的负载处于比较平衡的状态,采用合理有效的方式控制用户流量,避免影响用户体验。常用的限流算法:

2.1 计数器算法

如数据库连接池,线程池和对象池等。

2.2 令牌桶算法

a.每秒有R个令牌被放入桶中;
b.桶的容量固定不变,当桶满了之后则溢出;
c.当有n个令牌到达时,而桶中剩下的令牌小于n时,该报将会被限流处理,如抛弃或缓存。

举例:Nginx的限流模块,Google Guava的RateLimiter的类。

2.3 漏桶算法

a.可以以任意的速率流向桶中;
b.桶的容量不变,当桶满了,则新流入的被丢弃;
c.按照固定的速率从桶中流出。

2.4 服务降级

服务降级的目的是保证核心服务可用,即使有可能是部分可用的,相当于丢车保帅。比如访问超时时,或者错误率太高等情况时使用。

常见情况:
a.在cache+DB架构下,当DB有问题时,可以让服务只读cache,当cache也不可用时,返回默认值;
b.在cache+DB架构下,当DB有问题时,可以让服务只写cache,最后异步将cache同步到DB,保证最终一致性;
c.在渲染页面时,一些不重要的展示(广告,推荐页等)可以获取,直接降级。
d.在访问量比较高时,可以拒绝给某些优先级较低的用户拒绝访问(如非VIP、爬虫或者机器访问)。

降级方式:
a.访问超时降级;
b.统计失败次数降级;
c.服务故障降级;
d.限流降级,即并发量超过阀值时,后续请求被降级。

2.5 服务熔断

在一个时间窗口内的熔断判断逻辑(以Hystrix为例):

getRequest(); // 拿到请求
if(如果已经熔断) {
    执行熔断降级处理
} else {
    采样判断是否需要熔断
    if(采样总数小于规定阀值) {
       正常执行
    } else if(当前采样错误率小于阀值) {
        正常执行
    } else if (当前采样失败率超过规定阀值) {
       执行熔断降级处理
    }
}

当过了这个时间周期之后,进行重新采样,然后请求测试,如果测试成功,则关闭熔断,否则持续熔断,这样就实现了快速失败和快速恢复。

采样信息:
采样信息保存到内存中,记录一定时间窗口内(如10秒)内的失败次数,超时次数,成功次数,拒绝访问次数,并发次数,延时百分百等。假如统计N组数据,始终保持这N组数据是最新的(即采取FIFO的算法模式)。

2.5 超时和重试

不设置超时时,在相应比较慢时,会导致满请求的累积效应,甚至会导致整个服务雪崩;而服务重试(适合幂等性服务,如读服务,非幂等性,如写,应避免重试),成倍地增加了访问量,特别是访问压力比较大时,有意无意的形成了DDOS攻击,最后导致服务不可用。因此一定要配合超时,重试和熔断等配合在整条链路上使用。

三、削峰

针对峰值流量进行分散处理,避免在同一时间段内产生较大的用户流量冲击,从而降低系统的负载压力。

常用的削峰方法有:

1.分时段;

将一个峰值,分配到多个时段。如12306网站进行分段放票。

2.验证码;

输入验证码,如12306的图片验证。

3.使用MQ异步调用

常用的MQ工具有,轻量级的ActiveMQ,RocketMQ,Kafka,RabbitMQ等。

4.热点数据自动发现

通过对实时埋点数据或者日志访问,统计调用次数和热点分析,然后做热点数据保护。

5.使用乐观锁

使用乐观锁可以避免数据库的行级锁,导致事务的串行执行。
具体逻辑如下:

select stock,version from products where product_id = 1
if(商品存在) {
    if(stock >= 要购买的个数n) {
   update products set version = ${version} + 1,stock=stock-n where product_id = 1 and version = ${version}

if(error) {
 retry
} else {
return 购买成功
}

    } else {
  return 商品无货
}
}


6.使用分布式缓存

将DB中的数据同步到redis中,引入分布式锁来保证事务性。针对redis的修改,可以通过MQ同步到DB中。

7.采取批量更新

针对行级的高并发修改,可以收集业务请求,然后达到阀值(如100)后,再做合并处理,这样大大降低了锁的次数。AliSQL的秒杀场景就使用了该方法,。

四、配置管理

配置管理需要实现界面化,变更可订阅,容灾机制
常用的配置管理工具有Zookeeper,Diamond、Disconf、QConf和Spring
Cloud等。

五、分布式缓存

缓存工具有Redis,Memcache,Tair,CKV等。

六、分库分表

常用分库分表工具,Atlas,Cobar,MyCat(支持分库,分表,读写分离),TDDL,Shark,JDBC-Sharding(支持分库,分表,读写分离)等,以及Canal基于MySql的binlog的增量订阅和消费组件,Canal有主备架构。

七、服务监控

常用的监控工具有Cacti,分布式监控工具Zabbix等。

架构中的各性能耗时图解.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容