
主要需求:对网站访问量进行技术(视频观看量、博客网站粉丝数、微服务调用量计数)。
需求
需求沟通
- 需求模糊需要确认细节
- 需求不明确下,不同技术背景的人会给出不同的方案
需求澄清
场景用例
量级规模(读/写)
- 每秒查询请求量
- 每个请求查询多少数据
- 每秒处理多少个视频观看记录
- 流量模式?是否有流量高峰
性能
- 预期从写入到读取数据的延迟?
- 预期 p99 读请求延迟是多少
- 高可用性(一般隐含要求)
成本
- 开发成本有什么限制?
- 运维成本有什么限制?
- 开发成员组成结构
功能需求
非功能需求
架构设计
简单架构图
部署图
存储设计
存什么
单个事件(每次点击)
聚合数据
数据库选型
结构化数据库
数据分区
主从复制
读写分离
ShardingSphere
本身需要高可用
NoSql 数据库
Cassandra
仲裁读写
支持最终一致性
支持动态添加节点
支持多数据中心
计数服务设计
数据聚合
消息队列
kafka
检查点(Checkpointing)
分区(Partitioning)
计数消费者(详细设计)
分区消费者(kafka client)
kafka client 可自动提交偏移量
计算方法
内部队列
DB Writer
死信队列
保证消息的高可用
数据填充(Data Enrichment)
添加 Cache 提高性能。
处理了每分钟的需求,如果还有更粗粒度的需求(小时、天、月)可以再次把消息发送到队列中进行计算。这是流处理的一种思想
数据接收路径(Data Ingestion path)
代理用户请求,发送数据到 MQs
相关技术点
如果实现 API Gateway 的负载均衡访问
Gateway 也是集群部署的,前置也需要负载均衡。
可以考虑 F5 或者 Nginx SLB
API Gateway 如何发现 Account Service 实例
集中式做法
Nginx + DNS
微服务注册中心
e.g. Eureka 注册中心 + Robbin 客户端
MQ 的生产者和分区之间、MQ 的消费者和分区之间的服务发现和负载均衡
相对复杂
网关如何实现容错限流
如何通过网关实现实时的防爬虫
MQ Client 同步和异步生产问题
消息格式
protobuf/json
查询服务设计
数据存储
Distributed Cache
热点数据
提高查询效率
Database
热点数据
Object Store
历史数据归档
分钟小时数据数据量大,一直存储比较消耗数据库内存,数据库性能会逐步下降。对于已经聚合完成的一个月以前的分钟小时数据,把它们存储到 Object Store。大部分场景下用户只关注近期数据,偶尔查询历史详情数据。
技术站选型
流程图
Spring Boot
负载均衡 - F5
Zull or spring cloud gateway
euraka and ribbon
Kafka
Redis
Cassandra or Hbase
Hadoop
线下计算
OSS
对象存储(长期存储)
更多的问题
如何定位系统瓶颈
性能和压力测试
核心服务:
定位性能和多线程问题 & 系统调优
对生产部署进行容量估算
获取基准性能数据
如何监控系统健康状况
对系统做细粒度的监控和埋点
服务监控
调用量
调用延迟
调用错误数
硬件资源
CPU
内存
磁盘
Java 项目
垃圾回收活动
队列
消息堆积
消息堆积是系统需要扩容的一个重要信号
监控手段
日志监控
Metrics 监控
调用链监控
健康检查
如何确保线上系统运行结果正确
完整的线下测试
确保系统功能正确。但是线下测试不能完全覆盖线上的真是流量,一些场景对数据准确性要求比较高。
确保线上服务正确行
开发一套线上模拟程序
数据是模拟的,还不能完全覆盖生产流量。
创建线下校验系统(Lambda Architecture)
引入一套线下批处理系统,比如 Hadoop/Map reduce。同时做相同计算,线下有一个校验系统对两套系统产生的结果进行校验。
如何解决热分区的问题
对于热点视频,进行特殊处理。对应的分区会产生频繁的读写。
视频 ID 添加时间戳
热点视频按时间再分区
如何监控慢消费者
TODO
总结
分布式系统设计流程主要分为五个步骤
功能需求(API)
需求用例
输入输出
非功能需求
高可用
高性能
可扩展
成本
其他
总体设计
写入路径
读取路径
详细设计
存储设计
写入处理设计
读取查询设计
分布式系统概念和技术
技术栈选型
评估
性能测试/瓶颈定位
监控
扩容升级
线上校验
扩展
监控系统
微服务调用量 or 错误数
欺诈检测系统
账户使用情况
限流系统
访问用户 IP
推荐系统
用户浏览和购买商品计数
推荐系统处理加工
今日热点
热点文章技术
等
参考
Java 实现的一致性 hash