Grokking-SDI 读书笔记

386 阅读3分钟

参考

系统设计问题

System Design Interviews: A step by step guide

  • 需求澄清
  • 系统接口设计
  • Back-of the envelope estimation 粗略估计
    • 系统规模(what scale is expected from the system)
    • 存储需求
    • 贷款需求
  • 定义数据模型(Defining data model)
  • 高级设计(High-level design)
    • 架构图
  • 细节设计(Detailed design)
    • 分布式存储
    • 多级缓存设
    • 负载均衡
  • 找到并解决系统瓶颈(Identify and resolving bottlenecks)
    • 单点问题
    • 存储备份
    • 熔断限流
    • 兜底设计

Designing a URL Shortening service like TinyURL

需求背景

系统需求及目标

  • 功能需求(Functional Requirement)
    • 给定一个URL,可以产出一个唯一的短的URL,短链接

    • 当用户点击短链接,可以重定向原始链接

    • 用户可以定制化短链接

    • 短链接应该有个默认的过期时间,用户可定制

  • 非功能需求(Non-Functional Requirement)
    • 系统高可用
    • URL重定向应该实时的,并且最小化延迟
    • 短链接应该不可预测
  • 扩展需求(Extented Requirement)

容量预估及限制

系统是一个读比较多的系统,假设读写比例100:1

  • 吞吐预估(Traffic estimates)
    • 假设一个月有500M的新URL

      100500M=>50B 100 * 500M => 50B

    • QPS预估,创建新URL

      500million/(30days24hours3600sec)200URL/s 500 million / (30 days * 24 hours * 3600 sec) \approx 200 URL/s

    • 考虑到读写比100:1, URL重定向/每秒

      100200URLs/s=20K/s100 * 200 URLs/s = 20 K/s

  • 存储预估(Storage estimates)
    • 假设每个短链接存储5年。因为500M/月的新建,链接数:

      500million5year12months=30billion500 million * 5 year * 12 months = 30 billion

    • 假设每个短链接500字节,存储容量:

      30billion500bytes=15TB30 billion * 500 bytes = 15 TB

  • 带宽预估(Bandwidth estimates)
    • 对于写请求200个/s,每秒请求大小:

      200/s500bytes=100KB/s200 /s * 500 bytes = 100 KB/s

    • 对于读请求,20K/s重定向:

      20K/s500bytes=10MB/s20K/s * 500 bytes = 10 MB/s

  • 内存预估(Memory estimates)
    • 按照八二法则,20%的URL占用了80%贷款,我们可以缓存20%的URL

    • 我们有20K/s请求,那么一天的请求:

      20K3600seconds24hours1.7billion20K * 3600 seconds * 24 hours \approx 1.7 billion

    • 缓存20%:

      0.21.7billion500bytes170GB0.2 * 1.7 billion * 500 bytes \approx 170 GB

    • 有很多duplicate请求,实际的存储低于170 GB

  • 高水平评估(High level estimates):假设一个月新建500 million URLs,读写比例100:1 | 类别 | 预估 | | --- | --- | | New URLs | 200/s200/s | | URL重定向 | 20K/s20K/s | | 入数据 | 100KB/s100KB/s | | 出数据 | 10MB/s10MB/s | | 存储5年 | 15TB缓存15TB | | 缓存 | 170GB$ |

系统API

/**
 * @param api_dev_key: The API developer key of a registed account.
 * @param orignal_url: Original URL to be shortened
 * @param custom_alias: Optional custom key for the URL
 * @param user_name: Optinal user name to be used in encoding
 * @param expire_date: Optinal expiration date for the shortened URL
 *
 * @return: succ: the shorened URL, fail: error code
 */
 
createURL(api_dev_key, orignal_url, custom_alias=None, user_name=None, expire_data=None)

/**
 * @param api_dev_key: The API developer key of a registed account.
 * @param url_key: representing the shortened URL to be retrieved
 *
 * @return: succ: 'URL Removed'
 */
deleteURL(api_dev_key, url_key)

数据库设计

image.png

基础系统设计及算法

两种方案:

Encoding actual URL

计算每个URL的唯一hash(MD5或者SHA256算法),我们仅仅预留了8字节后缀,MD5和Base64都超标了

image.png

Generating keys offline

使用KEY服务(Key Generation Service KGS)

  • 并发问题
    • KGS使用两个表存储keys:一张已用的表,一张未用的表,并且可以使用缓存加快速度
    • 使用锁
  • Key数据库大小:使用5字节KEY,总共可以产生68.7B唯一的keys 6(字节/key)68.7B(唯一key)=412GB6(字节/key) * 68.7B(唯一key) = 412 GB
  • 单点问题:使用副本
  • 每个应用服务器可以缓存keys:加快速度
  • key查找
  • Custom aliases限制

image.png

数据分区及副本

  • 范围分区
    • 基于首字母:带来数据不平衡
  • Hash分区

Cache

  • 需要多少缓存:20%的热点数据缓存,170GB左右
  • 缓存回收策略(Cache eviction)LRU(Least Recently Used)
  • 副本更新

image.png

负载均衡

三个地方可以使用负载均衡

  • 客户端和服务端
  • 服务端和数据库
  • 服务端和缓存服务

负载均衡算法:

  • Round-Robin(轮询调度算法):如果有台服务变慢,无法感知

数据清理(Purging or DB cleanup)

Lazy清理

  • 当用于访问过期的链接,我们可以删除这个链接,并返回错误给用户
  • 有个单独的清理服务,周期性从DB和Cache删除过期的链接
  • 每个链接设置一个默认的过期时间
  • 删除链接后,可以将此key重新放入key数据库,可以被重用
  • 可以删除长期未被访问的链接

image.png

监控(Telemetry)

  • 短链接被使用次数
  • 用户位置
  • 怎样存储这些采集数据
  • 热点数据击穿问题

安全和权限