一、如何设计微博点赞功能数据库?
明星的一条微博的点赞数可能有几十万,甚至百万以上。那么这个「点赞功能」(会记录谁点了赞),新浪微博的数据库是如何设计的呢?
网上说用到了 Redis,那么难道是直接用 Redis 保存的(指的是持久化保存)?还是说逻辑处理在 Redis 中,之后会定时同步/持久化到 MySQL 等磁盘数据库?
概括一下:就是想弄明白「点赞」这种数据量庞大的功能,数据库是如何设计、保存的呢?
没设计过微博,也不懂新浪是怎么搞的,纯粹按照我们做流式监测项目的经验做一个设计思路。
首先每条微博你所看到的点赞总数肯定本地和后端分开,也就是你点赞后,本地加1,先保证你自己马上看到变化。然后通过点赞事件的方式传递给队列中,肯定不会直接写关系数据库,一条流量明星微博,千万粉丝点赞,评论里再点赞的请求事件挺吓人的。
先走队列,队列后面一路事件流是流式点赞统计,那么每条微博都会有个当日总数和非当天统计总数,这个流计算控制就可以了。另外保证最近一周的微博点赞统计数都在内存里,例如用Redis,一周以上的微博点赞数据都在k-v库里,例如用Hbase。内存库和kv库可以做冷热数据交换。
队列后面另一条路事件流,直接将微博点赞事件数据作为原始数据写入到大数据平台,例如hdfs,但是写入前,做一个类似hudi,parquet列格式,方便存储进hdfs的数据查询,也方便后续批量统计。
定期对大数据平台的微博点赞事件做批量统计,并定期与实时流对接的k-v库中的非当天点赞统计总数做比对,统计数字若不同,就按照大数据平台批统计结果为准,在保证一致性的前提下,同步更新内存库和k-v库。这块可以参考lambda架构的办法。
这样点赞总数总是来自当日总数和非当天统计总数之和,当日总数是实时增量的,不去理会是否正确,做好批量统计比对就一定能保证隔天以后点赞总数的准确性。如下图所示:
上述仅仅是一个思路,可以同时解决微博点赞统计准确性和点赞访问性能两个指标,实际业务肯定比这个思路复杂千百倍,但总之给大家一个理解参考的方向。
一定有人会想为什么在实时统计准确度上要这么下功夫,我想说以我们做实时流计算的经验的答案:是的。实时增量统计是不可信的,原因来自各种情况,例如计算服务重启,那么就会导致增量统计数据不准,只有通过实时与隔天分离的办法,也就是lambda的架构思想,始终保持隔天以后的统计总量来自批处理的结果。
二、如何选择实时采集数据的数据库?
前提:数据采集24小时连续不断,更新或插入数据库操作的频率大概在每秒1000 。
解决方案:
采集数据主要是看应用场景,如果是采集数据按周期整存整取,批量读取分析的话,用分布式文件系统,数据量够大,写入非常快,直接上Hadoop hdfs
但是若数据采集到,不仅要做离线分析,还需要实时的回放查找,那么对于这种情况最好的方法就是使用时序数据库,例如opentsdb,它是基于HBASE,因此底层还是依赖Hadoop hdfs。
influxdb也不错,自己实现原生数据库,只不过你要为集群模式付费,其实它们都是通过lsm-tree的nosql,对最近存储的数据,查找性能很强,但是对于历史数据的查找速度就差点。当然你也可以考虑国产清华造的IoTDB,现在也是Apache顶级开源项目了,而且也是需要通过Hadoop hdfs来保证数据可靠性!
再加一条,若应用场景不仅仅是高速写入,还可能涉及到大量的范围查找,那么就要从MongoDB这样的分布式数据库的选择基础之上进行优化,因其采用B-tree索引,范围查询的综合效果肯定是要好于基于lsm-tree的nosql(近期数据查找快),例如时序数据库基本上都是lsm-tree。但Mongo的写入一定要根据实际数据结构优化,因为你的业务基本上是1毫秒级的写入,这对于Mongo是一个不小的挑战,所以MongoDB的批量顺序写,以及加大内存资源等设置就很重要。