zoukankan      html  css  js  c++  java
  • 系统设计总结

    如何处理一个系统面试题---基本套路:

    4S分析法:Scenario场景、Service、Storage、Scale:

    • 程序 = 算法 + 数据结构
    • 系统 = 服务 + 数据存储

    核心思想:trade-off分析,用这种设计有什么不好,有什么好

    三大步骤

    1. 向面试官提问:分析功能/需求/QPS/存储容量
    2. 画图:根据分析结果设计可行方案:Service + Storage
    3. 优化:研究可能遇到的问题,怎么样scale
    • 过程
      • Scenario 场景

        • 和面试官讨论

        • 搞清楚需要设计哪些功能

        • 并分析出所设计的系统大概所需要支持的 Concurrent Users / QPS / Memory / Storage 等

      • Service 服务

        • 合并需要设计功能,相似的功能整合为一个Service
      • Storage 存储

        • 对每个 Service 选择合适的存储结构

        • 细化数据表单

        • 画图展示数据存储和读取的流程

      • 得到一个 Work Solution 而不是 Perfect Solution

      • 这个Work Solution 可以存在很多待解决的缺陷


    1.Scenario : 描述使用场景,约束和假设

    1. 问清楚自己要做哪些功能
    2. 问清楚或者说清楚自己要handle多大用户量,面试官起码得给你确认这么几个信息,否则聊不下去。
      • 一个是你平均每天handle多少用户
      • 一个是你峰值(最多?不太精确但是形容一下)每天handle多少用户
    3. 自己把自己要算的东西都算出来:
      • QPS存储size,不非得一口气全部算完,但是记住最基本的用户量,然后再说然后的。

    分析出QPS的作用:

    • QPS = 100
    • 用你的笔记本做 Web 服务器就好了
    • QPS = 1k
    • 用一台好点的 Web 服务器就差不多了
    • 需要考虑 Single Point Failure
    • QPS = 1m
    • 需要建设一个1000台 Web 服务器的集群
    • 需要考虑如何 Maintainance(某一台挂了怎么办)
    • QPS和 Web Server (服务器) / Database (数据库) 之间的关系
    • 一台 Web Server 约承受量是 1k 的 QPS (考虑到逻辑处理时间以及数据库查询的瓶颈)
    • 一台 SQL Database 约承受量是 1k 的 QPS(如果 JOIN 和 INDEX query比较多的话,这个值会更小)
    • 一台 NoSQL Database (Cassandra) 约承受量是 10k 的 QPS
    • 一台 NoSQL Database (Memcached) 约承受量是 1M 的 QPS

    2.创建设计概要

    使用所有重要的组件来描绘出一个概要设计。搭架子,我的系统要干嘛,为了做这件事情,我们需要什么组件,怎么安排。这里一切最简单,保证这个东西可以work,不要有明显的优化还不做。

    这里可以说出要设计哪些服务Service,比如设计一个音乐播放系统,则需要这几个服务:

    • User Service
    • Channel Service
    • Music Service

    3.设计核心组件:Service、Storage服务和存储

    • 将大系统划分为小服务
    • 为每个服务选择合适的存储结构,以及设计数据库的表结构

    4.Scale度量你的设计

    确认和处理瓶颈以及一些限制。举例来说就是你需要下面的这些来完成拓展性的议题吗?

    • 负载均衡
    • 水平扩展
    • 缓存
    • 数据库分片

    题目1: 设计一个用户系统,实现功能包括注册、登陆、用户信息查询、好友关系存储:

    1. 询问需求、场景:估算QPS

    2. 设计可行解:有哪些Service 和Storage,数据流流向是怎样?

      • (1) AuthService : 负责登录注册

        • 用户是如何实现登陆和保持登陆的?
          会话表Session,将session_key作为cookie返回给浏览器 => 浏览器保存cookie => 之后用户每次向服务器发送访问,都会自动带上cookie => 此时服务器会检测到请求中的cookie中的session_key,得到这个用户信息.
          数据库中存有一个Session_Table

        • Cache-Aside和Cache-Through:

          • Memcached 是一个 Cache-aside 型的 Database

          服务器分别与 DB 和 Cache 进行沟通 DB 和 Cache之间不直接沟通 业界典型代表:Memcached + MySQL

          • Redis 是读写操作都很快的 Cache-through 型 Database

          服务器只和 Cache 沟通 Cache 负责 DB 去沟通,把数据持久化 业界典型代表:Redis(可以理解为 Redis 里包含了一个 Cache 和一个 DB)

      • (2) UserService : 负责用户信息存储与查询

      • (3) FriendshipService: 负责好友关系存储

        • 怎么存?SQL vs NOSQL

        SQL一条数据以row为单位;
        NOSQL的column是动态的,可以无限大,可以随意添加;一条数据以grid为单位, row_key + column_key + value = 一条数据

        • 以Cassandra为例剖析典型的NoSQL数据结构
    3. 优化

      • how to scale?
        • 单点失效:数据库sharding和replication
          • sharding:
          • 纵向切分:直接不同的表存在不同的机器上
          • 横向切分:粗暴的方法直接按照user_id % 10 进行拆分;好的方法:一致性Hash算法

    题目2: 设计一个TinyURL

    1. 询问需求、场景:估算QPS (一天有24 * 60 * 60 = 86400秒)
      • 询问面试官日活跃用户,假设100m
      • 推算写一条TinyRUL的QPS:
        • 假设每个用户每天发0.1条带tinyUrl的微博,则100M * 0.1 / 86400 ~ 10M / 100k ~ 约等于100
        • 峰值Peak QPS: 100 * 2 ~ 200 (假设峰值大概是平时的2倍)
      • 推算读一条TinyURL的QPS:
        • 假设每个用户每天点击1条带tinyUrl的微博,则100M * 1 / 86400 ~ 1k
        • 峰值Peak QPS: 2k (假设峰值大概是平时的2倍)
      • 推算每天产生的TinyURL所占的存储:
        • 100M * 0.1 ~ 10M条,每条url长度100算,一共1G

    可以看出来这题流量并不是很大,所以不需要考虑很多的高性能,只要设计出可行解,主要是说明出Service,是怎么存的,怎么取的.

    1. 设计可行解:有哪些Service 和Storage,数据流流向是怎样?

      • (1) UrlService:

        • UrlService.encode(long_url)
        • UrlService.decode(short_url)
        • 访问端口设计:首先将长网址encode为短网址,然后用户输入这个短网址,浏览器会重定向才到decode后的真正的url
      • (2) Storage数据存取:

        • SQL vs NoSQL

        • 是否需要支持 Transaction?——不需要。NoSQL +1
        • 是否需要丰富的 SQL Query?——不需要。NoSQL +1
        • 是否想偷懒?——Tiny URL 需要写的代码并不复杂。NoSQL+1
        • 对QPS的要求有多高?—— 经计算,2k QPS并不高,而且2k读可以用Cache,写很少。SQL +1
        • 对Scalability的要求有多高?—— 存储和QPS要求都不高,单机都可以搞定。SQL+1
        • 是否需要Sequential ID?—— 取决于你的算法是什么

      • (3) long2short hash算法:

        • 算法1: 进制转换:Base62,根据数据库的自增id来, 将这个整数id转化成6位的62进制的数(0-9, a-z, A-Z)
        • 算法2: 随机生成: 随机生成一个6位的shortURL,在数据库查一遍,如果没用过,则使用;
    2. 优化:
      (1)缓存memchache:
      (2) sharding

    3. 知识点:

      一致性Hash算法

      • 在横向扩展时,减少数据的移动

      • 原理:

        • 一个简单的一致性Hash算法:

        • 将 key 模一个很大的数,比如 360
        • 将 360 分配给 n 台机器,每个机器负责一段区间
        • 区间分配信息记录为一张表存在 Web Server 上
        • 新加一台机器的时候,在表中选择一个位置插入,匀走相邻两台机器的一部分数据

        • Consistent Hashing —— 更实用的方法 : 
          思想:就是将机器看成1000个虚拟节点,利用key的hash值找key在的机器
          具体算法:

          • 将整个 Hash 区间看做环
          • 这个环的大小从 0~359 变为 0~2 64 -1
          • 将机器和数据都看做环上的点
          • 引入 Micro shards / Virtual nodes 的概念

          • 一台实体机器对应 1000 个虚拟点 Micro shards / Virtual nodes

          • 每个 virtual node 对应 Hash 环上的一个点
          • 每新加入一台机器,就在环上随机撒 1000 个点作为 virtual nodes
          • 需要计算某个 key 所在服务器时

          • • 计算该key的hash值——得到0~2 64 -1的一个数,对应环上一个点
            • 顺时针找到第一个virtual node
            • 该virtual node 所在机器就是该key所在的数据库服务器

          • 新加入一台机器做数据迁移时

          • • 1000 个 virtual nodes 各自向顺时针的一个 virtual node 要数据

      数据库备份 -- Replica 数据备份

      • Replica
        • 是实时的, 在数据写入的时候,就会以复制品的形式存为多份
        • 当数据丢失的时候,可以马上通过其他的复制品恢复
        • Replica 用作在线的数据服务,分摊读

      • MySQL Replica

      Master-Slave模式:Master 负责写,Slave负责读


    题目3: 设计一个推特

    1. 询问需求、场景:

      • (1) 估算QPS

        • 日活用户:150M,每个用户每天平均请求次数:60,则QPS = 150M * 60 / 86400 ~ 100k
        • 峰值Peak = 100k * 3 ~ 300k
        • 读频率:300k
        • 写频率:5k
      • (2) 设计功能

        • Post / Share a tweet
        • Timeline / News Feed
        • Follow / Unfollow a user
        • Register / Login
        • User Profile Display / Edit
    2. 设计可行解:有哪些Service 和Storage,数据流流向是怎样?将大系统拆分为小服务

      • (1) Service

        • User Service
        • Tweet Service
        • Media Service
        • Friendship Service
      • (2) Storage

        • Pull Model: 获得每个关注对象发的推特,然后在内存中merge
          复杂度:O(N) N为关注的好友,为N次DB Reads时间

          • 缺点:查询O(N)哥个关注对象的过程是阻塞的,会非常慢
        • Push Model: 为每个用户见一个news feed list,用户发一个帖子时,将帖子推送到关注该用户的news feed list中;关键词: Fanout;所以那个用户get的时候直接从news feed list中取就行了,不用再查数据库了;

          • 优点:可以将Post tweet到news feed list中的过程变为异步的:不再用户发帖的过程中执行,无需用户等待;

          • 缺点:不及时,fanout执行可能带来延迟,

          • 数据表设计:News Feed Table

          id、owner_id、tweet_id、created_time
          
          • push模型系统结构图:

          push模型

    3. 优化

      • (1)加Cache:最慢的部分发生在用户读请求时(需要耗费用户等待时间),在 DB 访问之前加入Cache :Cache 每个用户的 Timeline

  • 相关阅读:
    优雅得使用composer来安装各种PHP小工具
    Docker学习总结之Docker与Vagrant之间的特点比较
    深入理解php 匿名函数和 Closure
    laravel 拾遗 中间件
    centos 手动编译 fcitx 各种问题大全
    Install haroopad on centos7
    centos7 編譯 chmsee
    centos 7 禁用笔记本触摸板设置
    理解 Linux 配置文件
    输入法环境变量XMODIFIERS/GTK_IM_MODULE
  • 原文地址:https://www.cnblogs.com/shawshawwan/p/10186072.html
Copyright © 2011-2022 走看看