me icon indicating copy to clipboard operation
me copied to clipboard

学习笔记: 分布式系统案例课 (杨波)

Open nonocast opened this issue 2 years ago • 0 comments

如何设计一个分布式计数服务

面试官提出需要为一个类似B站视频网站在视频下方增加观看数量。

这个题有很多解法,如果不清楚需求,就会根据自身喜好产生很多解法:

  • SQL DB: MySQL, Oracle
  • NoSQL: MongoDB, Cassandra
  • Batch: Hadoop MR
  • NewSQL: TIDB
  • Cache: Redis
  • Stream: Kafka+Flink
  • Stream Cloud: Alibaba Cloud Realtime Compute

所以前提是对需求的澄清,包括:

  • 场景用例: 谁用这个系统? 用户如何使用这个系统?
  • 量级规模: 每秒查询请求? 每个请求查询多少数据? 每秒处理多少个视频观看记录? 流量模式? 是否有流量峰值?
  • 性能: 预期从写入到读取数据的延迟? 预期p99(99百分位)读请求延迟是多少? 高可用性(一般是隐含,即必须)
  • 成本: 开发成本有限制? 运维成本有限制?

接下来明确功能需求,即API

  • 处理需求: 对视频观看数进行计数
    • countViewEvent(videoId)
    • countEvent(videoId, eventType), eventTypes: view, like, share
    • processEvent(videoId, eventType, func), func: count, sum, avg
    • processEvents(listOfEvents)
  • 查询需求: 根据时间段返回视频观看数量
    • getViewsCount(videoId, startTime, endTime)
    • getCount(videoId, eventType, startTime, endTime)
    • getStats(videoId, eventType, func, startTime, endTime)

现在假定非功能需求:

  • 规模: 每秒处理1w+视频点击观看记录
  • 性能1: 写入/读取毫秒级延迟
  • 性能2: 写入到读取更新分钟级延迟,近实时流处理,最终一致
  • 高可用: 无单点失败
  • 水平按需扩展
  • 开源低成本

存储设计

  • 存什么?
    • 点击明细还是每分钟聚合数据?
    • 还是两个都存储? (好处不说了,缺点就是耗存储)
  • 数据库选型
    • 可扩展: 根据读写规模按需扩展
    • 高性能: 快速读写
    • 高可用: 不丢数据, 灾难恢复
    • 一致性折衷
    • 数据模型易于升级
    • 成本
  • MySQL 方案
    • sharding: 将A-M的存在MySQL A上,N-Z的存在MySQL B上
    • replication: A和A',B和B'分别做主从,实践中一般采用一主一从或一主二从
    • 读写分离: A负责写,A'负责读,分摊压力
    • 通过ShardingSphere(原ShardingJDBC)在客户端实现MySQL代理,避免让程序员直接面对数据库复杂度。也可以通过ShardingProxy来做独立部署,等同于配置中心加服务发现。
  • Cassandra
    • 去中心,采用gossip
    • 支持按需动态增加节点
    • 支持多数据中心
    • 运维复杂性还是比较高

nonocast avatar Jun 21 '22 08:06 nonocast