架构师必读:日均500万数据,如何进行数据存储选型?

Posted by 陈树义 on 2021-01-24

转载自:MongoDB、ElasticSearch、Redis、HBase 这四种热门数据库的优缺点及应用场景 - 知乎

小编公司有一个消息平台,目前单表日均产生 500 万消息记录。随着业务不断发展,目前单表的容量已经突破 6 亿。原先的 MySQL 存储方式面临越来越大的瓶颈,合适的数据存储框架便成了一个非常重要的问题。

MongoDB、ElasitcSearch、Redis、HBase 是现今最火的四款 NoSQL 数据库产品。在实际的开发中,这四种数据库有什么区别?我到底该选哪个?想必这是很多互联网开发都遇到过的难题。下面就给大家总结下这四种数据库产品的特点和应用场景,希望能够帮助你更深刻的理解这四种数据库的特点,好帮助你作出正确的数据库选择。

MongoDB

MongoDB 是当今最火爆的 NoSQL 数据库。MongoDB 最早在 09 年发布,算得上是早期大数据时代的数据库代表作了。随着 MongoDB 的火爆,研发 MongoDB 的团队还专门成立了 MongoDB 公司来对 MongoDB 进行维护和推广,现在这个公司已经在纳斯达克上市,市值达到十几亿美元,算得上是技术变现的典范了。

MongoDB 最大的特点是表结构灵活可变,字段类型可以随时修改。 MongoDB 中的每一行数据只是简单的被转化成 Json 格式后存储,因此 MongoDB 中压根没有 MySQL 中表结构这样的概念,你可以直接简单粗暴的将任意结构的数据塞入同一个表中,压根不必考虑表结构的限制,更不必像 MySQL 一样因为要修改数据表结构而大费周折。简而言之,往 MySQL 写数据像是在做填空题,你写入的数据必须与最早定义的表结构一致,而往 MongoDB 写数据就像是在做问答题,想怎么写就怎么写,这灵活度不要爽太多。

说完 MongoDB 的优点也该说一说它的缺点了。MongoDB 不需要定义表结构这个特点给表结构的修改带来了极大的方便,但是也给多表查询、复杂事务等高级操作带来了阻碍。 因此,如果你的数据的逻辑结构非常复杂,经常需要进行复杂的多表查询或者事务操作,那显然还是 MySQL 这类关系型数据库更合适。

得益于 MongoDB 的这些特点,MongoDB 很适合那些表结构经常改变,数据的逻辑结构没又没那么复杂不需要多表查询操作,数据量又比较大的应用场景。 例如,有一个游戏应用,需要存储每个用户的信息,用户分为法师、战士等具有不同属性的角色,还有装备、技能等很多结构复杂的信息,游戏每次更新还可能会引入很多新的用户属性,这时如果你使用 MySQL,那么你可能需要建立很多个表,定义很多个表结构,并且游戏的每次更新也可能会给你带来重定义表结构等一堆麻烦事,而如果使用 MongoDB 则这些麻烦统统不存在,因为你可以定义只一张表便可以容纳所有的信息,而且可以随时根据新的需求增减字段。

Redis

Redis 是现在最热门的 key-value 数据库。它与 MongoDB 同在 2009 年发布,也同样是早期大数据时代的数据库代表作。

Redis 的最大特点当然就是 key-value 存储所带来的简单和高性能了。 所谓 key-value 存储,就是每一条记录只包含一个用于查询数据的 Key,以及与之对应的存储数据的 value,就如同现实生活中的门牌号与住户,而没有诸如表、字段这些常规数据库中必需有的复杂概念,所有的查询都仅仅依赖于 key 值。因此,key-value 数据库可谓是数据库中数据结构最简单的一种,也得益于这种简单的结构,再加上 Redis 会把所有数据加载到内存中的,Redis 能得到远高于 MongoDB 这类常规数据库的读写性能。当然,Redis 的功能还不止 key-value 存储这么简单,相较它的 key-value 前辈 Memcached,Redis 还支持数据持久化,list、set 等多种数据结构,主从复制备份等一些列功能,因此 Redis 绝对称得上是 key-value 数据库中功能最全面、最简单易用的款。

Redis 的 key-valule 存储带来了性能这个优势,但是也给复杂查询带来了很多局限。 由于阉割掉了数据表、字段这样的重要特性,且所有的查询都依赖 key,因此 Redis 无法提供常规数据库所具备的多列查询、区段查询等复杂查询功能。同时,由于 Redis 需要把数据存在内存中,这也大大限制了 Redis 可存储的数据量,这也决定了 Redis 难以用在数据规模很大的应用场景中。

Redis 牺牲了常规数据库中的数据表、复杂查询等功能,换来了很大的性能提升,特别适合那些对读写性能要求极高,且数据表结构简单(key-value、list、set 之类)、查询条件也同样简单的应用场景。 如果你的数据表结构还挺复杂,你还经常需要做一些复杂查询操作,那你最好还是老老实实用 MongoDB 或者 SQL 吧。

ElasticSearch

相较于 MongoDB 和 Redis,晚一年发布的 ES 可能知名度要低一些,但是 ES 在搜索引擎领域的名声绝对是是响当当的。相较于其他高大上的数据库产品,ES 的出身要屌丝很多。ES 的创建者 Shay Banon 曾经是一个失业的屌丝程序员,在无事可干的时候为了方便老婆搜索食谱而创建了 ES(当然,当时还不叫 ES)。

不料无心插柳柳成荫,成就了今天最热门的搜索引擎数据库,果然妹子才是程序员工作的最大动力啊!ES 也专门成立了自己的 Elastic 公司已经获得数亿美金融资,当年的屌丝程序员 Shay Banon 也早已逆袭成为 CEO 并走上人生巅峰。诸位程序员看官读完这个故事是不是也已经开始内心澎湃的想象自己出任 CEO 迎娶白富美那一天了?

ES 的特点,正如其名,那就是搜索。 严格的说,ES 不是一个数据库,而是一个搜索引擎,ES 的方方面面也都是围绕搜索设计的。ES 支持全文搜索,这里简单解释下什么是全文搜索:对于 “我在北京的一家互联网公司工作” 这样的数据,如果你搜索 “北京”、“互联网”、“工作” 这些关键词都能命中这条数据的话,这就是全文搜索,你每天都在用的百度、Google 都属于全文搜索。值得一提的是,ES 的全文搜索对中文也有很好的支持(单是中文分词器就有很多种),绝对能够满足国内大多数人的全文搜索需求。除了搜索之外,ES 还会自动的替你对所有字段建立索引,以实现高性能的复杂聚合查询,因此只要是存入 ES 的数据,无论再复杂的聚合查询也可以得到不错的性能,而且你再也不用为如何建立各种复杂索引而头痛了。

说了这么多 ES 的优点,你是不是觉得 ES 简直万能了?可惜不是的,ES 也有很多的短处,最明显的就是字段类型无法修改、写入性能较低和高硬件资源消耗。 前边讲到 ES 会自动的替你建立索引,尽管这能给全文搜索以及聚合查询带来很多好处还能替你省了建索引这一麻烦事,但是这个特性也会带来一堆问题。ES 需要在创建字段前要预先建立 Mapping,Mapping 中包含每个字段的类型信息,ES 需要根据 Mapping 为字段建立合适的索引。由于这个 Mapping 的存在,ES 中的字段一但建立就不能再修改类型了。

例如,你建的数据表的某个字段忘了加全文搜索,你想临时加上,但是表已经建好并且已经有很多数据了,这时候该怎么办呢?不好意思,你只能把整个数据表删了再重建一遍!因此,ES 在数据结构灵活度上高于 MySQL 但远不如 MongoDB。ES 的缺点还不止这些,自动建立索引使得 ES 的写入性能也收到了影响,要明显低于 MongoDB。

对于同样的数据 ES 占用的存储空间也要明显大于 MongoDB(建那么多索引能不占空间吗?),对硬件资源的消耗也是非常厉害,大数据量下 64G 内存 + SSD 基本是标配,算得上是数据库中的贵族服务了,因此如果你的老板很小气,对于 ES 的选用可要慎重喽!

ES 的全文搜索特性使它成为构建搜索引擎的利器。除此之外,ES 很好的支持了复杂聚合查询这一特点还使得 ES 非常适合拿来作数据分析使用。 其实,ES 还专门做了与自己配套的 ELK 套装,给你提供从日志收集到数据可视化分析的一条龙服务,绝对是构建高大上数据分析平台的利器。但是,ES 的高成本和低写入性能这些缺点也注定了它不适合用在那些数据价值不高、对写入性能有要求、数据量大而成本受限的场景中。

HBase

HBase 是 Hadoop 项目的一部分,而且是当年谷歌大数据三驾马车之一的 BigTable 方案的实现,因此绝对算得上是大数据时代最有代表性的技术之一了。

作为 Hadoop 系列产品之一,HBase 也继承了 Hadoop 项目的最大优点,那就是对海量数据的支持,以及极强的横向(存储容量)扩展能力。 和 Redis 类似,HBase 也需要为每一行数据定义一个 key,之后所有的查询都依赖这个 key 进行。但是不同的地方在于,HBase 中的一行数据还可以有非常多的列项(类似 MongoDB 字段),数据会按照列进行分组和存储,同一列的数据存储在同一个地方,这也是 HBase 被称为列式存储数据库的原因。其实从本质上来说,HBase 相当于是把逻辑上的一张大表按照列族分拆成若干张小表分别进行存储,不仅是列,数据的行数到达一定数量后表也会再被拆分。因此,HBase 能够把巨大的表分布到很多台机器上,从而容纳规模近乎无限的数据。同时,对 HBase 进行横向扩展也非常方便,你基本只需要添加新的机器,而不用对数据做任何改动,就可以实现数据库容量线性的增长,这在其他 SQL 数据库中是难以做到的(尽管其他数据库也有诸如 MongoDB 分片集群之类的功能帮助你进行数据规模横向扩展,但是无论是在实施的难度上还是在对数据的影响方面这些都无法跟 HBase 相提并论。)

HBase 的列式存储特性带来了海量数据规模的支持和极强的扩展能力,但是也给数据的读取带来很大的局限。由于只有同一列族的数据才会被存放在一起,而且所有的查询都必须要依赖 Key,这就使得很多复杂查询难以进行。例如,如果你的查询条件涉及多个列项,或者你无法获取要查询数据的 key,那么查询效率将会非常低下。因此,HBase 仅仅适合。

HBase 的列式存储特点带来了对海量数据的容纳能力,因此非常适合数据量极大,查询条件简单,列与列之间联系不大的轻查询应用场景。最典型的比如搜索引擎所使用的网页数据库。HBase 不适合数据结构复杂,且需要复杂查询的应用场景。另外值得一提的是,HBase 是很重的一款产品,需要依赖很多的 Hadoop 组件,因此如果你的数据规模不大,那就完全没必要杀鸡用牛刀,MongoDB 这类产品完全可以更好的满足你的需求。

总结

以上四种数据库是当今 NoSQL 中最火爆的几款,掌握了它们,你基本就能 cover 住互联网开发中的绝大多数数据存储需求。这里还想强调的一点是,如同买衣服一样,没有最好的数据库,只有最适合你的应用场景的数据库,因此选用一款数据库前一定要想清楚自己的应用场景是否合适。再给大家总结下这些数据库的适用场景:

如果你对数据的读写要求极高,并且你的数据规模不大,也不需要长期存储,选 redis;

如果你的数据规模较大,对数据的读性能要求很高,数据表的结构需要经常变,有时还需要做一些聚合查询,选 MongoDB;

如果你需要构造一个搜索引擎或者你想搞一个看着高大上的数据可视化平台,并且你的数据有一定的分析价值或者你的老板是土豪,选 ElasticSearch;

如果你需要存储海量数据,连你自己都不知道你的数据规模将来会增长多么大,那么选 HBase。

中间件数据规模查询性能写入性能复杂查询、检索
MongoDb❤❤❤❤❤❤❤❤❤❤❤
Redis❤❤❤❤❤❤❤❤
ElasticSearch❤❤❤❤❤❤❤❤
HBase❤❤❤❤❤❤❤❤❤