IT技术博客大学习 共学习 共进步

系统架构

共 731 篇文章

IT 2016-03-20 22:02:49 / 累计浏览 3,594

分布式系统设计系列 -- 基本原理及高可用策略

这篇从分布式系统的基本构成讲起,将其拆解为节点、网络、存储三元组,并探讨了节点状态(有状态与无状态)及系统异常的基本分类。文章的核心在于剖析分布式环境与单节点系统的关键差异:例如,一次write()调用并不能保证对端成功接收数据;TCP协议虽可靠,但双方无法同时确认消息送达,这引出了经典的“拜占庭将军”问题。开发者必须面对多出的“超时”等第三种不可控状态,并将各种故障视为常态而非偶然。 在此基础上,文章重点解读了分布式系统的经典CAP理论(一致性、可用性、分区容忍性),阐明了强一致性与弱一致性的具体应用场景与权衡。最后,文章开始介绍应对这些挑战的设计策略,比如通过重试机制处理暂时性故障。对于希望构建健壮分布式系统的工程师而言,理解这些无法绕开的底层原理与固有约束,是进行可靠架构设计的第一步。

IT 2016-03-20 21:57:39 / 累计浏览 2,977

ZooKeeper编程指导

这篇讲的是 ZooKeeper 这个分布式协调服务的编程实战指南。作者从分布式应用开发者的角度出发,将 ZooKeeper 的核心概念与实际操作紧密结合,提供了一份从入门到避坑的完整路线图。 文章前半部分重点梳理了关键概念:比如类似文件系统的分层数据模型,以及其中每个“znode”节点可以携带数据和监听器(Watches)的特性;会话的生命周期管理,包括超时与断线重连的机制;还有确保分布式一致性的基础。这部分为理解 ZooKeeper 如何工作打下了必要的理论基础。 后半部分则深入实际编程场景,覆盖了客户端操作指南、常用语言绑定,以及简单的程序结构示例。特别值得一提的是,文章专门总结了“陷阱:常见问题和故障排查”,将分布式系统中常见的“羊群效应”、会话过期处理等难题和盘托出,实用性很强。 无论你是想了解 ZooKeeper 如何通过临时节点、顺序节点实现分布式锁、队列等协调服务,还是需要在生产环境中规避网络分区、会话管理带来的风险,这篇文章都从原理到细节给出了扎实的指引,是扎实理解并用好 ZooKeeper 不可多得的参考资料。

IT 2016-03-19 22:46:41 / 累计浏览 1,225

分布式选主 -- 利用Mysql ACID和Lease协议实现选主和高可用

在分布式系统中,选主和高可用是常见挑战。作者从实际生产场景出发,探讨了在对一致性要求并非极致严格、且允许短暂不可用的情况下,一种利用现有基础设施实现简易选主的方案。 针对ZooKeeper在节点存活不足半数时无法工作的限制,文章提出了一种基于MySQL ACID特性与Lease(租约)协议的替代设计。核心思路是利用一张MySQL表的唯一记录来维护全局Master信息,其事务特性保障了数据一致性。集群中的每个节点持有一个唯一ID,并按照约定的Lease周期进行心跳维护和竞选。 具体运作上,Master节点需定期向MySQL更新心跳,确保Lease未过期。其他Slave节点则定期检查:若发现数据库中Master的Lease已过期,便发起竞争写入自己作为新主。通过Lease机制,即使原Master因网络分区而失联,它也会在租期耗尽后自动停止服务,有效避免了“双主”脑裂问题。方案也坦诚指出了在数据库访问时延等情况下,可能存在极短时间窗口内的极限冲突,但可通过后续选举自动恢复。 该方案特别适用于需要一主一备、且对秒级故障可容忍的系统,它在ZooKeeper集群规模受限或希望降低依赖复杂度的场景中,提供了一个轻量且实用的工程化思路。

IT 2016-03-19 22:42:12 / 累计浏览 1,328

Yahoo的流计算引擎基准测试

这篇来自雅虎工程博客的文章,对他们团队开源的流计算基准测试(streaming-benchmarks)进行了详细解读。测试背景是雅虎生产环境中大规模使用Storm,但面对Flink、Spark Streaming等新兴框架的竞争,需要一份更贴近真实世界场景的性能对比报告。 基准测试设计了一个典型用例:从Kafka读取JSON事件,处理后写入Redis时间窗口计数。核心对比聚焦于三大主流引擎:Apache Storm、Apache Flink 和 Apache Spark Streaming。 测试的关键结论非常明确:Storm 0.10.0 和 Flink 0.10.1 均展现出亚秒级的低延迟特性,其中Storm在99%的百分位数上取得了最低的延迟表现,体现了其在实时性上的传统优势。Flink在保持低延迟的同时,也提供了较高的吞吐量。相比之下,Spark Streaming 1.5.1 能够支持很高的吞吐量,但代价是其端到端延迟明显高于前两者。 文章也坦诚地指出,早期版本的Flink基准测试代码存在一个调试残留问题,这提醒读者在参考任何性能数据时,都需要关注其测试条件与代码版本的严谨性。整个测试的价值在于,它并非空谈理论,而是基于一个与雅虎内部使用场景高度相似的开源基准,为不同流处理技术在延迟与吞吐量这对核心指标上的权衡,提供了直接的参考依据。

IT 2016-03-19 22:40:54 / 累计浏览 1,506

Akka简单性能分析

这篇讲的是如何把异步任务从应用服务器拆分出去时遇到的问题与选型。作者面临的需求是将异步处理独立部署,最初考虑了MQ配合线程池的传统方案,但发现这种方式在某些场景下仍需依赖共享变量(如HashMap或ThreadLocal),导致客户端阻塞,本质上并未完全摆脱多线程共享状态的并发隐患。 于是转向了更现代的Akka框架。文章梳理了Akka的核心特性:高吞吐(单机每秒千万级消息)、低内存占用(1GB内存可承载250万Actor)、弹性自愈与无中心设计。作者没有停留在理论介绍,而是用一个极简的例子——循环发送一千万条消息——做了直观的性能验证。通过VisualVM监控截图可以看出,Akka的调度器(dispatcher)仅凭三个线程就高效完成了海量异步消息的处理,展现了其轻量与高性能的特点。 整体来看,作者通过实际场景对比,清晰地指出了传统MQ方案在并发模型上的局限,并用可复现的测试案例证明了Akka在实现高性能异步处理时的优势,为架构选型提供了扎实的参考。

IT 2016-03-18 17:09:16 / 累计浏览 1,929

图解微服务架构演进

这篇讲的是随着业务规模扩大,传统单体应用架构如何一步步演进到微服务架构的完整路径。 作者从 Dubbo 用户手册的一句话切入,点明了架构升级的背景:常规垂直应用架构已无法应对互联网发展,服务化改造势在必行。文章核心是梳理了服务化架构的演进阶梯:最初是功能内聚但扩展性差的 **ORM 单体架构**;随后为提升性能,演化出便于前后端分离、加速开发的 **MVC 垂直应用架构**;当应用间交互增多,便抽离核心业务,通过 **RPC 分布式服务框架** 实现复用与整合;随着服务数量激增,需要调度中心进行统一管控,形成了 **SOA 流动计算架构**。 最终,演进到了微服务架构。它的核心思想是将功能进一步拆解为更原子、自治的服务单元进行高密度部署,以实现彻底的解耦。文章也结合敏捷开发、持续交付和容器化(Docker)等趋势,指出微服务是应对复杂度的必然演进方向。整个梳理逻辑清晰,从历史演进的角度为理解微服务提供了一个扎实的上下文。

IT 2016-03-18 17:07:19 / 累计浏览 1,566

缓存系列文章–无底洞问题

这篇讲的是分布式缓存系统中一个经典陷阱——“无底洞”问题。作者从Facebook大规模Memcached集群的实践切入,指出盲目增加节点不仅无法提升性能,反而会导致批量操作(如mget)因网络次数暴增而变慢。 问题的根源在于哈希分布下,大量key被打散到不同节点。一次批量获取需要跨多次网络IO,机器越多,耗时越长。文章对比了哈希分布与顺序分布的特点,并给出了四种应对方案:最简单的串行mget(O(n)网络时间),优化后的按节点分组串行IO(O(节点数)网络时间),以及多线程并行IO和利用Redis的hash-tag强制key到同一节点。 通过对比可以看出,从“串行mget”到“hash-tag”,核心思路都是尽可能减少网络往返次数。文章最后用清晰的表格总结了各方案的优劣与适用场景,为开发者在数据分散与访问效率之间做出权衡提供了明确参考。

IT 2016-03-09 00:16:23 / 累计浏览 2,652

系统设计典型问题的思考

系统设计面试题没有标准答案,但思考过程有章可循。这篇文章就从“问题该怎么想”入手,梳理了一套从外到内的解题框架。作者的核心观点是:不要急于画架构图,而是反复沟通澄清需求——优先搞定2-3个核心用例,明确用户与数据规模,并识别请求模型(比如读远多于写)。 在此基础上,先定义核心模型与API,再划分系统层次与组件,最后逐层细化。在细化过程中,文章重点讨论了存储选型(关系型分库分表 vs. NoSQL的CAP权衡)、集群策略、消息队列与缓存设计这几个关键环节,并强调所有优化都应建立在明确的系统瓶颈识别之上。 文章后半部分将这套思路应用到了三个经典案例中:设计微博信息流时,需权衡消息推送的push模型与拉取模型,并设计分级的缓存;设计短网址系统时,核心挑战是如何在分布式环境下高效生成全局唯一ID;而设计实时聊天系统,则需解决服务端到客户端的消息推送问题,比如采用Comet技术维持长连接。 最终,文章落脚于工程师对这类开放性问题的反复琢磨与沉淀。这些思考虽不像算法题有唯一正解,却能在实际工程中建立起至关重要的宏观设计直觉。

IT 2016-03-06 23:07:09 / 累计浏览 1,427

当前端也拥有 Server 的能力

这篇从 Fetch API、ServiceWorker 到 Cache API 出发,探讨了前端如何借助这些新接口获得传统上属于服务器端的能力。作者以 XMLHttpRequest 的繁琐写法作为对比,引出了基于 Promise 的 Fetch API 在处理请求与响应时的简洁与直观,例如只需两步即可完成 JSON 数据的获取与解析。同时,文章也客观指出了 Fetch 当前尚不支持请求中断、进度上报等局限。 文章的重点在于 ServiceWorker,它被描述为一个位于前端的“HTTP 拦截器”。通过注册一个 Worker 脚本,开发者能够完全控制特定 URL 的请求与响应,甚至可以模拟出服务端不存在的内容,清晰展示了前端如何拦截并处理网络流量,这是实现离线访问与高效缓存策略的基础。最后提及的 Cache API,则作为 ServiceWorker 的协作工具,提供了精细管理浏览器请求/响应缓存的能力。 总体来看,这篇文章串联起了三个关键 API,展示了现代前端从单纯的请求发起方,转变为能够管理请求生命周期、拦截网络通信并缓存资源的“轻量级服务端”角色。

IT 2016-03-03 14:16:06 / 累计浏览 4,299

Cuckoo Filter:设计与实现

这篇讲的是如何设计和实现一种名为 Cuckoo Filter 的高效过滤器。作者从实际业务中海量数据快速查询的需求出发,指出经典的 Bloom Filter 虽然空间利用率高,但存在无法删除元素的硬伤,一旦删除就会导致漏报。 为了解决这个问题,文章引入了布谷鸟哈希(Cuckoo Hashing)的设计思想。每个元素有两个哈希位置,发生冲突时,新元素会“踢走”原有元素,并利用其备用位置重新安置,就像布谷鸟侵占别的鸟巢一样。通过使用包含多个槽位的桶结构,可以大幅缓冲碰撞几率,实现高达 80% 以上的空间占用率(论文数据超过 90%),同时支持可靠的插入、查询和删除操作。 作者随后展示了自己用不到 500 行 C 代码实现的完整案例。核心思路是在内存中维护一个轻量级的哈希表,仅存储元素的部分摘要(tag)来快速过滤,将完整数据存放在后端存储(如 Flash)。这样查询时能最大程度避免不必要的磁盘读取。代码清晰地定义了哈希表、槽位结构,并实现了查询、插入等关键操作,验证了该方案在正确性和效率上的可行性。

IT 2016-02-16 20:34:34 / 累计浏览 3,473

三次性能优化经历

这篇分享的是作者在技术生涯中三次重要的性能优化经历,涵盖了Portal、Service和Spark三个不同场景,每次优化都持续数月,充满了挑战与实战心得。 在Portal优化中,作者强调首先厘清前后端交互模型,通过划分页面组件的动态与静态部分来实施缓存策略,并指出统一接口设计对于优化的基础性作用——杂乱无章的交互模型往往成为噩梦。Service优化则聚焦高并发查询场景,尝试了Memcached作为中心缓存以提高命中率,但需处理缓存失效带来的风险和延迟问题;同时探索了计算迁移到客户端和异步预处理,最终将数据源迁移到NoSQL的DynamoDB以减轻数据库压力。Spark优化更为系统化,作者测试了不同实例类型、内存配置和executor数量下的性能表现,评估性价比,并修正代码中的并行化问题;特别关注了异常数据量下的稳健性,如Q4业务暴涨时的处理。 作者通过这些复盘揭示,性能优化的核心始终围绕CPU、内存、网络和并行度的平衡,但具体策略需因地制宜。优化时不仅要关注单一指标,还需考虑整体系统行为,比如缓存失效时的压力转移,或Spark中

IT 2016-02-11 22:54:42 / 累计浏览 2,818

系统设计的典型分层和涉及的知识点

这篇讲的是系统设计面试中的典型套路。作者发现,许多看似复杂的设计问题,其实可以拆解为几个标准层次来思考。文章通过一张清晰的图表,梳理了从问题分析到具体技术点的完整框架。 核心将问题分为两大块:一类是“问题本身的分析”,涵盖同步/异步、消息推拉模式、数据结构设计等常见考察方向。另一类是“系统实现的分析”,又进一步细分为前端展示层、业务逻辑层,以及最复杂的数据访问层。每一层都对应着具体的挑战,比如缓存需要分层设计(冷热数据),数据库要考虑分片,而性能优化的核心始终围绕吞吐量与延迟展开。 特别值得注意的是,作者强调一致性模型是分布式系统的灵魂,读写模型则常与存储结构紧密结合。这篇文章的价值不在于给出一个标准答案,而是提供了一个结构化的思考工具,帮助你在面对任何系统设计问题时,都能快速定位关键层次,有条不紊地展开分析。

IT 2016-02-09 23:35:05 / 累计浏览 3,518

微信朋友圈技术之道

这篇讲的是微信朋友圈在面临十亿级日发布、百亿级日浏览的海量压力时,如何保障系统稳定与性能的核心架构。 微信朋友圈负责人陈明分享了其背后的技术之道。面对移动互联网汹涌的峰值流量(如春节期间流量达平日5倍),系统通过一套自动化的服务优先级策略进行应对:优先保障支付与点对点消息,然后是群聊,最后才是朋友圈。在核心架构上,朋友圈采用“写扩散”模型——用户发布内容时,会将数据副本写入每个好友的时间线表。这种看似“重”的写入,换来了极其简单可靠的读取(只读自己的时间线),大幅降低了读失败的可能性。 文章还揭示了朋友圈数据依赖的四个核心表(发布、相册、评论、时间线)及其水平扩展方式,并详细阐述了多层级容灾设计。从同城多园区无感切换,到全球多数据中心的跨地域同步,微信甚至为适应高延迟、高丢包的跨国公网环境,自研了类TCP协议以保证数据同步的效率与安全。 整个分享从数据背景、架构选型到容灾细节,清晰展示了一个超大规模社交系统如何在性能与可靠性之间做出权衡与设计。

IT 2016-02-09 23:06:49 / 累计浏览 1,709

skynet 里的 coroutine

这篇讲的是 Skynet 框架如何利用 Lua 协程,将基于回调的消息处理模型,巧妙地转换为开发者更熟悉的阻塞式 RPC 调用风格。 Skynet 本身是一个消息分发器,每个服务通过一个统一的回调函数处理消息。这种异步模型虽然高效,但写起来可能不够直观。文章深入剖析了框架内部的核心技巧:为每条进入的消息创建一个协程,并让消息处理函数运行在其中。当遇到如网络请求等需要阻塞的操作时,处理函数会通过 coroutine.yield 将控制权交还框架,并附带操作类型(如“CALL”)和会话ID。框架挂起该协程,等待结果消息到达后,再根据会话ID找到并恢复对应的协程继续执行。 文章还进一步探讨了更高级的场景:如果开发者想在消息处理中自己使用协程怎么办?此时,用户协程的 yield 会被自己的 resume 捕获,导致 Skynet 的阻塞 API 失效。为此,框架提供了 skynet.coroutine 库。它在用户 yield 的类型前加上一个“USER”标记,从而与框架的内部 yield 区分开来,确保两者能协同工作而不冲突。 作者最后分享了使用协程作为迭代器的实际案例:处理一个巨大的内存操作日志文件时,通过协程实现了流式读取和转换,避免了内存溢出,展示了这一机制在实际工程中的实用价值。

IT 2016-02-07 14:50:29 / 累计浏览 3,037

《火星救援》中你应该知道的5个高可用系统故障恢复原则

这篇文章从电影《火星救援》出发,将主角马克·沃特尼的火星生存挑战,与互联网高可用系统的故障恢复实践做了精彩类比,提炼出了五条关键原则。 作者指出,故障发生时应秉持信息透明原则,及时向内部与外部同步状态,这比隐瞒问题更能赢得理解与支援。面对紧迫的恢复时限,技术负责人需在信息不全的情况下快速决策。在解决过程中,既要鼓励工程师发挥主观能动性积极尝试,也要善于利用系统预留的“救生锤”——比如那些99.9%时间不用的功能开关或旧接口。最后,当常规手段失效时,可能需要像电影里抛弃所有负重一样,采取一些简单粗暴但有效的方法来快速恢复服务,事后再进行数据修复。 文章没有停留在抽象理论,而是紧扣电影情节与技术场景的对应点,比如NASA的新闻发布会对应故障公告,探路者号对应遗留系统,让这些工程原则变得生动可感。文末那个马克在地球喝咖啡的比喻,也巧妙点出了运维人员平凡日常中的珍贵。

IT 2016-02-07 14:49:39 / 累计浏览 1,911

Pinterest的Feed架构与算法

这篇讲的是Pinterest如何将首页Feed流从简单的时序排列,升级为高性能、高可用的个性化推荐系统。随着流量增大,约1/3的访问指向Feed页,工程师面临的核心挑战是:如何在保证99.99%可用性的前提下,为每个用户动态生成个性化的高质量内容。 核心方案是一个分层的“Smart Feed”架构。它不再按时间排序,而是按权重优先展示。系统由三个关键服务构成:Feed Worker负责接收新内容并为每个用户独立计算权重,放入优先级队列;Feed Content Generator根据队列生成新的、按优先级排序的Pin流;Smart Feed Service则负责整合新内容与历史快照,确保即使在新内容生成服务异常时,用户也能快速看到历史列表,实现优雅降级。 存储层的设计尤为巧妙。面对海量数据和高写入QPS,Pinterest采用了双HBase集群方案。主集群处理写入,通过异步任务将数据同步到备用集群。读取时则优先从轻量的“物化存储”集群获取历史列表,再与主集群的新内容合并。这一设计不仅优化了读写延迟,更通过跨可用区的备份,将整体可用性提升至99.99%以上。

IT 2016-02-07 14:25:11 / 累计浏览 1,608

YYCache 设计思路

这篇讲的是作者从实际需求出发,设计高性能iOS缓存库YYCache的思考过程。他对比了NSCache、TMMemoryCache、PINMemoryCache等主流内存缓存实现,发现它们在性能或功能上各有不足,于是YYMemoryCache采用了OSSpinLock保证线程安全,并实现了LRU淘汰算法,在基准测试中性能表现突出。 针对磁盘缓存,文章分析了基于文件、mmap和SQLite三种技术路径的优劣。作者指出SQLite在存储小数据时性能更优,且便于实现元数据管理和淘汰策略,因此YYDiskCache采用了SQLite结合文件存储的混合方案,在实测中兼顾了性能与功能。 最后,作者还对比了Realm与SQLite的性能差异,并提到Realm会向外部IP发送数据,建议开发者谨慎使用。整篇文章从技术选型到性能评测,为iOS开发者选择和构建缓存方案提供了详实的参考。

IT 2016-02-07 14:23:53 / 累计浏览 2,553

移动端图片格式调研

这篇技术调研从移动端流量与视觉体验的双重痛点出发,系统梳理了从老牌JPEG、PNG、GIF到新兴WebP、APNG、BPG的多种图片格式。作者不仅对比了它们在压缩率、透明通道、动画支持等方面的核心差异,更深入到Android与iOS底层编解码架构(如Skia、ImageIO)和具体开源库(如libjpeg-turbo、MozJPEG)的性能剖析。 文章的亮点在于其扎实的实测数据。通过在iPhone 6上对典型图形与照片素材进行编解码测试,直观呈现了不同格式在文件体积、处理速度上的权衡。例如,JPEG在quality 0.9时达到较好的质量与效率平衡;PNG处理照片类图片时体积和速度明显逊色;而WebP凭借其全能特性和广泛的应用,已成为移动端优化的重要选择。 对于关注移动端性能优化的开发者来说,这篇文章提供了清晰的选择指南:WebP是当前均衡且普及的解决方案,APNG在动图上优于GIF,而高压缩比的BPG则代表了未来方向,尽管其仍受版权与计算成本制约。

IT 2016-02-06 23:33:57 / 累计浏览 2,349

开发者应该了解的 web 性能

这篇文章的核心观点是:网站性能优化没有放之四海而皆准的标准答案,但开发者可以通过理解关键原理来做出更有效的决策。作者从影响网站速度的复杂因素出发,对比了几个常见优化手段的原理与差异。 文章首先指出,单纯追求“页面载入时间”并非最佳目标。作者以亚马逊为例,分析了其“渐进式渲染”策略:即便页面完全载入需18秒,但用户在前1.5秒就能看到首屏关键内容。这引出了对TTFB(首字节时间)的讨论,解释了它为何比整体加载时间更能反映服务器响应与网络传输效率。 具体技术对比方面,文章剖析了几个关键点:使用gzip压缩能显著减少传输字节数;优化图片(而非仅靠CSS调整大小)对移动端用户体验至关重要;清理不必要的脚本与CSS文件可以消除冗余加载。这些措施的共同点在于减少需要传输的数据量。 文章还强调了“关键渲染路径”的概念,即浏览器从获取HTML到绘制内容必须执行的步骤顺序。整体而言,作者旨在帮助开发者超越“照单全收”的优化清单,转而理解每个措施背后“为什么有效”,从而能针对自身应用进行精准调试与验证。

IT 2016-02-06 10:51:58 / 累计浏览 3,158

限流系统如何发现系统的热点

这篇讲的是如何利用限流系统的内部机制,来解决一个棘手的实际问题:如何在海量调用参数中,实时发现系统热点。 作者从热点的两个核心挑战出发:一是如何在海量参数中只保留最可能成为热点的记录,二是如何在分布式集群中高效汇总统计信息。文章的核心方案巧妙地结合了两种技术:用ConcurrentLinkedHashMap(一种LRU缓存结构)控制内存,仅保存近期访问量最高的参数;同时利用限流系统已有的动态滑动窗口算法,计算这些参数在短时间内的平滑QPS。 对于分布式统计,文章利用了限流系统自身暴露的QPS端口作为数据采集点,并通过多线程任务队列进行快速合并,使得在千台机器规模的集群上也能在数秒内获得结果。最终的性能数据表明,该方案在日常机器上可达到29万的吞吐量,内存消耗可控,有效解决了实时热点发现与系统性能之间的平衡问题。