查询服务设计
数据获取路径
两个问题考虑:
1、老数据归档的问题。
如果所有分钟小时级的数据一直存在这个DB当中,那么DB的存储空间会被不断的消耗,性能也会不断的下降。所以一旦小时天月的数据聚合完成,我们就可以将一些老的原始数据(比如说两周或者一个月以前的数据从DB当中搬出去,挪到适合长期存储的地方去,比如说对象存储。)
这样做的原因是大部分场景下用户关注的都是近期数据。
2、对近期频繁访问的数据进行缓存。
从上图当中可以看到:
- 最上面分布式缓存:缓存近期频繁访问的数据
- 中间 DB 存储近期的数据
- 下面对象存储长期的数据
我们把缓存和 DB 当中的数据称为热数据,把长期存储当中的数据称为冷数据。
计数栈选型
总体流程
写入处理路径
假设有三个用户最近一分钟内同事观看了视频A,请求通过 API Gateway 被转发到 Counting Service, Counting Service 先将请求缓存在内存当中,后台以一分钟为周期,将请求写入 MQ 的某个分区。(这里假定相同 video Id 前缀的请求进入同一个分区),计数消费者从对应分区当中拉取消息,缓存存在内部的队列当中。 Aggregator 从内存队列当中拉取消息,聚合计算每分钟的观看量,并且以一分钟为周期将结果写入内部的第二个缓冲队列,最后 DB Writer 从内部队列当中拉取结果,最终将结果写入到 DB 当中。
查询路径
用户点击查看视频A 的观看量,请求通过API Gateway 被转发到 Query Service, Query Service 先访问分布式的缓存,如果没有缓存数据,就去后台数据库当中去查询,查询以后先讲结果缓存在分布式缓存当中,再将结果返回客户端。
计数栈选型
对于使用 spring 的项目来说
- API Gateway 网关: 可以选用 Netflix Zuul 网关或者Spring Cloud Gateway 。 网关也是需要集群和负载均衡的,所以前置需要负载均衡器
- API Gateway、查询服务、计数服务之间的服务发现问题,使用Netflix Eureka 做服务注册中心,使用Netflix Ribbon 做客户端负载
- MQ 选择主流的 Kafka,分布式缓存选用Redis Cluster,数据存储选择 Cassandra ,它比较适合大规模时间序列数据的存储。线下计算可以选用主流的 Hadoop
进一步考量和总结
更多面试问题
1、如何定位系统的性能瓶颈
显然我们需要对这个系统进行性能和压力测试。
测试的两个目的:
1、定位性能、内存和多线程问题。
2、为生产部署进行容量估算。 通过对小规模集群进行性能测试,可以获得基准性能数据,从而估算出了应对生产的流量,包括考虑高峰期的流量,我们需要申请多少的软硬件资源。
2、如何监控系统的健康状况
显然我们需要对系统进行细粒度的埋点和监控。
- 对核心监控的调用量、调用延迟错误数都要监控起来。对硬件资源包括cpu、内存磁盘的利用率也都要监控起来。
- 对消息队列中的消息堆积的情况要监控和告警。因为消息堆积是系统需要扩容的一个重要的信号。
监控的手段有很多:
例如日志监控、Metrics监控、调用链监控、还有健康检查等
3、如何确保线上系统运行结果正确
线下的功能测试。
开发一套线上的模拟程序,定期模拟一些用户的视频点击事件,写入到生产系统,同时也查询生产系统,然后后台对查询结果进行实时的校验。
如何解决热分区的问题
热点视频:用户频繁点击的视频。
对于热视频,如果我们不进行特殊处理的话,系统就会有热分区的问题。具体表现为某些 MQ 的分区或者后台数据库的分区 读写特别的频繁,严重的时候可能造成系统的性能问题。
对热分区的处理:
对这个视频Id key这个部分添加时间戳,这样可以把热点视频按时间,比方说每小时分摊到不同的分区当中去。