海量数据查询方案设计

时间:2023-01-05 07:17:20

原始数据的数据量太大了,能存下来就很不容易了,这个数据是没法直接来给业务系统查询和分析的:

  • 数据量太大了
  • 也没有很好的数据结构和查询能力,来支持业务系统查询

一般用流计算或批计算,把原始数据再进行一次或多次过滤、汇聚和计算,把计算结果落到另外一个存储系统,由这存储再给业务系统提供查询支持。“流计算”指Flink、Storm实时计算,批计算是Map-Reduce或Spark非实时计算。

像点击流、监控和日志这些原始数据是“海量数据中的海量数据”,这些原始数据经过过滤汇总和计算之后,大多数情况下数据量会有量级下降,如从TB级别的数据量,减少到GB级别。

有的业务,计算后的数据非常少,如按天粒度的汇总数据或排行榜类数据,用什么存储都能满足要求。有些业务没法通过事先计算的方式解决全部的问题。原始数据经过计算后产生的计算结果,数据量相比原始数据会减少一些,但仍然是海量数据。还要在这个海量数据上,提供性能可以接受的查询服务。

1 分析类系统如何选择存储?

查询海量数据的系统,大多都是离线分析类系统,你可以简单地理解为类似于做报表的系统,也就是那些主要功能是对数据做统计分析的系统。这类系统是重度依赖于存储的。选择什么样的存储系统、使用什么样的数据结构来存储数据,直接决定了数据查询、聚合和分析的性能。

分析类系统对存储的需求:

  • 用于分析的数据量比在线业务大出几个数量级,这需要存储系统能保存海量数据
  • 能在海量的数据上做快速聚合、分析和查询。“快速”前提是处理GB、TB甚至PB级海量数据,在这么大的数据量上做分析,几十s甚至几min都算很快,和在线业务要求的毫秒级速度不一样
  • 由于数据大多异步写入,对写入性能和响应时延要求不高
  • 分析类系统不直接支撑前端业务,所以也不要求高并发

存储产品

如果你的系统的数据量在GB量级下,MySQL仍可考虑,查询能力足以应付大部分分析系统的业务需求。并可和在线业务系统合用一个数据库,不用做ETL(数据抽取),省事且实时性好。最好给分析系统配置单独的MySQL实例,避免影响线上业务。

数据量级超过MySQL极限,可选列式数据库,如:HBase、Cassandra、ClickHouse,这些产品对海量数据,都有非常好的查询性能,在正确使用,10GB量级的数据查询基本上可以做到s级返回。高性能代价是功能缩水,这些数据库对数据的组织方式都有一些限制,查询方式上也没MySQL灵活。

另一选择是ES,本来是一个为了搜索而生的存储产品,但是也支持结构化数据的存储和查询。由于它的数据都存储在内存中,并且也支持类似于Map-Reduce方式的分布式并行查询,所以对海量结构化数据的查询性能也好。

ES对数据组织方式和查询方式的限制,没有其他列式数据库那么死板。即ES的查询能力和灵活性是要强于上述这些列式数据库的。优先考虑ES。但是ES有一个缺点,就是你需要给它准备大内存的服务器,硬件成本有点高。

数据量级超过TB级的时候,对这么大量级的数据做统计分析,无论使用什么存储系统,都快不到哪儿去。这个时候的性能瓶颈已经是磁盘IO和网络带宽了。这种情况下,实时的查询和分析肯定做不了。解决的办法都是,定期把数据聚合和计算好,然后把结果保存起来,在需要时对结果再进行二次查询。这么大量级一般选择保存在HDFS中,配合Map-Reduce、Spark、Hive等等这些大数据生态圈产品做数据聚合和计算。

根据查询选择存储系统

面对海量数据,仅根据数据量级选择存储系统远不够。“我的系统,每天都产生几个GB的数据量,现在基本已经慢得查不出来了,你说我换个什么DB能解决?”对不起,换什么数据库也解决不了你的问题。为什么这么说?

过去几十年,存储技术和分布式技术,在基础理论方面并没有本质突破。技术发展更多的是体现在应用层,如集群管理简单,查询更自动化,像Map-Reduce这些。不同的存储系统之间,并没有本质的差异。它们的区别只是,存储引擎的数据结构、存储集群的构建方式,以及提供的查询能力,这些方面的差异。这些差异,使得每一种存储,在它擅长的一些领域或者场景下,会有很好性能表现。

如RocksDB、LevelDB,它们的存储结构LSM-Tree,就是日志和跳表的组合,单从数据结构的时间复杂度上来说,和“老家伙”MySQL采用的B+树,有本质的提升吗?没有吧,时间复杂度都是O(log n)。但是,LSM-Tree某些情况下利用日志有更好的写性能表现。没有哪种存储能在所有情况下,都具有明显的性能优势,存储系统没有银弹,不要指望简单更换一种数据库,就解决数据量大,查询慢问题。

但特定场景通过一些优化方法,把查询性能提升几十倍甚至几百倍都有可能。根据查询来选择存储系统和数据结构。用Elasticsearch构建商品搜索系统就是把这个思想实践得很好的一个例子。ES倒排索引并没有比MySQL的B+树更快或更先进,但面对“全文搜索”查询需求,倒排索引就比使用其他的存储系统和数据结构,性能高出几十倍。

京东物流之所以这么快,有套智能补货系统,根据历史的物流数据,对未来的趋势做出预测,来给全国每个仓库补货。这样京东就可以做到,你下单买的商品,很大概率在离你家几公里那个京东仓库里就有货,这样自然很快就送到了。这个系统的背后,它需要分析每天几亿条物流数据,每条物流数据又细分为几段到几十段,那每天的物流数据就是几十亿的量级。

这份物流数据,它的用途也非常多,如智能补货系统要用;调度运力的系统也要用;评价每个站点儿、每个快递小哥的时效达成情况,还要用这个数据;物流规划人员同样要用这个数据进行分析,对物流网络做持续优化。

什么样的存储系统保存这些物流数据,才能满足这些查询需求?任何一种存储系统都满足不了这么多种查询需求。要根据每一种需求专门选择合适存储系统,定义适合数据结构,各自解决各自的问题。而不是用一种数据结构,一个数据库去解决所有问题。

对于智能补货和运力调度这两个系统,区域性很强,可把数据按照区域(省或者地市)分片,再汇总一份全国的跨区物流数据,绝大部分查询都可落在一个分片上,查询性能很好。

对站点和人的时效达成情况,这种业务的查询方式以点查询为主,考虑事先在计算时,按站点和人把数据汇总好,存放到一些分布式KV存储,做到毫秒级查询性能。

对物流规划的查询需求,查询方式是多变的,可以把数据放到Hive表中,按照时间进行分片。按时间分片是对查询最友好的分片方式。物流规划人员可以在上面执行一些分析类查询任务,一个查询任务即使是花上几个小时,用来验证一个新的规划算法,也是可以接受的。

总结

海量数据的主要用途,就是支撑离线分析类业务的查询,根据数据量规模不同,由小到大可选:关系型数据库,列式数据库和一些大数据存储系统。TB量级下数据,若可接受相对较贵的硬件成本,ES很好。

对于海量数据来说,存储系统无银弹,重要的是思想,根据业务对数据查询方式,反推数据应该使用什么存储系统、如何分片,以及如何组织。即使是同样一份数据,也要根据不同的查询需求,组织成不同的数据结构,存放在适合的存储系统中,才能在每一种业务中都达到理想的查询性能。

FAQ

做一个日志系统,收集全公司所有系统的全量程序日志,给开发和运维人员提供日志的查询和分析服务,你会选择用什么存储系统来存储这些日志?原因是什么?

为什么 Kafka 能做到几倍于 HDFS 的吞吐能力,技术上的根本原因是什么?

这个问题的最根本原因是,对于磁盘来说,顺序读写的性能要远远高于随机读写,这个性能差距视不同的磁盘,大约在几十倍左右。Kafka是为顺序读写设计的,儿HDFS是为随机读写的设计的,所以在顺序写入的时候,Kafka的性能会更好。

对于思考题,会选择 ES 作为存储系统,这里是因为是
1: 日志一般是根据时间线来保存的,而且不用保存历史的数据,只需要保存最近 15天或者 7天的数据就可以满足要求,数量量不是很大
2: 查看日志的时候一般都会使用全文搜索, ES 可以高效的支持全文搜索

对内存数据库有个疑问,是启动之后他会把放到硬盘的数据放到内存里?还是查询过一次之后把结果放到内存里?启动之后他会把放到硬盘的数据放到内存里

es作为分布式内存数据库,这个如何理解?es并没有像redis一样,把所以数据都存储在内存?ES是“可靠的”存储,而Redis是“不可靠的”存储。

数据量没到PB的时候直接用ES,再大的话,估计得用MR了,但MR会不会太慢了?

这个时候的性能瓶颈已经网络和磁盘的IO了。而且MR的“慢”也是相对的,当查询数据量足够大的时候,MR的性能还是非常不错的。