logsystem是一道最近在facebook面试中经常遇到的问题,本文抛砖引玉,介绍我关于该问题的思考。
需求
是用来收集什么日志? => 收集手机app的crush记录
收集日志的目的? => 分析crush的原因 => 最好需要上层的查询分析接口
日志的存储时间?永久还是有期限? => 两年 or 永久?为了估算空间
数据特点
- Crush收集的记录可能经常会发生变化
时间 模块 错误信息 栈信息等 - 写明显大于读
潜在的需求
估计
并发量
考虑Facebook全球十亿台设备,万分之一的机会一台设备发生bug,那么每秒的平均请求量:
1000,000,000 / 100 = 1000w
1000w / 24 60 60 = 1000w / 8w = 250 qps
考虑巅峰是平均请求量的20倍,qps = 5000,仍然很小,并发压力不存在
容量
考虑一条crush记录,1kb。暂且考虑存2年,那么容量为:
1kb 1000w 365 * 2 = 8TB
开始时可考虑2块2TB磁盘
系统原型
mobile -> service -> queue
/ | \
storage aggregater alert
用户协议:可考虑http或者udp
从简单实现角度入手,采用http请求,发送json数据
考虑性能可采用udp,丢数据是可以接受的
Mobile
考虑实现:每次崩溃后,写入记录到本地,下次启动时发送。
优化: 发送时,对同类错误进行去重和汇总后发送,避免同一请求发送多次。
Service
功能:请求的路由,安全,流量控制。
最简单的办法采用Nginx,利用upstream模块,反向代理到消息队列中
Storage
非关系型数据存储,可考虑HBase, MongoDB。
Aggreagator
对数据按照时间、类型维度进行汇总,存入统一数据库,用于查询
设计可能存在的问题
数据跨地域存储,造成分析时难度。每次分析可能只能分析一个地域的数据。跨地域,跨表的Join的速度可能存在问题。
解法:考虑引入一个中间节点,定时汇总多个地域的数据。
nginx访问hbase可能因为网络问题等原因,造成短时间吞吐较低,形成瓶颈。
解法: 考虑nginx每次接收到Crush记录后,写入磁盘。由后台收集日志程序,发送请求到hbase端。
总结
在系统初期,在每个地域部署一台服务器,需要最少三台数据服务器,每个服务器需要至少2T硬盘,可坚持半年,并且每半年增加2T。
系统上线之后,可考虑加入日志收集模块,减少nginx与数据服务器的交互。并且引入数据汇聚节点,定期同步在各个地域的服务器。