Skip to content

四火的唠叨

一个纯正程序员的啰嗦

Menu
  • 所有文章
  • About Me
  • 关于四火
  • 旅行映像
  • 独立游戏
  • 资源链接
Menu

系统设计典型问题的思考

Posted on 03/15/201509/02/2022 by 四火

CAP系统设计方面的问题问题是非常考验经验和思维过程的,而且和常见的算法问题、语言基础问题不同,涉及的面很广,还没有比较一致的判别标准。但无论如何,还是可以归纳一些常见的思路和典型问题的线索。

首先,反复沟通和澄清系统需求。只有把需求澄清清楚了,才可以开始思考并落到纸面上。但是需求的沟通应该是持续和循序渐进的,问题很难从一开始就思考全面。最重要的条目包括:

  • use cases,通常问题只需要 2~3 个 use cases 需要考虑,其他的部分会晚些考虑,或者不考虑。这样就可以简化问题。
  • 用户数量(用户可以是下游系统或者人)、数据数量,澄清这个事实无疑非常重要,对系统设计的决策有重大意义。
  • 请求模型,比如读远大于写,比如 60% 的请求都访问 top 20 的记录。

其次,尝试抽象一个简单的模型,从简单模型开始,思考不同的场景和约束,逐步完善。落实到代码上的时候,最核心的部分包括:

  • 模型的定义。
  • 代码接口,API。
  • 数据是怎样被存储的,比如表结构和文件结构。

在此基础上,考虑最基础的组件和架构划分,整个系统要分几层,有哪些组件,各自什么作用,可能的瓶颈是什么等等。还有前面的 API、模型分别被安插到哪部分上面,同时反复比较第一步的几个 use case 是否都被满足。

再次,细化层结构和组件,比如:

  • 存储层。是否需要持久化存储?选择文件、关系数据库,还是 NoSQL 数据库?
    • 如果选择关系数据库,是否需要 sharding 或 partition?参考 Quora:What’s the difference between sharding and partition?
    • 如果选择 NoSQL 数据库,CAP 中分别牺牲和优先保证哪一个?参考:Visual Guide to NoSQL System。扩容的策略(比如一致性 hash)?
    • 存储是否需要分层(比如冷层——文件、暖层——关系型数据库、热层——缓存,不同成本的存储介质,用以应付不同的数据访问频率)?
  • 集群。所有节点对等还是中心节点主备?请求负载分担的策略?如何增减节点?如何判定节点健康状况?是否需要会话?会话如何同步?Scale up 和 Scale out 的区别,参考 Wikipedia:Scalability。
  • 消息模型。生产者和消费者的速率?无法应付时是否需要缓冲队列?消息流量控制?速率控制的精细度?
  • 缓存系统。缓存的分层?分布式部署还是集中式缓存服务?使用什么缓存淘汰算法(比如 LRU)?参考:In-Process Caching vs. Distributed Caching。

其中,系统瓶颈的识别和 scale 是紧密联系着的两个话题。在需求驱使的基础上着手优化,比如缓存的应用,这需要建立在系统瓶颈被识别或者假定被识别的基础上,否则就是乱枪打鸟。在瓶颈解决之后再考虑 scale。

最后,不断讨论和完善,每一个讨论迭代都要得出一个实际的结论,避免持续停留在过高抽象层面。这里涉及的部分可以很多,包括可扩展性、数据规模、吞吐量、可维护性、实时性、数据一致性等等。

所以,归纳起来的四部分为,先从系统外部理清楚需求,接着设计核心模型和 API,再进行基本的分层和组件划分,最后才是细化每一层或者每个组件的设计。从外到内,逐层剖析。

这些点说起来容易做起来难,通过反复阅读和思考一些常见的系统设计场景,其实我们还是可以从中总结出若干规律来。

下面列出几个非常常见和典型的系统设计问题的 hints:

1、怎样设计一个微博/Twitter 系统(news feed 系统)

  • 思考读写模型,latency 上看明显是读的要求明显高于写的模式。
  • 转发和回复,拷贝原微博文字还是存储转发/回复树形关系?分析利弊。另外,这里涉及到产品设计,参见:Twitter Vs. Weibo: 8 Things Twitter Can Learn From The Latter。
  • 区分两种典型消息传播的触发方式:push on change 和 pull on demand,两种方式利弊明显。参考:Why Are Facebook, Digg, And Twitter So Hard To Scale?
  • 存储分级。这里 CAP 中 A 最为重要,往往 C 可以被牺牲,达到最终一致性。
  • 缓存设计,分层的数据流动?如何识别热门?
  • 删除微博功能的设计。

2、怎样设计一个短网址映射系统(tiny url 系统)

  • 思考读写模型,明显是读优先级高于写的服务,但是通常不需要修改。读写服务分离,在写服务崩溃时保证读服务健康运行。
  • 链接缩短使用的加密和映射的方式中,算法如何选择?短链接可以接受那些字符?此处可以估算特定的规则下长度为 n 的短链接最多可能表示多少种实际链接。
  • 如果使用统一的短链接序列分配机制,如何分布式设计这个分配逻辑?它不能够成为瓶颈。例如,一种常见的思路是让关系数据库的自增长索引给出唯一 id,但是如果不使用关系数据库,在分布式系统中如何产生唯一序列号且避免冲突?参考:如何在高并发分布式系统中生成全局唯一 Id。
  • 是否需要保留原始链接最后部分?如 http://abc.def.com/p/124/article/12306.html 压缩成 http://short.url/asdfasdf/12306.html,以增加可读性。
  • 由于协议部分可以预见或者需要支持的数量很少(比如就支持 http 和 https),是否可以考虑把协议部分略去,以枚举方式和短链接正文放在一起?
  • 由于属于 web 服务,考虑判定 URL 合法性,考虑怎样控制请求流量和应对恶意访问。

3、怎样设计一个实时聊天系统?可以是 MSN、QQ 这样的 CS 结构的,也可以是 Facebook Chat 或者微博私信这样的 BS 结构的。

  • 登陆时需要获取好友状态列表,这通常也是 priority 0 的 use case。
  • 这个问题的特点是客户端和服务端已经天然地分开了,核心问题之一是把服务端和客户端的交互梳理清楚。如果是 BS 结构的,怎样使得从服务端到客户端的消息推送成为可能?Ajax+Comet 是一个办法,hang 住连接,消息推送。还有一种办法是客户端轮询,但是显然实时性无法胜任。
  • 如果使用 Comet,服务端将存在大量的空闲连接。参考,select、poll、epoll 之间的区别总结 [整理]。对于消息的处理,引入协程,减少线程调度开销,参考:Difference between a “coroutine” and a “thread”?。
  • 如果是 CS 的,消息和状态还可以通过 P2P 的方式;但是如果是 BS 的,就必须实现一个服务端的消息系统,参考:实时通信协议 XMPP。
  • 存储方面,CAP 怎么权衡?可以牺牲掉哪一个?
  • 如果要求完成历史消息功能,那又是另一番故事了。其他值得讨论的扩展的功能包括系统消息群发、好友状态更新和消息搜索等等。

还有一些系统设计典型和经典问题,想到的先列在下面,等后续有时间总结了再补充到上面去:

  • 搜索引擎设计(包括网页爬虫)
  • 邮件系统设计(例如 GMail)

无论如何,对于这些问题的解决,反复思考是非常有趣的。这些东西貌似可以直接拿来学习的材料比较少,而且也不像算法那样丁是丁卯是卯的,评判的标准模糊得很。

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

×Scan to share with WeChat

你可能也喜欢看:

  1. 系统设计的典型分层和涉及的知识点
  2. 实际技术选型的考虑因素
  3. 常见分布式应用系统设计图解(二):Feed 流系统
  4. 系统设计中的快速估算技巧
  5. Scala 的模式匹配

3 thoughts on “系统设计典型问题的思考”

  1. dingli says:
    02/04/2017 at 3:06 PM

    zan.

    Reply
  2. rapin says:
    03/28/2015 at 7:09 AM

    虽然看不懂,但也给个赞

    Reply
  3. allen says:
    03/17/2015 at 7:56 PM

    第一次看到有关架构的文章 赞

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

订阅·联系

四火,啰嗦的程序员一枚,现居西雅图

Amazon Google Groovy Hadoop Haskell Java JavaScript LeetCode Oracle Spark 互联网 亚马逊 前端 华为 历史 同步 团队 图解笔记 基础设施 工作 工作流 工具 工程师 应用系统 异步 微博 思考 技术 数据库 曼联 测试 生活 眼界 程序员 管理 系统设计 缓存 编程范型 美股 英语 西雅图 设计 问题 面向对象 面试

分类

  • Algorithm and Data Structure (30)
  • Concurrency and Asynchronization (6)
  • System Architecture and Design (43)
  • Distributed System (18)
  • Tools Frameworks and Libs (13)
  • Storage and Data Access (8)
  • Front-end Development (33)
  • Programming Languages and Paradigms (55)
  • Testing and Quality Assurance (4)
  • Network and Communication (6)
  • Authentication and Authorization (6)
  • Automation and Operation Excellence (13)
  • Machine Learning and Artificial Intelligence (6)
  • Product Design (7)
  • Hiring and Interviews (14)
  • Project and Team Management (14)
  • Engineering Culture (17)
  • Critical Thinking (25)
  • Career Growth (57)
  • Life Experience and Thoughts (45)

推荐文章

  • 聊一聊分布式系统中的时间
  • 谈谈分布式锁
  • 常见分布式系统设计图解(汇总)
  • 系统设计中的快速估算技巧
  • 从链表存在环的问题说起
  • 技术面试中,什么样的问题才是好问题?
  • 从物理时钟到逻辑时钟
  • 近期面试观摩的一些思考
  • RSA 背后的算法
  • 谈谈 Ops(汇总 + 最终篇):工具和实践
  • 不要让业务牵着鼻子走
  • 倔强的程序员
  • 谈谈微信的信息流
  • 评审的艺术——谈谈现实中的代码评审
  • Blog 安全问题小记
  • 求第 K 个数的问题
  • 一些前端框架的比较(下)——Ember.js 和 React
  • 一些前端框架的比较(上)——GWT、AngularJS 和 Backbone.js
  • 工作流系统的设计
  • Spark 的性能调优
  • “残酷” 的事实
  • 七年工作,几个故事
  • 从 Java 和 JavaScript 来学习 Haskell 和 Groovy(汇总)
  • 一道随机数题目的求解
  • 层次
  • Dynamo 的实现技术和去中心化
  • 也谈谈全栈工程师
  • 多重继承的演变
  • 编程范型:工具的选择
  • GWT 初体验
  • java.util.concurrent 并发包诸类概览
  • 从 DCL 的对象安全发布谈起
  • 不同团队的困惑
  • 不适合 Hadoop 解决的问题
  • 留心那些潜在的系统设计问题
  • 再谈大楼扔鸡蛋的问题
  • 几种华丽无比的开发方式
  • 我眼中的工程师文化
  • 观点的碰撞
  • 谈谈盗版软件问题
  • 对几个软件开发传统观点的质疑和反驳
  • MVC 框架的映射和解耦
  • 编程的未来
  • DAO 的演进
  • 致那些自嘲码农的苦逼程序员
  • Java 多线程发展简史
  • 珍爱生命,远离微博
  • 网站性能优化的三重境界
  • OSCache 框架源码解析
  • “ 你不适合做程序员”
  • 画圆画方的故事

近期评论

  • Ticket: TRANSACTION 1.922915 BTC. Go to withdrawal >> https://yandex.com/poll/enter/BXidu5Ewa8hnAFoFznqSi9?hs=20bd550f65c6e03103876b28cabc4da6& on 倔强的程序员
  • panshenlian.com on 初涉 ML Workflow 系统:Kubeflow Pipelines、Flyte 和 Metaflow
  • panzhixiang on 关于近期求职的近况和思考
  • Anonymous on 闲聊投资:亲自体验和护城河
  • 四火 on 关于近期求职的近况和思考
  • YC on 关于近期求职的近况和思考
  • mafulong on 常见分布式基础设施系统设计图解(四):分布式工作流系统
  • 四火 on 常见分布式基础设施系统设计图解(八):分布式键值存储系统
  • Anonymous on 我裸辞了
  • https://umlcn.com on 资源链接
© 2025 四火的唠叨 | Powered by Minimalist Blog WordPress Theme