都是套路:高并发系统的降级特技

标签: 运维经验 高并发系统 | 发表时间:2016-07-28 04:03 | 作者:小码哥
分享到:
出处:http://www.yunweipai.com

作者简介:

张开涛

京东集团技术研发,2014年加入京东,开发过京东商品详情页、详情页统一服务架构与开发工作,设计并开发了多个亿级访问量系统。

工作之余喜欢写技术博客,有《跟我学 Spring》、《跟我学Spring MVC》、《跟我学Shiro》、《跟我学Nginx+Lua开发》等系列教程。

开篇:

在开发高并发 系统时有三把利器用来保护系统:缓存、降级和限流。之前已经有一些文章介绍过缓存和限流了。本文将详细聊聊降级。

当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。

系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。本文将介绍一些笔者在实际工作中遇到的或见到过的一些降级方案供大家参考。

降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

降级预案

在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:

一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;

警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;

错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;

严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

降级的类别

  • 降级按照是否自动化可分为:自动开关降级和人工开关降级。
  • 降级按照功能可分为:读服务降级、写服务降级。
  • 降级按照处于的系统层次可分为:多级降级。

降级的功能点

降级的功能点主要从服务端链路考虑,即根据用户访问的服务调用链路来梳理哪里需要降级:

页面降级:在大促或者某些特殊情况下,某些页面占用了一些稀缺服务资源,在紧急情况下可以对其整个降级,以达到丢卒保帅;

页面片段降级:比如商品详情页中的商家部分因为数据错误了,此时需要对其进行降级;

页面异步请求降级:比如商品详情页上有推荐信息/配送至等异步加载的请求,如果这些信息响应慢或者后端服务有问题,可以进行降级;

服务功能降级:比如渲染商品详情页时需要调用一些不太重要的服务:相关分类、热销榜等,而这些服务在异常情况下直接不获取,即降级即可;

读降级:比如多级缓存模式,如果后端服务有问题,可以降级为只读缓存,这种方式适用于对读一致性要求不高的场景;

写降级:比如秒杀抢购,我们可以只进行Cache的更新,然后异步同步扣减库存到DB,保证最终一致性即可,此时可以将DB降级为Cache。

爬虫降级:在大促活动时,可以将爬虫流量导向静态页或者返回空数据从而降级保护后端稀缺资源。

降级策略

1、自动开关降级

自动降级是根据系统负载、资源使用情况、SLA等指标进行降级。

超时降级

当访问的数据库/http服务/远程调用响应慢或者长时间响应慢,且该服务不是核心服务的话可以在超时后自动降级;

比如商品详情页上有推荐内容/评价,但是推荐内容/评价暂时不展示对用户购物流程不会产生很大的影响;

对于这种服务是可以超时降级的。如果是调用别人的远程服务,和对方定义一个服务响应最大时间,如果超时了则自动降级。

之前总结过一些的文章《使用httpclient必须知道的参数设置及代码写法、存在的风险》和《dbcp配置及jdbc超时设置总结》。在实际场景用一定主要配置好超时时间和超时重试次数和机制。

统计失败次数降级

有时候依赖一些不稳定的API,比如调用外部机票服务,当失败调用次数达到一定阀值自动降级;然后通过异步线程去探测服务是否恢复了,则取消降级。

故障降级

比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。

降级后的处理方案有:

默认值(比如库存服务挂了,返回默认现货)

兜底数据(比如广告挂了,返回提前准备好的一些静态页面)

缓存(之前暂存的一些缓存数据)

限流降级

当我们去秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时开发者会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;

降级后的处理方案可以是:

排队页面(将用户导流到排队页面等一会重试)

无货(直接告知用户没货了)

错误页(如活动太火爆了,稍后重试)

2、人工开关降级

  • 在大促期间通过监控发现线上的一些服务存在问题,这个时候需要暂时将这些服务摘掉;
  • 还有有时候通过任务系统调用一些服务,但是服务依赖的数据库可能存在:网卡被打满了、挂掉了或者很多慢查询,此时需要暂停下任务系统让服务方进行处理;
  • 还有发现突然调用量太大,可能需要改变处理方式(比如同步转换为异步);

此时就可以 使用开关来完成降级

开关可以存放到配置文件、存放到数据库、存放到Redis/ZooKeeper;如果不是存放在本地,可以定期同步开关数据(比如1秒同步一次)。然后通过判断某个KEY的值来决定是否降级。

另外对于新开发的服务想上线进行灰度测试;但是不太确定该服务的逻辑是否正确,此时就需要设置开关,当新服务有问题可以通过开关切换回老服务。

还有多机房服务,如果某个机房挂掉了,此时需要将一个机房的服务切到另一个机房,此时也可以通过开关完成切换。

还有一些是因为功能问题需要暂时屏蔽掉某些功能,比如商品规格参数数据有问题,数据问题不能用回滚解决,此时需要开关控制降级。

3、读服务降级

对于读服务降级一般采用的策略有:

暂时切换读(降级到读缓存、降级到走静态化)

暂时屏蔽读(屏蔽读入口、屏蔽某个读服务)

在《应用多级缓存模式支撑海量读服务》中曾经介绍过 读服务,即:

接入层缓存→应用层本地缓存→分布式缓存→RPC服务/DB

我们会在接入层、应用层设置开关,当分布式缓存、RPC服务/DB有问题自动降级为不调用。当然这种情况适用于对读一致性要求不高的场景。

页面降级、页面片段降级、页面异步请求降级都是读服务降级,目的是丢卒保帅(比如因为这些服务也要使用核心资源、或者占了带宽影响到核心服务)或者因数据问题暂时屏蔽。

还有一种是页面静态化场景:

动态化降级为静态化:比如平时网站可以走动态化渲染商品详情页,但是到了大促来临之际可以将其切换为静态化来减少对核心资源的占用,而且可以提升性能;其他还有如列表页、首页、频道页都可以这么玩;可以通过一个程序定期的推送静态页到缓存或者生成到磁盘,出问题时直接切过去;

静态化降级为动态化:比如当使用静态化来实现商品详情页架构时,平时使用静态化来提供服务,但是因为特殊原因静态化页面有问题了,需要暂时切换回动态化来保证服务正确性。

以上都保证出问题了有预案,用户还是可以使用网站,不影响用户购物。

4、写服务降级

写服务在大多数场景下是不可降级的,不过可以通过一些迂回战术来解决问题。比如将同步操作转换为异步操作,或者限制写的量/比例。

比如扣减库存一般这样操作:

方案1:

a、扣减DB库存;

b、扣减成功后更新Redis中的库存;

方案2:

a、扣减Redis库存;

b、同步扣减DB库存,如果扣减失败则回滚Redis库存;

前两种方案非常依赖DB,假设此时DB性能跟不上则扣减库存就会遇到问题;因此我们可以想到 方案3:

a、扣减Redis库存:

b、正常同步扣减DB库存,性能扛不住时降级为发送一条扣减DB库存的消息,然后异步进行DB库存扣减实现最终一致即可;

这种方式发送扣减DB库存消息也可能成为瓶颈;这种情况我们可以考虑 方案4:

a、扣减Redis库存;

b、正常同步扣减DB库存,性能扛不住时降级为写扣减DB库存消息到本机,然后本机通过异步进行DB库存扣减来实现最终一致性。

也就是说正常情况可以同步扣减库存,在性能扛不住时降级为异步;另外如果是秒杀场景可以直接降级为异步,从而保护系统。

还有如下单操作可以在大促时暂时降级将下单数据写入Redis,然后等峰值过去了再同步回DB,当然也有更好的解决方案,但是更复杂,不是本文的重点。

还有如用户评价,如果评价量太大,也可以把评价从同步写降级为异步写。当然也可以对评价按钮进行按比例开放(比如一些人的看不到评价操作按钮)。比如评价成功后会发一些奖励,在必要的时候降级同步到异步。

5、多级降级

缓存是离用户最近越高效;而降级是离用户越近越能对系统保护的好。因为业务的复杂性导致越到后端QPS/TPS越低。

页面JS降级开关:主要控制页面功能的降级,在页面中通过JS脚本部署功能降级开关,在适当时机开启/关闭开关;

接入层降级开关:主要控制请求入口的降级,请求进入后会首先进入接入层,在接入层可以配置功能降级开关,可以根据实际情况进行自动/人工降级;

这个可以参考《京东商品详情页服务闭环实践》,尤其在后端应用服务出问题时,通过接入层降级从而给应用服务有足够的时间恢复服务;

应用层降级开关:主要控制业务的降级,在应用中配置相应的功能开关,根据实际业务情况进行自动/人工降级。

总结:

降级能保障系统在大促中活下来,而不是死去,达到丢卒保帅的作用。对用户提供有损服务,总比不服务要好。根据自己的场景设计相应的降级策略,保障系统在危机时刻能通过降级手段平稳度过。

文/张开涛

文章出处:高效运维

相关 [套路 系统] 推荐:

都是套路:高并发系统的降级特技

- - 运维派
京东集团技术研发,2014年加入京东,开发过京东商品详情页、详情页统一服务架构与开发工作,设计并开发了多个亿级访问量系统. 工作之余喜欢写技术博客,有《跟我学 Spring》、《跟我学Spring MVC》、《跟我学Shiro》、《跟我学Nginx+Lua开发》等系列教程. 在开发高并发 系统时有三把利器用来保护系统:缓存、降级和限流.

缓存更新的套路

- - 酷 壳 – CoolShell.cn
看到好些人在写更新缓存数据代码时, 先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中. 试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库. 于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了.

柯南破案的标准套路

- sugar - 河蟹娱乐
具体套路就是这样,尸体绝大多数时候是由女性发现的,然后嗷的一嗓子人就都到齐了. 再看嫌犯,首先有一个凶神恶煞的、看着就不像好人的、跟曹爷似的嫌疑人,不过放心,这人肯定是好人. 还会有一个一听说案子就吓的屎尿俱出顺裤裆流明显跟案子有牵连的嫌疑人,这人肯定知道不少内情,但不是凶手,而且之后十有八九会被真凶干掉.

[译]最牛B的编码套路

- - 陆其明's Blog
最近,我大量阅读了Steve Yegge的文章. 其中有一篇叫“ Practicing Programming”(练习编程),写成于2005年,读后令我惊讶不已:. 与你所相信的恰恰相反,单纯地每天埋头于工作并不能算是真正意义上的锻炼——参加会议并不能锻炼你的人际交往能力;回复邮件并不能提高你的打字水平.

招聘面试的套路与原则

- - mindwind
进入八月,开启了夏季的社招季. 近期集中的招聘、面试,形成了一些心得体会,或者说叫套路,而隐藏在这些套路背后的其实是一些更通用的原则. 所以,这一篇其实是写给招聘者的,不过,所有的应聘者也有可能有成为招聘者的一天,也可以参考. 一次集中的扩招需求,有点像每年一度的晋升评审,都需要对大量的候选人进行定级评审,因为每一个新招聘的人员都会对其有一个定级的过程.

壳系统

- Vernsu - It Talks-魏武挥的blog
经常有人被我问到“你用什么浏览器”时的答案是:傲游啦360啦,但事实上,这些都不是真正的浏览器,从技术角度讲,充其量只是在IE浏览器上加一个壳罢了. 在国外,壳浏览器是以“皮肤”的形式存在,纯属为了美化浏览器而用. 但在中国,壳浏览器成了一门生意. 奇虎的主要收入来源并非来自那个由于一场商战而赫赫有名的安全卫士,而是来自于360浏览器(它有两个版本,分别以IE和Chrome为内核).

秒杀系统

- - 开源软件 - ITeye博客
秒杀系统架构分析与实战. (反馈非常好的文章,推荐). (1)查询商品;(2)创建订单;(3)扣减库存;(4)更新订单;(5)付款;(6)卖家发货. (1)低廉价格;(2)大幅推广;(3)瞬时售空;(4)一般是定时上架;(5)时间短、瞬时并发量高;. 假设某网站秒杀活动只推出一件商品,预计会吸引1万人参加活动,也就说最大并发请求数是10000,秒杀系统需要面对的技术挑战有:.

Ext文件系统

- Haides - 博客园-首页原创精华区
  虽然从Ext2到Ext4,找数据的方式发生了变化,但是,磁盘的布局还是非常相似的. 其实这个东西也不需要变化,因为现在也没什么特别巧妙的方式,而且磁盘的吞吐量、效率的瓶颈也不在这里. 当然,这里排除那些根据自身文件特点设计的数据库,毕竟还是为了支持通用文件.   Boot在第一个块,放的应该是引导程序,超级块就放在了第二个块上,如果不是可以在mount的时候通过参数sb来设置.

HBase 系统架构

- - 博客园_首页
HBase是Apache Hadoop的数据库,能够对大型数据提供随机、实时的读写访问. HBase的目标是存储并处理大型的数据. HBase是一个开源的,分布式的,多版本的,面向列的存储模型. 5 可在廉价PC Server搭建大规模结构化存储集群. HBase是Google BigTable的开源实现,其相互对应如下:.