主持人:冯大辉
岑文初:模块化来降低耦合性时如何把握模块划分的粒度?如何权衡复用性与粒度过细导致依赖复杂的矛盾?
杨海朝:耦合性是影响软件系统复杂程度和设计质量的重要因素,模块化设计的目标是建立模块间耦合度尽可能松散的系统,通过尽量使用数据耦合,少用控制耦合,限制公共耦合的范围和一定要避免使用内容耦合来降低接口的复杂性。
在系统架构中模块化设计对于降低耦合性有非常重要的作用,相关的功能合在一起,不相关的功能分离开来。
模块划分的粒度决定着最终划分结果的合理性和有效性。模块划分的粒度越细,越易于定义和开发,但随着模块数的增加,模块之间的接口也随之增加,使得各个模块在组装成系统消耗的时间增加,同时加大了整个系统测试的复杂度。模块划分的粒度越粗,越有利于整个系统的组装,整个系统的测试复杂度也降低,但整个系统的灵活性下降,难以满足用户对系统的多样性需求。
模块划分的粒度是一个不太容易把握的问题,不同的产品和项目有不同的划分粒度方法。模块化的粒度需要根据模块的三大特征(相对独立性、互换性、通用性)来把握。每个模块的聚合度越高,耦合性就越低,反之亦然。在做模块划分时,应使模块之间尽可能独立,块内联系尽可能大,块间联系尽可能小,功能模块逐层分解和细化,直至形成若干容易编写的模块。同时还需要结合模块的功能、模块的规模、模块的出入口等诸多因素综合考虑。模块划分的粒度越小,通用范围广,可在较多应用进行复用,但其较小的粒度组装过程烦琐,会导致复用效率降低。反之,模块划分的粒度越大,组装的步骤越少,可复用效率越
高,但其复用范围受到限制。
岑文初:如何处理高并发系统中缓存失效的场景?
杨海朝:从硬件到操作系统,从系统软件到应用软件,我们随处都可以看到缓存的身影。缓存在Web2.0网站中发挥着越来越重要的作用,特别是大流量的高并发系统。缓存在带来性能提升和支持高并发的同时,也带来另一个问题,如果缓存宕机导致所有的缓存失效,所有的流量都压到后端的服务上,例如数据库层。这时,后端服务因为压力过大无法提供服务或快速响应,缓存因为等待后端请求的响应而“热”不起来,最终导致“雪崩”问题。在高并发系统中,解决缓存失效有以下三个思路。
使用Consistent Hashing算法。把数据缓存分片,减少缓存宕机对服务的影响范围。Consistent Hashing能最大限度地抑制Hash键的重新分布,同时要取得比较好的负载均衡的效果,需要在服务器数量比较少时,增加虚拟节点来保证服务器能均匀地分布在圆环上,最大限度地减小服务器增减节点时产生的缓存重新分布问题。
缓存多份。通过应用写多份缓存,或应用写一份缓存由中间件把此份缓存复制多份,在缓存宕机时能切换到另一份缓存上,减少缓存宕机对后端数据存储的影响。这种方式最好采用缓存之间的复制,减少应用开发的复杂度。
解决高并发系统中的缓存失效问题,需要结合业务逻辑进行综合考虑。
实现缓存持久化或半持久化。所谓的持久化就是定期把缓存里面的数据刷到磁盘,保存起来,在缓存失效时能保证大部分数据仍然有效,例如使用Redis或MemcacheDB把一些数据存到磁盘。可能有人会说:“是否在刷磁盘那一刻会影响缓存的高效性?”这可以考虑通过高端硬件(例如Fushion IO或SSD作为存储设备),来减少刷Cache过程中减少对服务的影响。
这些仅仅是实现的三个思路,各有利弊。解决高并发系统中的缓存失效问题,需要结合业务逻辑进行综合考虑。
岑文初:目前是如何做好应用的依赖监控的?例如依赖缓存,是否知道缓存的命中率情况、使用率等;依赖外部服务,是否知道外部服务的消耗时间、成功失败情况等。
杨海朝:应用监控日益成为保障系统安全运行不可或缺的工具,在提高系统可用率和故障的预警能力、最大限度地缩短故障修复时间方面,日益显示出其重要程度。
此外,对应用依赖的服务的监控也非常重要,目前可以建立一整套监控体系,这套监控体系不仅监控应用自身,同时也对外部服务进行监控。应用在调用依赖服务时,打印应用调用的详细日志,记录调用的返回时间,以及成功与否,同时要求外部或依赖服务提供一个统一的接口,用来返回每次调用消耗的时间以及失败率。通过对这些日志的实时分析来发送邮件和短信报警。
岑文初:系统是否有对内或者对外提供服务,如何管理服务的使用权限,如何做服务升级?
杨海朝:在系统中服务的使用权限至关重要,特别是既提供对内服务又提供对外服务的系统。
目前管理服务的使用权限,设置白名单是最简单的方式。通过设置白名单,只有在白名单里面的用户和来源IP才能访问服务,其他的都无权访问。外部调用服务也通过使用appkey的方式,简单地说是API接口的钥匙,只有通过这个钥匙才能打开API的大门,从而获取数据,同时对appkey的申请设置一系列流程来保证其安全性。根据这些appkey来设置不同的权限等级,控制对目标数据的访问以及调用频率。
通过使用Gearman系统进行“热”升级。在负载均衡设备的后端增加一个代理层,升级时通过对代理层的心跳探测页面修改,把落到这台机器上的流量切走,然后对这台机器进行升级,升级完之后进行测试,测试完成之后,再对某一区间机器进行升级,在某一个时间内测试没有问题,再对其他所有区间进行升级。提前准备好回退机制,保证每次升级对用户的影响最小,力求达到无缝升级。
岑文初:对于不同系统之间的耦合如何处理?比如前端系统要求快速响应大量的用户请求,但是依赖于后端的服务体系,而服务系统的瓶颈可能在数据库读写上,如何协同这样需求差异化系统工作?
杨海朝:不同系统之间的耦合性是指各个系统之间的互相依赖程度。需要熟悉各种耦合性的特性,为不同的系统之间选择合适的耦合性。
如果系统之间采用紧耦合,那么涉及对象与对象的直接通信,这些对象通常比在松耦合系统中交互更为频繁。假如两个对象位于不同系统中并且由不同的网络分开,则会导致性能和延迟问题。
如果系统之间采用松耦合以及基于消息的架构,客户端和服务端不需要知道对方如何实现。两端的消息协议符合协商,则客户端或服务器端的实现就可以根据需求进行变更,而不会互相影响。
松耦合提供了紧耦合所不能提供的许多优点,并且它有利于降低客户端和服务端之间的依赖性。例如采用异步策略。对于需要快速响应的系统,尽可能把过程变成异步的,减少请求者所经历的响应延时。如果系统A同步调用系统B,那么A和B是紧密耦合,而紧耦合的系统是需要共同进退,两个系统需要承担相同的量,并且如果B不可用,则A也不可用。如果系统A和系统B之间是异步的方式,不管是通过消息队列、多播消息、批处理还是其他实现方式,那么系统A和系统B是相互独立的,如果B宕机,A仍然能够继续提供服务,也即所谓的优雅降级策略。这种异步策略能把高并发的写入高峰变成一个平缓的写入速率,减少了硬件的部署成本,同时可以控制消息队列的写入速度以及优化队列来避免后端服务出现压力过高问题。
岑文初:对于系统优化,平时如何查找瓶颈,最后又如何确定优化后是有效的?可以的话请举例说明。
杨海朝:系统上线,首先对系统进行必要的压力测试,量化能承担的最大量。通过对客户端性能指标和非客户端性能指标进行收集,对系统的响应时间、并发用户数、吞吐量、硬件资源的表现等这些关键点进行分析,最终找到系统的性能瓶颈。
同时通过这些压力测试,确定系统在访问量不端增加时,可能出现瓶颈的组件。压力测试过程中输出详细的日志信息,然后对日志信息进行整理,分析各种组件的性能表现情况。
对于已经在线的系统,要部署好各种状态监控系统,最好以图形化的方式呈现出来。在出现性能瓶颈时,能通过这些状态监控信息,找到性能瓶颈点或将性能瓶颈缩短在一定的范围之内,然后对线上系统按逻辑功能进行划分,例如静态池、动态池、缓存层、数据库服务。修改每个功能模块以便输出详细的日志信息,对这些日志信息进行整理和分析,找到瓶颈所在,同时记录各个功能块的性能表现,在优化后,收集相同信息进行对比来确定优化前后的性能差别。对于单个模块可以通过一些
性能分析工具来对程序的性能进行分析,例如Rational Quantify。
下面以数据库的瓶颈分析为例。
- 收集一天内所有的SQL语句,以及统计每种类型的语句占的比例。
- 收集当前系统中CPU、内存、硬盘I/O的表现情况,分析硬件资源瓶颈。
- 对执行效率低、消耗硬件资源、响应慢并且频繁调用的SQL语句进行优化。
- 将收集优化后的硬件资源表现情况和之前进行对比,最终量化优化提高的比例。
总之对于不同的系统,寻找性能瓶颈的步骤可能会有所不同,但都离不开对关键数据的收集和分析。
主持人介绍:冯大辉,现任丁香园(http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。
提问嘉宾介绍:岑文初,2006年加入阿里巴巴,2007年初开始负责阿里软件平台架构设计,2007年底开始进入开放平台领域,2009年8月加入淘宝开放平台,现在是淘宝开放平台主架构师。自认没有特长,只是学习能力比较强。
回答嘉宾介绍:杨海朝,新浪首席DBA,负责整个公司的数据库管理工作。热衷于数据库设计、性能优化、分布式部署方案和高可用性方面的研究。在大规模高并发、海量访问特别是大规模数据库运维方面有丰富的管理和维护经验。
分享到:
相关推荐
- **JS模块化加载**:利用FIS框架中的模块化加载器提升加载效率。 ##### 成果展示 经过一系列优化后,不仅显著提升了用户体验,还为后续的性能改进奠定了坚实的基础。 #### 四、公共主页优化实践 针对百度公共...
Go-Macross是基于Golang构建的高性能、模块化Web框架,专为提高开发效率而设计。在Golang的世界里,Web开发框架的选择至关重要,它们能够帮助开发者快速构建健壮且可扩展的Web应用程序。Macross框架就是这样一个工具...
使用C++编写PCM源码,能够利用其面向对象的特性,实现模块化设计和高效的性能。同时,C++广泛应用于系统级编程,使得PCM可以紧密地与操作系统和硬件接口,提供低延迟、高精度的性能数据。 6. **核心(Core)级监控...
模块化设计是物联网网关实现中不可或缺的,它可以帮助开发者将复杂系统拆分为多个功能明确、相互独立的模块。对于物联网网关而言,模块化能够使得每个模块独立开发和测试,提高系统的可维护性和可扩展性。例如,可以...
饼图分析不仅适用于开发阶段,也适用于应用发布后的性能监控。通过收集用户反馈和持续监控,开发者可以不断调整和优化缓存策略,确保应用在不同设备和使用场景下的性能表现。 总结来说,Android的缓存饼图是开发者...
五、性能监控与优化 1. 监控工具:使用如Prometheus、Grafana等工具实时监控系统性能指标,及时发现并解决问题。 2. 性能测试:通过JMeter、LoadRunner等工具模拟高并发场景,找出性能瓶颈并优化。 3. 缓存策略:...
在维护分布式缓存集群时,监控模块是不可或缺的。它通常包含缓存服务器监控、缓存实例监控、缓存应用拓扑监控和缓存集群监控四个部分。缓存服务器监控的目的是确保缓存集群中的服务器本身运行良好,监控其CPU使用率...
随着信息技术和网络技术的发展,煤矿安全监控系统趋于智能化、网络化,需要高效、稳定的数据处理技术来支撑其运行。在煤矿安全监控系统中,监控分站作为数据采集与指令传输的关键节点,其数据处理能力直接影响整个...
4. **性能监控**:在清理前后,对系统性能进行监控,如CPU使用率、内存占用、响应时间等,以便评估清理效果和调整清理策略。 5. **日志分析**:分析系统日志,查找可能导致缓存积压的原因,如异常的高并发访问、...
物联网网关作为物联网系统中的关键组件,其主要职责是连接感知层的各种设备,如传感器、执行器等,并与网络层进行交互,...通过模块化设计,我们可以更灵活地应对不断变化的物联网需求,提升整个系统的性能和用户体验。
第1章 绪论 1.1 等待的真相 1.2 瓶颈在哪里 1.3 增加带宽 ... 1.5 加快服务器脚本计算速度 ...第18章 性能监控 18.1 实时监控 18.2 监控代理 18.3 系统监控 18.4 服务监控 18.5 响应时间监控
Redis,全称Remote Dictionary Server,是一款开源的、高性能的键值对存储系统,常被用作数据库、缓存和消息中间件。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,这使得Redis在处理各种场景时具有...
此外,GWT的模块化设计允许开发者专注于业务逻辑,而无需过多关注性能优化细节。 为了进一步提升GWT应用的性能,以下是一些关键优化策略: 1. **利用强缓存**:通过设置合适的HTTP缓存头(如Expires和Cache-...
9. **测试与监控**:进行详尽的测试,确保缓存机制在各种场景下的正确性和稳定性,同时通过日志和分析工具监控缓存的性能和效果。 在实际开发中,可以结合第三方库如SDWebImage处理图片缓存,FMDB处理SQLite数据库...
Python 通过 Canal 进行数据监控后的数据缓存设计是一种高效的数据处理策略,尤其适用于有大量实时或近实时数据更新的场景。在这个特定的人脸识别项目中,编码阶段的人脸特征被存储到 MySQL 数据库中,而检测阶段则...
3. **存储模块设计**:在视频监控系统中,存储模块负责将摄像头捕获的视频流持久化保存。这通常涉及到视频编码、数据压缩和存储格式的选择。论文可能涵盖了H.264等高效编码标准,以及如何使用数据库或文件系统来组织...
在这个案例中,我们讨论的是一个基于Kohana框架构建的模块化RPC服务器。Kohana是一款用PHP开发的轻量级、安全且高效的MVC框架,它提供了强大的模板引擎、数据库抽象层以及多种工具,用于构建高效的应用程序。 首先...
此文档一共两部分,此下载链接为第1部分。 第1章 绪论 1.1 等待的真相 1.2 瓶颈在哪里 1.3 增加带宽 ...第18章 性能监控 18.1 实时监控 18.2 监控代理 18.3 系统监控 18.4 服务监控 参考文献 索引
此外,可能还包括了错误处理、缓存管理、性能监控等高级话题。 总的来说,这个压缩包提供的资源涵盖了从理论到实践的全过程,对于想要深入理解ASP.NET动态电子商务网站开发的学习者来说,是一份非常宝贵的学习资料...