转自:https://yq.aliyun.com/articles/54449 测试辈的也学习学习~~ 对架构还是甚是感兴趣的 对好的架构方法论及实践能信手拈来 我要成为真正的高手 ^_^
Ps:关于[三]的流行参考,百度可得
- 宅男有三好;Dota、基友、破电脑。
- 萝莉有三好;柔体、轻音、易推倒。
- 屌丝有三废;在吗、忙不、早点睡。
- 女神有三宝;干嘛、呵呵、去洗澡。
“ 与传统意义上的红包相比,近两年火起来的互联网“红包”,似乎才是如今春节的一大重头戏。春晚直播期间讨论春晚的微博达到5191万条,网友互动量达到1.15亿,网友抢微博红包的总次数超过8亿次。看得见的数据背后,隐藏的是什么看不见的技术呢?”
按照各家公布的数据,除夕全天微信用户红包总发送量达到10.1亿次,摇一摇互动量达到110亿次,红包峰值发送量为8.1亿次/分钟。而支付宝的红包收发总量达到2.4亿次,参与人数达到6.83亿人次,红包总金额40亿元,峰值为8.83亿次/分钟。春晚直播期间讨论春晚的微博达到5191万条,网友互动量达到1.15亿,网友抢微博红包的总次数超过8亿次。”
本文会以一些公开的内容聊聊万变不离其中的所谓绝招,为了吸引要求,素材主要参考淘宝大秒系统和各家红包系统的情况。
第一板斧
第一板斧:活下来 [Stability]
俗话说身体是革命的本钱,首先要活着。大凡架构还没有舍身成仁的死法,都是好死不如赖活着。关于如何活着,其实是有模式可循的,活着这事在技术界也有一个蛮好听的名字--稳定性(花名 Stability)。稳定性实践笔者印象比较深的有2篇内容,一是由淘宝小邪在2011年分享的[淘宝稳定性实践]。
该材料经墙内搜索百度查询,基本没有别的存档了,唯有百度文库硕果仅存,地址就不贴了。这个slide主要讲了4招:容量规划、集群容灾、依赖降级、运行监控。
就容灾可以区分为同机房内、同城异机房、异地机房几个层次考虑。
上图机房1种C系统故障切换机房2的情况。
保护自己是很重要的,如下图所示,C挂了,则A调用C超时,如何保障A不被拖累呢?
阿淘也给出解法,就是stable switch。如下图所示:
随着淘宝、天猫的业务发展,本着更优雅运维的思路,阿淘在稳定性方面的建设肯定有更多精细化,更好、更优雅的做法,但是其本质原则:活着胜过一切!
多个备份、无缝切换、超限限流、断尾求生又称优雅降级等是指导同类互联网应用的常见招数。另外,特别安利一下服务治理,随着微服务兴起,大有不微不能出来见人的姿势。但服务治理是在服务管理中一块重要内容,亘古弥新。如果有上千应用,服务接口不计其数。做一次功能升级,我得知道谁调用了我,我调用了谁;做性能和容量改进,我得知道那条链路是瓶颈;做链路优化,我得通过工具来看那些强依赖可以调整为弱依赖等等。
一片信手普及的基础文也写得这么干,江湖也不禁为自己点赞了。(话说龙姑娘的红包,啥时候发一下…)
第二篇高大上的ppt是来自国外的一个ppt。
作者把可用性和稳定性,做了一些区分。可用性偏大局,比如FO,MM模式等。而稳定性强调单区域应用中的手段比如开关,降级等。
第二板斧
第二板斧:简单可扩展(scalability)
啥叫可扩展,就是可以不断加资源以达成更大容量,支撑更高的并发、迎接更多用户。这里的资源可以是应用服务器,也可以是数据库服务器,或者是缓存服务器。
[可扩展Web架构探讨]这个材料中也有对可扩展有所定义。
这里也提及scalability是系统适应不断增长用户数量的能力。特别提及扩展容易(所有组件都应当简单扩展)、无共享架构(shared arch)。
负载均衡是的作用有几个,一是接入接入保护、失效检测;二是提供在用户和服务器之间做中介,让增减服务器对用户不可见;三是通过负载均衡算法让流量相对均衡的分布。负载均衡有硬件设备也有纯软件比如LVS,负载均衡对于页面请求以及rpc调用都能较均衡的分配,是一个重要的考量因素。
(关于负载均衡的具体内容,此文不赘述)
有一个很古老的文档,叫LiveJournal's Backend - A history of scaling 叙述了网站的发展历程。
一台server有啥坏处,自不必说了。然后…
某一天发展到5台了,3个web server;2台db。使用mysql replication来做复制。
随着用户数的增加,用户需要cluster
后来因为性能的原因,需要使用cache,包括Mogile Storage等。详情可参见
一个网站的发展后来成了很多架构文章的标配。上更多webserver、上更多dbserver、读写分离、分库分表、上搜索引擎等等。架构之道在合适的时间做合适的决定(tradeoff),运用之道,存乎一心。
第三板斧
第三板斧:拦河大坝、去并发
由于营销活动(创造营销节点、扩大影响力的需要),总有很多产品策划、运营乐此不疲的玩着一个game---在足够集中的时间内比如秒级处理足够多的用户请求,让世界为此狂欢,同时也是彰显技术实力的一次大考。
小米卖着抢号的手机、天猫发明了双11光棍节、微信和支付宝连续2年做着新春红包。营销活动的时候要使用前2板斧,保证可用性和简单可扩展性,同时还要祭出第三板绝杀—拦河大坝、缓存为王、去热点资源的并发。
为啥要拦?很简单,用户很热情(感性),但系统必须得理性!就3个苹果手机,凭啥让几十万人都涌入柜台!在大秒系统一文中许同学就娓娓道来(省得少画个图)……
对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,如上图所示:在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:
- 1先做数据的动静分离
- 2将90%的数据缓存在客户端浏览器
- 3将动态请求的读数据Cache在Web端
- 4对读数据不做强一致性校验
- 5对写数据进行基于时间的合理分片
- 6对写请求做限流保护
- 7对写数据进行强一致性校验
将90%的数据缓存在客户端浏览器,将动态请求的读数据cache在web端,还是不够的。在大秒的过程中,存在极端情况,就是请求超过单key所在server的QPS能力。
数据访问热点,比如Detail中对某些热点商品的访问度非常高,即使是Tair缓存这种Cache本身也有瓶颈问题,一旦请求量达到单机极限也会存在热点保护问题。有时看起来好像很容易解决,比如说做好限流就行,但你想想一旦某个热点触发了一台机器的限流阀值,那么这台机器Cache的数据都将无效,进而间接导致Cache被击穿,请求落地应用层数据库出现雪崩现象。这类问题需要与具体Cache产品结合才能有比较好的解决方案,这里提供一个通用的解决思路,就是在Cache的client端做本地Localcache,当发现热点数据时直接Cache在client里,而不要请求到Cache的Server。
数据更新热点,更新问题除了前面介绍的热点隔离和排队处理之外,还有些场景,如对商品的lastmodifytime字段更新会非常频繁,在某些场景下这些多条SQL是可以合并的,一定时间内只执行最后一条SQL就行了,可以减少对数据库的update操作。另外热点商品的自动迁移,理论上也可以在数据路由层来完成,利用前面介绍的热点实时发现自动将热点从普通库里迁移出来放到单独的热点库中。
心得体会
请允许笔者总结一下高并发方案的解决之道。
使用缓存,能越前端缓存的放在前端,这样调用链路最短。
这里的缓存不仅仅是redis、或者memcached,而是local或者climatchent优先的思路,去除对并发资源的依赖。比如[揭秘微信摇一摇背后的技术细节]一文中提到:
按一般的系统实现,用户看到的红包在系统中是数据库中的数据记录,抢红包就是找出可用的红包记录,将该记录标识为match属于某个用户。在这种实现里,数据库是系统的瓶颈和主要成本开销。我们在这一过程完全不使用数据库,可以达到几个数量级的性能提升,同时可靠性有了更好的保障。
- 1支付系统将所有需要下发的红包生成红包票据文件;
- 2将红包票据文件拆分后放到每一个接入服务实例中;
- 3接收到客户端发起摇一摇请求后,接入服务里的摇一摇逻辑拿出一个红包票据,在本地生成一个跟用户绑定的加密票据,下发给客户端;
- 4客户端拿加密票据到后台拆红包,match后台的红包简化服务通过本地计算即可验证红包,完成抢红包过程。
分拆热点
上文提到,在极端情况下大秒使用了二级缓存,通过拆分key来达到避免超过cache server请求能力的问题。在facebook有一招,就是通过多个key_index(key:xxx#N) ,来获取热点key的数据,其实质也是把key分散。对于非高一致性要求的高并发读还是蛮有效的。如图
则解决之道是:
- Hot keys are published to all web-servers
- Each web-server picks an alias for gets
- – get key:xxx => get key:xxx#N
- Each web-server deletes all aliases
微博团队披露:服务端本地缓存,使用nginx本身缓存和服务器的L0缓存,来提升模块的响应速度,做到了90%以上核心接口的响应时间在50ms以内,减少了进程等待时间,提升了服务器的处理速度。
解决并发有1种基本办法: 分拆!而分拆有两种拆法,
1拆资源
一是把资源(resource)拆了,著名的比如ConcurrentHashMap,拆成了16个桶,并发能力大大提高。
2拆基础数据
在红包应用中,如果还依赖一个共同的基础数据,也可以把这个基础数据拆成多个cell。
预处理
[互动1808亿次,16倍的超越!谈支付宝红包的高并发挑战]一文中如此说:
“在这次春晚活动中,涉及到大量的资源,包括图片、拜年视频等。图片和视频都比较大,十几b到几百kb不等。当在高峰期时,如果瞬间有海量的请求到CDN上,这么大的请求带宽根本扛不住。我们当时预估了大约有几T的带宽需求。
为了能有效地扛住瞬间峰值对CDN的压力,我们对资源进行了有效的管理和控制。首先在客户端预埋了几个缺省资源,万一真不行了,这几个资源可以用。其次尽量提前打开入口,当用户浏览过后,就将资源下载到本地。再次浏览时不再需要远程访问CDN。最后,做了应急预案,高峰期一旦发现流量告警,紧急从视频切换到图片,降低带宽压力,确保不出现带宽不够而发生限流导致的黑屏等体验不好的问题。
最后的结果可以用完美来形容,由于预热充分,带宽虽然很高,但没达到我们的告警值,应急预案也没有使用。
”微信团队也提到:“
在除夕,用户通过摇一摇参与活动,可以摇到红包或其他活动页,这些页面需要用到很多图片、视频或 H5 页面等资源。在活动期间,参与用户多,对资源的请求量很大,如果都通过实时在线访问,服务器的网络带宽会面临巨大压力,基本无法支撑;另外,资源的尺寸比较大,下载到手机需要较长时间,用户体验也会很差。因此,我们采用预先下载的方式,在活动开始前几天把资源推送给客户端,客户端在需要使用时直接从本地加载。”
异步化
江湖传说中有一句话,叫能异步的尽量异步。做活动的时候,资源多宝贵啊,对C端无感但可以容忍的,就让它慢慢做,而此种一般放入到队列当中。
杭州的蘑菇街七公又名小白,是一个热情的朋友。他提及交易服务依赖过多的解决之道。服务依赖过多,会带来管理复杂性增加和稳定性风险增大的问题。试想如果我们强依赖10个服务,9个都执行成功了,最后一个执行失败了,那么是不是前面9个都要回滚掉?这个成本还是非常高的。所以在拆分大的流程为多个小的本地事务的前提下,对于非实时、非强一致性的关联业务写入,在本地事务执行成功后,我们选择发消息通知、关联事务异步化执行的方案。(看看下图,那些可以异步化?)
使用队列
拦、拦、拦;之后缓存抗;缓存扛不住的并发分拆;但是还有一个问题,就是极端热点资源在db里,如果并发高还是会出问题。大秒一文中有较好的处理方案,就是排队。Web服务器排队,在db层还做了一个patch排队,真心是业务是最好的老师,不得已何必祭大招!
应用层做排队。按照商品维度设置队列顺序执行,这样能减少同一台机器对数据库同一行记录操作的并发度,同时也能控制单个商品占用数据库连接的数量,防止热点商品占用太多数据库连接。关于详情,可以阅读大秒一文。
总结
总结一下,互联网架构三板斧:
- 活下来(Stability)
- 简单可扩展(Scalability)
- 拦河大坝/去并发
在第三板斧中又有分层拦截、多级缓存、数据近端、分拆锁、预处理、异步化及队列等pattern。学习原则:灵活运用,不尽信经验。
写这么个长篇,我也是醉醉的了,权当为那些没时间学习、没仔细学习的朋友尽心了。
【引用内容 出处】
《互动1808亿次,16倍的超越!谈支付宝红包的高并发挑战》- QCon公众号
《10亿红包从天而降,揭秘微信摇一摇背后的技术细节》 - InfoQ网站《淘宝大秒系统设计详解》- CSDN《解密微博红包:架构、防刷、监控和资源调度》 - InfoQ网站
http://www.slideshare.net/jboner/scalability-availability-stability-patterns
LiveJournal's Backend - A history of scaling