查看: 28557| 回复: 24
跳转到指定楼层
上一主题 下一主题
收起左侧

一同攻克系统设计与构架

   
全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
大家好我是 《面试官教你破解系统设计题》  https://www.1point3acres.com/bbs/thread-171320-1-1.html 的作者

一亩三分地的小伙伴们有没有兴趣一起攻克系统设计与构架?

目标是方便 1 )做系统和 2 )做管理都能够很方便地有相应的背景知识,更高效率和更省钱地做出健壮的和大规模的系统。当然,对你构架面试也会有帮助。

内容是旧金山湾区公司面试的真题与解答。

点此进入 >>> https://github.com/puncsky/system-design-and-architecture <<<

攻克的方法是,针对主流的互联网产品的系统构架和常用的理论,调研市面上的解决方案,择优录用,去繁就简,像是做幻灯片一样都过一遍,观其大略,不求甚解。参考链接在每一篇基本上都有具体列出。

大多数内容是英文的,欢迎中文翻译 :)

最后,希望集社区的力量,互通有无,一起把这件事情做到世界一流!

英文 Tg 交流群: https://t.me/system_design_and_archiecture

中文微信交流群




最后,因为我是一亩三分地的老用户,为了回馈地里,如果有新的进展,会持续首发在一亩三分地。


补充内容 (2019-10-10 03:04):
由于现在人数较多,需微信加 onetptp 拉你入群

评分

参与人数 21大米 +42 收起 理由
HCaffrey + 2 很有用的信息!
hptg1994 + 1 给你点个赞!
艾利克斯 + 3 给你点个赞!
格罗鸽鸽飞 + 2 非常感谢,很有帮助!
英勇的麦克斯 + 1 给你点个赞!

查看全部评分


上一篇:Google工程师分享的10 大类常考面试算法
下一篇:container / kubernetes 开发 深挖

本帖被以下淘专辑推荐:

推荐
 楼主| puncsky 2019-11-24 16:17:45 | 只看该作者
全局:
本帖最后由 puncsky 于 2019-11-24 16:21 编辑

谷歌的软件工程:软件开发

本文首发于硅谷io


业界公认,谷歌是一家工程能力超强的公司。它有哪些好的工程实践?我们可以在里面得到哪些启发?其中又有哪些地方是被人诟病的?这些内容比较细致我们慢慢讲,本篇主要是讲开发。


代码库

  • 截止15年有 20 亿行代码存在少量的 Monorepo 单一代码库中,绝大部分代码对所有人是可见的。谷歌鼓励工程师见到有问题就可以改,只要所有人审核通过,就能进库。
  • 几乎所有的开发都是在代码库的头部 (head) 进行的,而不是在分枝上,避免 merge 时候遇到问题,安全修复也更方便。
  • 每个改动都会触发测试,有错几分钟内就能通知作者和审查者。
  • 代码库的每个子树至少有两个所有人,其他开发者可以提交修改,但是所有人批准才能进库。

构建系统

  • 分布式构建系统 Blaze 让编译、链接、测试轻松快速。
  • 成百上千台机器。
  • 可靠性高,确定的依赖输入导致确定的结果输出,不会出现奇怪的不确定的抖动。
  • 快。一个构建结果缓存了,依赖它的构建会直接采用缓存,不必重新勾结。只会重新构建改动的部分。
  • 提交前自检 (pre-submit checks)。一些快速的测试可以在提交前先执行。

代码审查

  • 有代码审查工具
  • 所有改动必须有审查
  • 发现 bug 之后可以去之前的那个审查上指出问题,相关人员会被邮件通知到
  • 实验性质的代码不用强制审查,但是生产环境下的代码一定会被审查
  • 鼓励每个改动尽量小。百行以内是“小”,三百行以内是“中”,一千行以内是“大”,超过一千行是“超tm大”。

测试

  • 单元测试
  • 集成测试、回归测试
  • 提交前检查
  • 自动生成测试覆盖率
  • 部署之前做压力测试,并产生相应的关键指标,尤其是延迟、错误率随着负载的变化

Bug 追踪工具



Bugs, feature requests, customer issues, process 等等都记录起来,需要时常 triage 以确认优先级然后分配给相应的工程师。

编程语言
  • 限制有五个官方语言 C++, Java, Python, Go, JavaScript,以便代码重用和开发协作。每种语言有风格指南。
  • 工程师要经历代码可读性培训。
  • 当然某些场合的 DSL (Domain-specific language) 也不可避免。
  • 这些语言之间的数据交互主要是通过 protocol buffers。
  • 通用流程很重要,不同的语言,同样的工作流程

Debug 和分析工具

  • 服务器崩溃时,崩溃信息会自动记录下来。
  • 内存泄漏会附带上当前的 heap 对象。
  • 有大量的 web 工具帮你检测 RPC 的请求、改变设置、资源消耗等等。

发布

  • 大多数的发布工作是普通的工程师自己做的
  • 及时发布很重要,因为快速的发布节奏能够极大地激励工程师多干活、更快地得到反馈
  • 典型的发布过程:
    • 找最新的稳定 build ,做一个 release branch,可能再附带 cherry-pick 一些小改动
    • 跑测试与构建、打包
    • 发布到 staging 服务器上内部测试,这时候可以 shadow 一下线上的流量,看看有没有问题
    • 发布到 canary 上承接少量的流量公开测试
    • 逐渐发布给所有的用户

对发布的审查



用户可见的、或者是重大的发布必须有相关的法务、隐私、安全、可靠性、业务需求相关的审查批准,确保相关人员被通知到。有专门的工具来辅助这个流程。

尸检报告


有重大的 outage 事故发生之后,相关责任人必须写尸检报告,内容包括
  • 事件标题
  • 总结
  • 影响:发生了多久、影响了多少流量、损害了多少利润
  • 时间轴:记录时间的发生、诊断和消弭
  • root causes
  • 做的好的地方,做的不好的地方:有什么经验能够帮助他人在下一次更快更准地找到并解决问题?
  • 接下来的可行动作:有什么接下来可以做的事情能够避免将来类似的事情发生?
对事不对人,这里的关键是理解问题本身、以及将来如何避免类似问题。

重写代码


大量的软件每隔几年就会被重写一次。坏处是确实成本高,好处是
  • 保持敏捷。市场在变,软件的需求也一直在变,代码也需要随之变化以应对不时之需。
  • 降低复杂度。
  • 传承知识给新人,让他们有拥有感。
  • 提高工程师的移动性,促进跨领域创新。
  • 采用最新的技术栈和方法论。

我的评论



谷歌的单一代码库和强大的构建系统是小公司不可学的,毕竟小公司没有资源和能力让构建系统快到敏捷可用;保持小、简单、快速会让小公司跑得更顺畅,更加专注于核心业务逻辑。
构建系统通常是定制化的,你的知识无法迁移和衍生。强大的构建系统对新手甚至是有害的,因为提高了新手俯瞰全局的成本。
知识无法迁移和衍生也是完善的内部工具 (in-house tools) 的问题。我在职业生涯中会尽量避免使用不会开源的内部工具,比如 Uber 的 Schemaless,只针对特定的场景且没打开放出来算做大做强 ;而相反的, Linkedin 的 Kafka 则是一个有开放性和衍生性的知识的好产品。
在公开市场,这整个开发、测试、集成、发布的流程都有非常好的工具帮你来做,举个 JS 社区的例子:
[td]
流程工具
代码库Github, Gitlab, Bitbucket, gitolite
代码审查Github Pull Requests, Phabricator
提交前自检、测试与 Linthusky, ava, istanbul, eslint, prettier
Bug TrackingGithub Issues, Phabricator
测试与持续集成CircleCI, TravisCI, TeamCity
部署发布在线服务的 Heroku, Netifly, 发布移动 App 的 Fastlane, 发布库的 NPM


最后,我可能有一个洞见,不注重这些工程流程自动化的细节的公司,在工程上会损失巨大的竞争力。我甚至为了良好的工程实践自己配了一个 JS 全栈开发框架 OneFx。快节奏与慢节奏、高质量与低质量差别,通常是指数级别的,因为 —— 通常,快会让你更快更多,差会让你更差更少。


如果这篇文章对你有帮助,请在 github 上 follow 我
回复

使用道具 举报

推荐
 楼主| puncsky 2019-10-8 17:45:28 | 只看该作者
全局:
本帖最后由 puncsky 于 2019-10-8 17:50 编辑

Designing Airbnb or a hotel booking system
Requirements
  • for guests
    • search rooms by locations, dates, number of rooms, and number of guests
    • get room details (like picture, name, review, address, etc.) and prices
    • pay and book room from inventory by date and room id
      • checkout as a guest
      • user is logged in already
    • notification via Email and mobile push notification
  • for hotel or rental administrators (suppliers/hosts)
    • administrators (receptionist/manager/rental owner): manage room inventory and help the guest to check-in and check out
    • housekeeper: clean up rooms routinely
Architecture
ComponentsInventory <> Bookings <> Users (guests and hosts)
Suppliers provide their room details in the inventory. And users can search, get, and reserve rooms accordingly. After reserving the room, the user's payment will change the status of the reserved_room as well. You could check the data model in this post.
How to find available rooms?
  • by location: geo-search with spatial indexing, e.g. geo-hash or quad-tree.
  • by room metadata: apply filters or search conditions when querying the database.
  • by date-in and date-out and availability. Two options:
    • option 1: for a given room_id, check all occupied_room today or later, transform the data structure to an array of occupation by days, and finally find available slots in the array. This process might be time-consuming, so we can build the availability index.
    • option 2: for a given room_id, always create an entry for an occupied day. Then it will be easier to query unavailable slots by dates.
For hotels, syncing data
If it is a hotel booking system, then it will probably publish to Booking Channels like GDS, Aggregators, and Wholesalers.

To sync data across those places. We can
Payment & BookkeepingTo execute the payment, since we are calling the external payment gateway, like bank or Stripe, Braintree, etc. It is crucial to keep data in-sync across different places. We need to sync data across the transaction table and external banks and vendors.
Notifier for reminders / alerts
The notification system is essentially a delayer scheduler (priority queue + subscriber) plus API integrations.
For example, a daily cronjob will query the database for notifications to be sent out today and put them into the priority queue by date. The subscriber will get the earliest ones from the priority queue and send out if reaching the expected timestamp. Otherwise, put the task back to the queue and sleep to make the CPU idle for other work, which can be interrupted if there are new alerts added for today.

If you find this article helpful, please follow me on Github.
回复

使用道具 举报

推荐
 楼主| puncsky 2019-10-21 08:52:28 | 只看该作者
全局:
设计负载均衡器
需求分析

互联网服务往往要处理来自全世界的流量,但是,一个服务器只能够同时服务有限数量的请求。因此,通常我们会有一个服务器集群来共同处理这些流量。那么问题来了,怎样才能够让这些流量均匀地分布到不同的服务器上呢?

从用户到服务器,会经过很多的节点和不同层级的负载均衡器。具体来讲,我们这次设计的需求是:
  • 设计第7层的负载均衡器,位于数据中心的内部。
  • 利用来自后端实时的负载信息。
  • 服务每秒千万级的流量以及10 TB每秒级别的吞吐量。
补充:如果服务 A 依赖服务 B,那我们称 A 是 B 的下游服务,而 B 是 A 的上游服务。
挑战为什么负载均衡会很难做?答案是很难收集准确的负载分布数据。
按照数量分布 ≠ 按照负载分布最简单的做法是根据请求的数量,随机地或者循环地分布流量。然而,实际的负载并不是根据请求的数量来算的,比如有些请求很重很耗CPU,有些请求很轻量级。

为了更加准确地衡量负载,负载均衡器得保持一些本地状态 —— 比如,存当前的请求数、连接数、请求处理的延迟。基于这些状态,我们能够使用相应的负载均衡的算法 —— 最少连接、最少延迟、随机 N 取一。
最少连接:请求会被导向当前连接数最小的服务器。

最少延迟:请求会被导向最少平均反应时长且最少连接数的服务器。还可以给服务器加权重。

随机 N 取一 (N 通常是 2,所以我们也可以称之为二选一的力量):随机的选两个服务器,取两者之中最好的,能够避免最坏的情况。
分布式的环境
在分布式的环境中,本地的负载均衡器难移了解上下游服务完整的状态,包括
  • 上游服务的负载
  • 上游服务可能超级大,因此很难选择一个合适的子集接入负载均衡器
  • 下游服务的负载
  • 不同种类的请求的具体处理时间很难预测
解决方案有三种方案能够准确地搜集负载的具体情况并相应地处理:
  • 中心化的一个均衡器,根据情况动态地处理
  • 分布式但是各个均衡器之间要共享状态
  • 服务器返回请求的时候捎带上负载信息,或者是均衡器主动询问服务器
Dropbox 在做 Bandai 的时候选择了第三种方案,因为这很好地适应了现行的随机 N 选一的算法。

然而,与原配的随机 N 选一的算法所不同的是,不是使用本地的状态,而是选择服务器实时返回的结果。
服务器使用率:后端服务器设置了最大负载,数当前的连接,然后计算出使用率,范围是从 0.0 到 1.0.

有两个问题需要考虑:
  • 处理错误: 如果 fail fast ,由于处理得很快,反而会吸引更多的流量产生更多的错误。
  • 数据要衰减: 如果服务器的负载太高,没有请求会发到那里。因此,使用一个类似于反 S 曲线的衰减函数来保证老数据会被清理掉。
结果: 服务器接收的请求更加的均衡了

如果这篇文章对你有帮助,请在 github 上 follow 我

更多内容,请访问我的博客





回复

使用道具 举报

🔗
miaoxinhuili 2019-10-9 00:34:40 | 只看该作者
全局:
谢谢分享 祝福祝福
回复

使用道具 举报

无效楼层,该帖已经被删除
🔗
森林火柴 2019-10-9 12:17:37 | 只看该作者
全局:
谢谢分享,正在努力,希望可以有所贡献
回复

使用道具 举报

🔗
 楼主| puncsky 2019-10-9 15:51:51 | 只看该作者
全局:
本帖最后由 puncsky 于 2019-10-9 15:57 编辑

Lyft 的营销自动化平台 Symphony
获客效率问题:广告投放如何花更少的钱用更少的人得到更高回报?具体来讲,Lyft 的广告投放要服务如下特点
  • 管理基于地域的 campaign
  • 数据驱动的增长:增长必须是规模化的、可测量的、可预测的
  • 支撑起 Lyft 独特的增长模型,如图:

主要的挑战是:难以规模化管理跨地域营销中的各个环节,广告竞标、预算、素材、激励、选择受众、测试等等。下图是营销者的一天:

我们可以发现“执行”占去了大部分的时间,而更少的时间花在了更重要的“分析和决策”上。规模化意味着减少繁复的操作,让营销人员专注于分析与决策。
解决方案:自动化为了降低成本,提高做实验的效率,需要
  • 预测新用户是否对产品感兴趣
  • 多渠道优化,有效评估和分配预算
  • 方便地管理上千个 campaigns
数据由 Lyft 的 Amundsen 系统做增强学习。
自动化的部分包括:
  • 更新 bid 的关键词
  • 关掉效果不好的素材
  • 根据市场改变 referrals values
  • 找到高价值的用户 segment
  • 在多个 campaign 中共享策略
构架
技术栈:Apache Hive, Presto, ML platform, Airflow, 3rd-party APIs, UI.
具体的组成模块LTV 预测模块用户的终身价值是衡量渠道的重要标准,预算由 LTV 和我们愿意为该地区的获客付出的价格共同决定。
我们对新用户的认知有限,随着交互的增多,所提供的历史记录会更准确地预测。
一开始的特征值:

随着历史上的交互记录的积累,做出的判断就会越准确:

预算分配模块搞定了 LTV,接下来是根据价格定预算。拟合出 LTV = a * (spend)^b 形式的曲线以及周围的区间里类似参数的曲线。为了找到全局最优,需要付出一些随机性的代价。

投放模块分为两部分,一部分是调参者,一部分是执行者。调参者根据定价,设定基于渠道的具体的参数;执行者把这些参数执行到具体的渠道上。
有很多流行的投放策略,在各色的渠道中,是共通的:

总结要注意人的经验在系统中的重要性,否则会 garbage in, garbage out. 当人从繁琐的投放任务解放出来,专注于理解用户、理解渠道、理解自身要传达给受众的信息之后,就能够获得更好的投放效果——花更少的时间达到更高的 ROI。



如果这篇文章对你有帮助
在 Github 上 Follow 我 :)


回复

使用道具 举报

🔗
 楼主| puncsky 2019-10-9 16:11:25 | 只看该作者
全局:
本贴内容及后续更新会移动至 https://www.1point3acres.com/bbs/thread-558127-1-1.html
回复

使用道具 举报

🔗
nebulaliang 2019-10-10 01:19:24 | 只看该作者
全局:
微信交流群的图片下载不了, 提示:“抱歉,您没有权限下载本附件”
回复

使用道具 举报

无效楼层,该帖已经被删除
🔗
 楼主| puncsky 2019-10-10 03:04:24 | 只看该作者
全局:
nebulaliang 发表于 2019-10-10 01:19
微信交流群的图片下载不了, 提示:“抱歉,您没有权限下载本附件”

由于现在人数较多,需微信加 onetptp 拉你入群
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表