浅谈分布式数据库该如何学习和实践 上篇

0 引言

现在分布式数据库的学习来说,最主要的困惑还是两个:

  1. 现在分布式数据库类型的产品太多
  2. 分布式数据库的许多概念,比如nosql,目前产品自身也未对概念有共识

而这篇文章将从几个角度来阐述,分布数数据库该如何学习以及实践,面对的人群,既可能是对分布式数据库有兴趣并且想要深入的初学者,也可能是一些实践在一线的技术工作人员,当然探讨为主,主要是还是理清脉络和思路。

1 数据库主要解决的问题

长话短说,数据库出现是有原因的,业务开发不擅长开发,需求有共性,且容易得出通用性解决方案,值得强调的是,这三个条件缺一不可,数据库的两大功能:

  • 以各种姿势对数据做查询(Online analytical processing = OLAP)
  • 保证多个操作要么一起完成,要么一起失败(Online transaction processing = OLTP)
  • 其他比如结构化数据,列啊,表啊,sql语法,都是实现体系,但不是数据库功能的本质

这两个功能的本质需求来源,就在于计算机系统的三级存储架构:

  • 磁盘写入慢但持久化存储(一旦写入不易丢失)
  • 内存写入读取快但非持久化存储(掉电则丢失)

试想,如果没有内存和磁盘两级存储切内存可以持久化(掉电数据不丢失),我们还需要数据库吗(或许那时候我们的数据库就只是一个解析器+KV map)

而数据库解决两个问题的方式:

  • 利用一套面向结果的SQL语法,来支持各种方式的查询,SQL的语法和标准,也不是浮沙上盖大楼,而是来源于数学中的关系代数(Relational algebra
  • 利用先在磁盘记录一条改动记录,以及回滚方式,来保证事务在掉电后仍然可以重启恢复之前的状态,概括为log write first, two phase commit

当然不同的数据库实现方式有一些差异,但是基本跳不出上面这两条的范畴。

2 分布式数据库 - 关系型数据库sharding

接着来说说分布式数据库中的关系型数据库sharding模型。

分布式数据库是为了解决单机数据库存储,IO或CPU的瓶颈而存在的

当出现单机瓶颈时,最简单的一种办法就是:将数据打散后存储在多个同样的关系型数据库中,这种方式被称为 shard nothing architecture ,这种模式一般来说,会有多个层次来实现:


  • proxy sharding,就是做一层proxy,由proxy来决定在哪个DB来执行sqljdbc中间件sharding,用中间件实现,减少了服务和网络的损耗,其他和proxy几乎一致
  • mysql的ndbcluster和fabric,这是mysql 引擎层面做的sharding
这三种方式其实都是做中间层,用转发解决了部分问题,缺点都差不多,
  • 都可以部分支持OLTP,当sharding key一致时,事务没有任何问题,但是key不一致时,跨库的事务要么效率低,要么需要人工来拆锁,不可避免,这导致了sharding key必须是一个有意义的字段(否则连事务都没法做)
    • 比如执行一句 update user set money = 100; 这样的全局sql,还是在一个大事务中,会跨库把所有的user都锁住。。
  • 支持OLAP普遍不好,特别是需要跨库join,跨库子查询,目前这种方法也部分可解,就是自己来做一些小型的map reduce,或者把sql转换后降低中间结果数据量后继续执行,一些可行的做法可以看这份ppt:vitess.io/resources/per
  • 还是OLAP的问题,OLAP都为单机执行,由于协议层执行sql的时候的假设就是sql下沉到DB层去执行,对于跨库sql,一般都只能支持到小表广播,或者是变换sql形式后下沉。
  • 对动态扩容支持的不大好,但并不是完全无法支持
    • 比如vitess的range hash方案,就可以自动扩容缩容
    • 但是由于扩容和缩容的时候有数据基线追平后才能切换,导致一般需要中断服务一定时间(几ms)
  • 这套玩意的部署和维护,需要消耗更多的开发和运维资源(相对直接用单纯的单机关系型数据库来说)

然后虽然有如此多的功能问题,但是这种sharding模式仍然受到很多大公司的欢迎,主要原因为:

  • 相对来说,每个切片(partition or fragment)仍然是一个完整的库,看得见摸得着,这让很多用户较为放心。
  • OLTP类问题,一般一个业务线可以拟定同样的sharding key,这对于业务较为成熟的大公司来说,sharding key不难确定,一旦sharding key确定,跨库事务是可以避免的。
  • OLAP类问题,只需要同步到hbase再用hive或spark来做运算即可,同步可能会消耗一定时间(比如 T+1),但是不影响大数据业务来做离线分析。
  • 少量的sql,如果是需要做分页,跨库join,也可以下沉到单库执行或是用小表广播解决。
  • 部署和维护以及稳定的开发和运维资源,向来是一些大公司的优势而不是劣势。

3 分布式数据库 - nosql分析

接下来说说nosql的一些内容,先引入一张有人的总结图:

这张图中,把nosql在食物链

上放到了关系型数据库sharding的更高层次,这点我不是特别认可,我认为nosql和关系型sharding是两种需求的产物。

简单来说,nosql就是为了获得scale out 的目的,抛弃了事务和join。

mongo可以说是一个对这个需求贯彻的比较彻底的nosql db,最近传的比较多的 rethinkdb 挂掉事件,就可以很明显对比,我认为mongo的流行是一个为产品做减法获得的胜利,我觉得mongo至少在resharding,schemaless以及分布式map reduce这三个方向上走的很对,至少对于很多的小公司,这三个特性足够了。

  • 事务可以依赖很多方式做到,不提供原生支持并不意味着做不到
  • 特别是游戏公司,scale out 的特性和resharding的特性不但可以在火爆的时候迅速缓解压力,而且可以在不活跃时由回收很多机器

nosql的一个小节:

  • nosql是一个典型的过渡性产物,舍弃了部分关系型数据库的特性,来达到scale out的特性,为了解决特定的需求所存在
  • nosql对于关系型sharding的一个优势就是运维部署成本的降低,以及存储成本的降低(一般为两个副本到三个副本的存储,如果不容灾则为一个副本)

4 小结

简单介绍了关系型数据库sharding的分布式数据库方案以及nosql方案,简单来说,分布式数据库的三个难点:

  • 事务(OLTP)
  • 分析型sql(OLAP)
  • 扩容能力(scale out)

这两个解决方案,都只能尽力解决两个:

  • 关系型数据库sharding解决了半个OLTP,半个OLAP,半个scale out
    • OLTP跨库支持不好
    • OLAP只能通过同步数据到hadoop或其他工具来做到
    • scale out在扩容和缩容方面面临大数据迁移,需要停服切换
  • nosql解决了OLAP,以及scale out
    • OLTP主动放弃,不赘述
    • OLAP效率往往不如spark或是hadoop这样专用的平台
    • scale out 则一般支持的超过关系型数据库sharding

经典的产品推荐:vitess,mongodb,都为开源产品,且代码质量不错

在下篇中将重点介绍下newSql 类产品,如google spanner等,敬请期待。

编辑于 2016-10-12