一、架构师需要解决的主要问题:
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等。