如何为业务产品选择一款合适的数据库?
互联网产品业务的不断发展,对数据库提出了各式各样新式的需求,于是涌现出了众多的数据库产品去迎合这些需求,导致软件开发者面对这么多选择时无从下手。
有些开发者在开发初期喜欢选择一款自己熟悉的数据库来使用,乍一看满足了所有需求,但项目后期伴随着各种新需求不断出现,问题就逐渐暴露出来。当面对这种情况时,摆在他们面前一般会有这些选择:
- 选择更换一款全新的数据库,于是不得不承担更换数据库带来大量业务代码重写的命运。
- 继续使用原来的数据库,把很多可以通过数据库实现的功能搬移放到业务代码中,从而让产品的业务逻辑越来越臃肿和复杂。
- 引入一款新的数据库,进行数据冗余,然后把一部分业务需求搬移到新的数据库产品上,但这样带来的工作量也不少。
显然这些都不是软件开发者所愿意面对的。
由于近几年一直从事与数据库密切相关的核心业务系统设计与研发,在使用各类数据库产品中也踩过不少坑,简单总结下供大家参考。本文主要以产品如何选择一款合适的数据库为主线来介绍,同时也穿插介绍写数据库使用中比较容易出现的问题,希望可以对你能有帮助。
数据库的分类
首先给大家推荐网址:https://db-engines.com/en/ranking,里面列举了 300 多种数据库产品,大部分开源和商业数据库都可以在这里找到,还包含一些数据库之间的特性对比。
在为产品数据库选型前,你首先需要对数据库产品的种类与特性有一个初步的认识,并且了解你的业务对数据库的各项功能和性能需求之后再做选择。数据库的分类有很多种方法,根据业界的一个相对普遍的认识,粗略分为下面五种:
- 关系数据库
- 文档数据库
- key-value 数据库
- 时序数据库
- 图数据库
关系数据库
关系数据库设计出来已经有几十年头了,在数据库中依旧占据着非常重要的角色,例如:Mysql、oracle、Postgres、MemSQL、GreenPlum、clickhouse、hlive 等。很多研发人员对关系数据库认识可能还是停留在大学课本上,但是目前关系数据库的发展已经发生了天翻地覆的变化。
目前关系数据库产品根据应用场景已经衍生至少几十种以上,不同种类数据库之间差别也非常大,所以在进行数据库选型时,不仅要选择数据库分类,还需要具体到某一款数据库。这里简单列举了关系数据库的现在演进过程中的一些新的特点,供你选择时参考:
-
属于 OLTP 还是 OLAP 类型?
关系数据库根据应用场景侧重点可以分为:OLTP(on-line transaction processing)和 OLAP(On-Line Analytical Processing), 也有同时兼顾 OLTP 和 OLAP 的数据库,例如 memsql。
OLTP 类型的数据库提供事务功能,严格满足 ACID 特性,实时性要求较高。而 OLAP 类型的数据库支持强大的汇聚分析能力,可能不支持事务,一般而言实时性会差一些。
clickhouse 就是一款典型的 OLAP 数据库,完全不支持事务且不保证主键唯一性,但在数据分析场景却有卓越的性能。在选择关系型数据库时,需要抛弃关系型数据库都支持事务这种旧时观点,认真了解各种数据库产品之间的差异,从而选出适合产品业务场景的数据库。
-
是否支持 JSON 格式?
现在关系型数据库和非关系型数据库的界限越来越模糊,很多关系型数据库已经支持 JSON 数据格式。关系型数据库支持 JSON 格式后,避免了软件开发者在特定场景下需要手动实现数据编解码功能,所以很受欢迎。
但有些软件开发者发现关系型数据库可以支持 JSON 格式后,就以为找到最佳选择,从而放松对数据格式和模型的设计,把关系型数据库当做文档数据库来使用,这样的观点是比较危险的。
目前关系型数据库支持的 JSON 格式在功能和性能上与传统字段还存在一些差异。在之前对比测试中,发现有些关系型数据库中 JSON 数据结构查询分析性能要比普通字段慢上几十倍,当然不同数据库的表现也不完全一致。
-
支持的存储模式?
关系数据库存储设计上可分为支持行式存储和列式储存模式,还有些支持行列混合模式,导致了数据库之间读写分析性能上较大的差异。这仅是粗略粒度的划分,具体到某一款数据库的存储设计还会有自己的特色,也需要了解关注。
针对列式存储的数据库进行整行数据更新会产生很大的开销,但进行少量字段的查询过滤分析时性能表现良好。数据存储模式与数据库在事务能力和分析性能上表现是息息相关的,所以针对产品业务选择数据库时,储存模式也是一个很重要的考量点。
-
是否需要 spark、storm 帮我分析计算?
你大概率不需要 spark、 storm 这些大数据计算引擎。很多产品在使用关系数据库的时候,当数据规模变大后会发现数据库的性能有点差,把目光投向了一些热门的大数据计算引擎,但可能一款分析能力强点的关系型数据库就满足你的需求。而引入 spark、storm 这些大数据组件,往往是需要引入的一整套生态工具链,有可能花费较大成本却没有解决你的问题。
-
性能评估是否全面?
对数据库的性能需要从多个维度去分析。以分析型关系数据库为例,不仅要关注查询分析响应速度,还要关注业务需求相关的每一个维度。例如:聚合分析支持的并发度、系统 API 能力、支持的读写能力等。而事务性数据库,在关注读写的并发能力的同时,也需要关注在数据分析上的性能表现。
文档数据库
文档数据库由于支持非常灵活的数据结构,一直受到开发者青睐,经常作为业务核心数据库来使用, 如:mongoDB、cassandra、ES 等。然而越灵活方便的数据库反而更容易被滥用, 这里简单列举了使用文档数据库过程中需要注意的一些事项:
-
区分元数据与数据
由于文档数据库支持复杂的 JSON 结果,导致很多业务产品在使用过程中不对数据模型进行抽象,把很多字段描述的元信息也一并保存到数据库中。这样会导致数据库中保存了很多的冗余信息,不仅会占有额外的磁盘空间,还会导致对数据建立索引和聚合分析时性能开销变大。
-
事务能力
很多文档数据库不支持多文档事务,仅保证单文档的变更的原子性,如果你的产品有比较强事务特性需求,在考虑选择文档数据库时一定要慎重。虽然 mongo 4.0 在以后的版本也支持了多文档的事务,但要认识到这里的多文档事务与标准关系数据库的事务还存在比较大的差异。
有些产品最初选用 Mongo 时可能没发现事务性的需求,后续发现不断有新的事务需求,只能通过复杂代码逻辑来实现一些事务需求,或用 redis 上的事务特性作为补救。随着后期事务需求增多,导致业务实现代码也越来越复杂、稳定性和性能都会变差。
当你产品中有很多表级别事务需求不断冒出时,可能因为产品初期业务分析建模时出现偏差,或者你的产品业务在做调整。这时候就需要及时调整和重构业务逻辑,把事务的职责交给能力擅长的数据库来实现。
-
不要频繁的更新数据
mongo 针对单文档的操作有非常卓越的性能,不同的编程语言都有比较成熟的 SDK,如 nodejs 的 mongoose、 ruby 的 Mongoid 等,软件开发者可以像近乎操作对象一样方便的去操作数据库中的文档记录。
这时带来另外一个问题,由于修改文档对象太方便了,产品业务代码中会出现大量的频繁的文档修改操作。单次修改都比较快,当这些修改操作加在一起产生的性能开销就会被放大,这时去重构代码或者切换其他产品时就会产生非常大的代价。
-
ES 是万能的?
经常能从一些开发者嘴里听到这句话,首先我们承认 ES 是一款性能非常优秀的数据库,支持强大搜索能力。每款数据库都有自己的特点,撇开搜索领域,如果仅对结构化数据进行聚合分析的话,有很多专业分析数据库产品的分析能力要强于 ES。
同时很多数据库也提供了一定搜索能力,并不是你的产品中发现有一个搜索功能就需要引入 ES,可能一个复杂点的查询语句就搞定了。可以看出一个发展趋势,更多数据库产品通过引入第三方插件或者增加高级别的系统 API,不断提升模糊搜索方面的能力。
key-value 数据库
Key value 的数据库种类也很多,如:aerospike,redis,memcache 等。使用 aerospike 可以快速存取经过 protobuf 格式序列化的对象,在广告业务中应用比较多。而 redis 作为一种常用 cache 手段在互联网产品服务中应用非常广泛,但在使用过程中有些使用不当的地方,简单列举了一些场景。
-
cache 效率如何?
既然作为一种 cache 方案,cache 时一定要有收益比。有些产品使用 redis 来 cache 一个 Mongo 的 根据 ID 的查询结果。前者的一次开销为 0.6ms 左右,后者的一次开销大约 1~2ms,如果命中率不高,这样的 cache 操作不仅没有提升性能,反而降低了性能,并带来很多额外的复杂度。
-
业务进程内 cache 还是 redis cache?
当使用 redis 作为 cache 方案时, 是否可以在业务进程内 cache?很多时候我们并不需要 cache 的数据在多个服务器之间共享,如果 cache 的数据量不大,而且调用频率非常高,反而基于业务进程内 cache 的性能更高。
很多语言都有比较成熟的内存 cache 库可以使用,而不是必须单独建立 Redis 数据库进行 cache,毕竟每次访问都会有网络开销。有时产品可能需要建立业务进程内 cache 和 redis cache 来应对一些不同的场景。
-
不要滥用事务能力?
新版本的 redis 增加了一些事务性的特性,例如 multi, watch,script 等,这些能力常作为补救措施来帮助产品实现一些事务需求。但要避免把很多不需要事务操作的功能使用事务性的方式去实现,从而给业务带来很多额外的复杂度。
假如你的产品业务有较强的事务需求,那 redis 事务肯定不是你的最佳选择。在你使用 multi 或者 watch 的过程中,需要注意到事务逻辑代码并不是完全在服务器上执行,中间有很多的网络开销导致事务处理时间被拉长,从而增加了冲突失败的概率。
时序数据库
时序数据库主要用于记录监控数据,在智能运维平台上应用比较多,如:openTSDB, prometheus, druid, keen 等。时序数据库有下面一些比较典型的特点:
- 数据以时间流的方式存在,每条记录包括时间戳。
- 大部分时序数据库不支持更新。
- 每条数据包括指标值和维度值,维度值不可计算。
现在主流智能运维平台都集成丰富指标监控能力,产品需要单独选用这类数据库的情况应该不多。如果你产品中需要选用这类数据库时,可以从下面几个维度来考虑。
-
每个时序数据库产品都还具有自己的特性,例如作为监控指标数控库,是否具备可扩展的指标收集插件?是否具备告警功能?以及是否方便集成第三方 BI 工具。以 prometheus 为例,支持开源的 job exporter 来收集数据,同时支持与 alertmanger 集成实现告警功能,还可以集成到 grafana 上展示和分析监控数据。
-
还需要从存储可扩展性方面考虑,有些时序数据库主要运行在单节点场景,当数据规模比较大时,需要以另外一种模式运行才可以把监控时序数据分布到不同的节点上。而有些数据库天然支持集群模式,如 druid, 但在支持集群模式的时候需要依赖第三方中间件,例如 zookepper 等,从而引入额外的运维成本。
-
是否支持计算分析能力,以及计算分析功能的丰富性也是一个非常重要的指标。有些时序数据库内集成了非常强的实时分析能力,而有些时序数据库则主要实现读写功能,需集成计算引擎的来实现分析计算。当然分析计算能力的性能是否满足需求也是一个考量点。
图数据库
图数据库在知识图谱领域应该比较广泛,有专有图数据库如 Neo4j、FlockDB 等,还有如 arangoDB 这种同时可以作为文档数据库和图数据库来使用,由于没有深入使用,这里就不做介绍了。
开源数据库,商用数据库, 云数据库, 大数据平台 你怎么选?
产品在选择一款数据库时,很多时候并不能仅根据业务功能需求来选择合适的数据库,还需要综合评估开发和运维等多方面的成本再做选择,怎么选呢?
开源数据库
选择开源数据库时需要意识到一点,现在数据库也是产品的一部分,也需要运维,先提几个发散的问题:
- 你的开源数据库有运行状态监控工具吗?
- 数据库出问题第一时间可以通知到你的团队吗?
- 这款数据库常见的异常问题你了解吗?可以快速修复吗?
- 数据库彻底挂了,你的数据有备份吗?
- 你的团队有独立的数据库运维人员吗?
现在互联网产品服务基本上是严重依赖数据库,数据库出故障很可能会造成产品服务彻底瘫痪。这里并不是鼓励大家不用开源数据库,而是在使用开源数据库的时候需要提前考虑这些因素,做到心中有数。
曾经在一个的产品中使用了开源数据库 arangoDB,在产品正式上线的第一天数据库就宕机了,在网上尝试了各种解决方法都不奏效,最后偶然的机会升级一下版本就 OK 了,真是惊心动魄。有了这次教训之后再选取开源数据库时我就变乖了不少。
如果你不是选择 mongoDB, postsql 这种非常普遍的开源数据库,有几点小建议可供参考:
- 看看这个开源数据库的社区活跃度怎么样?
- 看看这个开源数据库在 github 上的星星数目和 issue 列表怎么样?
- 是否有比较大的公司对其进行背书?
之前解决一个产品中非常棘手的性能问题时,对比分析了数十款数据库之后,综合分析后选择了 clickhouse 这款分析数据库。当时一个很重要参考点是,这款分析数据库是俄罗斯最大的搜索引擎 Yandex 的开发使用的。
商业数据库
商业数据库最典型代表的就是 mysql, oricle,不过这里我并打算多做介绍,其一是因为大家太熟悉了,其二是大部分的互联网公司的如果你的规模还不大,一般也不在你的考虑范畴内。
随着数据库需求的千差万别,涌现出一大批个性化的商业数据库产品,如果你了解这个行业,你会发现商业数据库产品的数量超过你的想象,当然大部分都是国外的产品。
这里举两个简单的例子,一个是 memsql, 另外一个是 scalemp。其中 memsql 也算是一款商业数据库,它提供的免费版本仅支持三个节点,同时对容量有严格的限制。另外一款是 scalemp,可以使用多片非易失内存构造内存集群,让你可以向访问普通内存方式访问几十 T 甚至更大的内存,这些商用版的数据库在特定业务场景中有很大的优势,在选择的时候更需要结合业务需求去考量。
我了解的与商业数据库合作的方式由两种,一部分商业数据库提供了免费版本,但有容量或者特性方面限制,限制外的功能都需要收费,而且费用也不低,另外一些商业数据库只提供商业版本。
选择商业数据库的好处是可以得到有力的运维支持,不过与个别的商业数据库产品使用发现获取的支持可能也有限。另外一点,有些商业数据库试用时需要填写一个申请表,当你填完试用表之后,对方可能发现你是中国企业就直接把你忽略了,所以提前需要有个心理准备。
云数据库
现在大型云服务厂商,例如 AWS,阿里云等,当你翻开它们数据库产品列表之后,可能会被五花八门的数据库种类所搞晕,但仔细分析之后发现基本上涵盖上面的五种类型数据库。
云服务厂商的数据库其实有两类,一种是完全自研的数据库,如 AWS redshift, 阿里云的 ADB 等性能都比较突出。另外一种占多数,其实是把第三方开源数据库或者商业数据库进行了包装部署到了云平台上了。选择云平台数据库有几个好处。
- 大部分云数据具备了很好的弹性伸缩性,可以根据业务需求快速动态的调整。
- 云平台厂商的每款数据库都有专门的研发团队,数据库配置调优方面更加专业。
- 可以一定程度上减少研发团队的数据运维成本,参加云数据库产品的发布会,会听到一个口号是:“未来数据运维工程师这个职业会逐渐消失”。
扯了这么多,其实还有一个最大的好处就是,你可以体验一把做甲方的感觉。
分析完云数据库产品时,你可能还发现一个种类:对象存储仓库,对象存储主要目的是为了解决文件存储的问题,例如很多互联网产品需要保存用户提交的图片文件等。
当产品规模很小时,可能构建一个独立的服务把文件保存到指定机器上就满足需求,但当产品保存的文件变多,并且请求量变大的时,就需要考虑选择一款对象存储仓库来解决问题。不过要注意在选取对象存储时尽量考虑使用 API 标准化的产品,例如支持 S3 的接口,以免业务接口绑定到一个特定产品上后续很难调整。
大数据平台
大数据平台是一套完整的解决方案。现在比较成熟的大数据平台集成了各种主流的大数据库产品,提供强大的消息通道,并且集成了丰富的数据计算和分析能力,同时还集成了人工智能相关能力。
如果把数据和分析的职责交给大数据平台之后,产品可以更加专注的业务逻辑上。假设业务产品的数据库规模比较大,并在数据计算分析上有很多通用需求,可以考虑选择一个大数据平台,这里我就不给个别厂商做广告了。
一款数据库能否满足你的需求?
每款数据库都有自己的特点,业务在不同场景下对数据库的需求也不一样,很多时候并不是选择一款数据库,而是选择几款数据库来满足业务各种需求场景。
简单点来考虑:
- 针对 cache 场景你可能需要考虑 memcache 和 redis。
- 核心业务如果事务性要求比较高,考虑选用事务能力强的关系数据库。如果对数据格式灵活性要求高, 反而对事务性要求较低,则可以考虑文档新数据库。
- 系统中大量的操作记录或者日志,需要经常查询分析且数据不会变更,可以考虑使用分析型数据库来保存。
- 保存文件可以使用第三方标准的对象存储服务等。
事实上核心业务的数据库选择需要考虑很多因素,首先需要对产品业务进行领域建模,分析出对数据库的各种功能与性能需求,然后基于各种数据库产品的特性并结合研发运维等各方面的成本综合考虑进行选择。
基于以上因素,很多时候需要针对核心业务区分不同的领域场景,选取不同种类的数据库。多款数据库之间各自发挥自己的特长,与产品的业务代码一起,在实现产品各种功能和性能需求前提下,最大程度的降低公司的成本。