第3篇 案例
9 淘宝网的架构演化案例分析 156
初期:2003年马云在家里用买来的C2C交易软件稍作修改就成了最初的淘宝网
作为刚刚起步的小网站,使用开源、免费、简单的技术搭建网站可谓一举多得:免费的技术降低成本、开源的技术能获取文档支持、简单的技术快速响应需求,工程师上手快,学习周期短、退一步,如果业务发展不顺利,及时关闭网站止损。
中期:应用服务器使用Weblogic,数据库使用Oracle,都需要授权使用费。
业务快速发展,宝贵的开发资源应投入到新业务开发上,而不是付费就能搞定的基础技术上,无后顾之忧可以全力以赴拓展市场。
后期:回归MySQL及NoSQL。
技术脱胎换骨。
10 维基百科的高性能架构设计分析 163
10.1 Wikipedia网站整体架构 163
GeoDNS:域名服务器BIND的增强版本,可将域名解析到距离用户最近的服务器。
LVS:基于Linux的负载均衡服务器。
Squid:基于Linux的反向代理服务器。
Ligthtpd:图片服务器。
PHP:网站建站语言。
Mencached:分布式缓存。
Lucene:Apache全文搜索引擎。
MySQL:关系型数据库。
10.2 Wikipedia性能优化策略 165
10.2.1 Wikipedia前端性能优化 165
核心:反向代理服务器Squid集群
圣杯:CDN服务(CDN加速),热门页面缓存在CDN服务器上,而CDN服务器又部署在离用户最近的服务器上(DNS解析为基础),请求从CDN直接返回,响应速度非常快,减少服务器压力,节约资源。
Wikipedia CDN 缓存准则:
1.页面内容不包括动态信息,以免页面内容很快失效或过时
2.每个页面有唯一的URL,以便CDN快速查找并避免重复缓存
3.HTTL响应头写入缓存控制信息,通过应用控制内容是否缓存及缓存有效期等。
10.2.2 Wikipedia服务端性能优化 166
硬件上:最好的服务器
代码层面上
10.2.3 Wikipedia后端性能优化 167
缓存策略:
1.热点集中数据缓存到本地服务器中
2.缓存数据内容尽量是可以直接使用的格式
3.存储session对象
4.Memcached连接相对数据库连接廉价
MySQL优化:
1.使用较大的服务器内存
2.使用RAID0磁盘阵列加速磁盘访问,降低了数据可靠性,主从复制、数据异步备份等手段解决
3.数据库事务一致性设置在较低水平,加速宕机恢复速度
4.如果Master数据库宕机,立即切换到Salve数据库,同时关闭数据库写服务
11 海量分布式存储系统Doris的高可用架构设计分析 169
Doris设计目标是支持中等高可用,Hadoop略胜一筹,这里主要看设计思想。
11.1 分布式存储系统的高可用架构 170
11.2 不同故障情况下的高可用解决方案 171
11.2.1 分布式存储系统的故障分类 172
瞬时故障:网络通信瞬时中断、服务器垃圾回收、后台线程繁忙停止数据访问操作;特点是是时间段,秒级甚至毫秒级可自行恢复正常。
临时故障:交换机宕机、网卡松动等导致的网络通信中断,系统升级、停机维护等运维引起的服务关闭,内存损坏、CPU过热等硬件导致的服务器宕机;特点是需要人工干预才能恢复正常,持续几十分钟甚至几个小时。
永久故障:硬盘损坏,数据丢失。可以通过更换硬盘重启服务器
11.2.2 正常情况下系统访问结构 172
11.2.3 瞬时故障的高可用解决方案 173
多次重试仍然失败,可能需要执行临时故障处理策略。
11.2.4 临时故障的高可用解决方案 174
11.2.5 永久故障的高可用解决方案 175
12 网购秒杀系统架构设计案例分析 176
秒杀活动带来的并发访问用户是平时的百倍甚至千倍,设计部署专门的秒杀系统。
12.1 秒杀活动的技术挑战 177
1.对现有业务造成冲击:秒杀时间短、并发量大,如果和网站原有应用部署在一起,会对现有业务造成冲击,甚至宕机。
2.高并发的应用数据库负载:不停刷新页面,对服务器,数据库造成极大压力。
3.突然增加的网络和服务器带宽:假设秒杀页面200k,需要的网络带宽是200k*访问用户数
4.直接下单:下单是普通URL,如果得到URL可以不用等到秒杀就下单。
12.2 秒杀系统的应对策略 177
1.秒杀系统独立部署:避免拖垮整个网站
2.秒杀商品页面静态化:HTML页面
3.租借秒杀活动网络带宽:秒杀商品页面做CDN缓存
4.动态生成随即下单页面URL:避免直接访问URL下单,服务器端生成随机参数,秒杀开始才能看到。
12.3 秒杀系统架构设计 178
1.如何控制秒杀商品页面购买按钮的点亮:为了减轻服务器端负载压力,更好地利用CDN、反向代理等性能优化手段,该页面被设计为静态页面。秒杀开始时,用户刷新页面,请求
根本不会到达应用服务器。
解决方案:使用JavaScript脚本控制,在秒杀商品静态页面中加入一个JavaScript文件引用,该JavaScript文件中包含秒杀开始标志为否;当秒杀开始的时
候生成一个新的JavaScript文件(文件名保持不变,只是内容不一样),更新秒杀开始标志为是,加入下单页面的URL及随机数参数(这个随机数只会产生一个,即所有人看到的
URL都是同一个,服务器端可以用redis这种分布式缓存服务器来保存随机数),并被用户浏览器加载,控制秒杀商品页面的展示。这个JavaScript文件的加载可以加上随机版本号
(例如xx.js?v=32353823),这样就不会被浏览器、CDN和反向代理服务器缓存。这个JavaScript文件非常小,即使每次浏览器刷新都访问JavaScript文件服务器也不会对服务器集
群和网络带宽造成太大压力。
2.如何只允许第一个提交的订单被发送到订单子系统:由于最终能够成功秒杀到商品的用户只有一个,因此需要在用户提交订单时,检查是否已经有订单提交。如果已经有订单提交
成功,则需要更新 JavaScript文件,更新秒杀开始标志为否,购买按钮变灰。事实上,由于最终能够成功提交订单的用户只有一个,为了减轻下单页面服务器的负载压力, 可以控制
进入下单页面的入口,只有少数用户能进入下单页面,其他用户直接进入秒杀结束页面。解决方案:假设下单服务器集群有10台服务器,每台服务器只接受最多10个下单请求。
在还没有人提交订单成功之前,如果一台服务器已经有十单了,而有的一单都没处理,可能出现的用户体验不佳的场景是用户第一次点击购买按钮进入已结束页面,再刷新一下
页面,有可能被一单都没有处理的服务器处理,进入了填写订单的页面,可以考虑通过cookie的方式来应对,符合一致性原则。当然可以采用最少连接的负载均衡算法,出现上述情
况的概率大大降低。
12.4 小结 182
即使系统出现故障也不应该出现错误页面,而是秒杀结束页面。
13 大型网站典型故障案例分析 183
13.1 写日志也会引发故障 184
故障现象:服务器集群报警磁盘可用空间低于警戒值,log文件过大
原因分析:log输出level为dubug
经验教训:log输出级别至少为warm,关闭第三方日志。
13.2 高并发访问数据库引发的故障 184
故障现象:数据库Load居高不下,持续报警
原因分析:SQL正常,但是被首页频繁调用
经验教训:首页最好是静态的,或者需要的数据从缓存服务器获取
13.3 高并发情况下锁引发的故障 185
故障现象:响应超时报警,很快又恢复,如此往复
原因分析:某singleton对象中多处使用了synchronized(this),this对象只有一个,所有请求都需要排队获取唯一的一把锁,远程调用长时间执行,其他线程需要等待,响应超时。
经验教训:锁操作要慎用
13.4 缓存引发的故障 185
故障现象:没有新应用发布,数据库Load突然飙升,并很快失去响应,切换备用数据库,很快网站瘫痪
原因分析:缺乏经验的工程师关闭了所有缓存服务器
经验教训:对缓存的管理提升到跟数据库一样的水平
13.5 应用启动不同步引发的故障 186
故障现象:某种应用发布后,服务器立即崩溃
原因分析:后台服务器准备好,前台才能启动,否则导致故障
经验教训:姑娘们穿好衣服,老鸨才开门迎客
13.6 大文件读写独占磁盘引发的故障 186
故障现象:图片上传时间数倍增加
原因分析:图片存储服务器有几个文件非常大
经验教训:图片服务器不应该和其他类型的文件服务器公用
13.7 滥用生产环境引发的故障 187
故障现象:某个时间段内,某些应用突然变慢
原因分析:有工程师在线上进行性能压力测试
经验教训:线上数据库修改需DBA协助
13.8 不规范的流程引发的故障 187
故障现象:某应用发布后,load飙升,回滚后告警消除
原因分析:开发为了测试将读缓存的代码注释掉,忘记打开
经验教训:加强代码review
13.9 不好的编程习惯引发的故障 188
故障现象:某功能一无法正常使用
原因分析:程序根据使用记录构造对象,用户都是第一次使用,对象为null
经验教训:确保对象不是null,必要时构造空对象
13.10 小结 188
简单设计,问题越容易被发现,越容易被解决。