当前位置: 首页 > 科技观察

分布式数据库和Hadoop不够好,所以我们设计了一个分布式SQL计算系统

时间:2023-03-13 22:40:23 科技观察

的设计思路来解决分布式数据库下复杂的SQL(比如全局排序,分组,join,子查询,尤其是不平衡字段这些逻辑操作)是难以实施;我在分布式数据库和Hadoop的一些实际应用经验的基础上,比较了两者的优缺点,并加入了自己的一些提炼和思考,设计了一套综合利用两者优点并加以补充的系统两者的不足之处。具体是利用数据库水平分区的思想实现数据存储,利用MapReduce的思想实现SQL计算。这里数据库的水平分区只是分库,不是分表。对于不同数量的表,分库的数量可以不同。比如1亿数据量分为10个子库,10亿数据量分为50个子库。.对于使用MapReduce实现计算的想法;对于一个需求,转化为一个或多个依赖的SQL,每个SQL分解为一个或多个MapReduce任务,每个MapReduce任务包括mapsql、shuffle)、reducesql,这个过程可以理解为类似于hive,区别就是连MapReduce任务中的map和reduce操作也是通过SQL实现的,而不是Hadoop中的map和reduce操作。这是MapReduce的基本思想,但是在Hadoop生态系统中,第一代MapReduce将结果存储在磁盘上,第二代MapReduce根据内存使用情况将结果存储在内存或磁盘中.类比使用数据库进行存储,MapReduce的结果存储在表中。数据库的缓存机制自然支持根据内存情况决定存储在内存还是磁盘;另外,在Hadoop生态系统中,计算模型不是一个,这里MapReduce的计算思路可以换成类似于spark的RDD迭代计算方式;这个系统是基于MapReduce来解释的。架构基于以上思路,系统的架构如下:无代理节点有代理节点模块描述关于系统中的模块,由于与大多数分布式系统类似,这里只做简单说明:两种架构无代理节点时,有代理节点时,客户端负责比较大的任务,包括:发送请求、解析SQL、生成执行计划、申请资源、安排执行、获取结果等;当有代理节点时,代理节点负责接受请求、解析SQL、生成执行计划、申请资源、安排执行、返回结果给客户端。另外,agent节点提供了支持外部协议的接口,比如mysql的c/s协议。使用mysql命令行,可以直接连接执行SQL。整个系统就像一个普通的mysql服务器。应用架构实际应用环境可能是一套正式环境,一套正式备份环境,一套离线环境,可以按照如下架构进行部署。基本概念说明下面对架构中的一些概念进行说明。下面介绍常见的增删改查,尤其是查询操作。插入数据时,根据余额字段和余额策略,将记录插入到相应的数据库节点中。中间。更新数据时,需要根据平衡策略判断数据更新前后的数据库节点是否发生变化:如果没有变化,直接更新;如果有变化,则删除更新前数据库节点中的旧数据,并在更新后的数据库节点中插入新数据。删除数据时,根据均衡策略在对应的数据库节点中删除。这三种更改数据的操作,只要是涉及多个节点的数据更改,都需要使用分布式事务来保证一致性、原子性等事务特性。查询操作查询操作的原理和hive类似,对比一下就明白了;为了便于解释查询操作,先解释一下stagetree和stage的结构,如下图所示:stagetreestage查询步骤结合上图,具体的查询操作流程为如下:对输入的SQL进行词法、语法、语义分析,收集表结构信息和数据分布信息,生成包含多个阶段(简称阶段)的执行计划。这些阶段具有一定的依赖关系,形成一个多输入单输出系统。任务树。每个阶段包括两种SQL,分别叫做mapsql和reducesql,每个阶段包括三个操作,map,datashuffling和reduce;map和reduce分别执行mapsql和reducesql。首先在不同的数据库节点执行map操作。map操作执行mapsql。它的输入是每个数据库节点上的表里面的数据,输出是根据某个字段按照一定的规则划分,放入不同的结果集中。结果集用作数据混洗的输入。然后执行datashuffling的过程,将不同的结果集拷贝到不同的数据库节点,执行reduce。在不同数据库节点执行reduce操作,reduce操作执行reducesql;***返回结果。示例由于系统的核心在于存储和计算,下面是存储和计算相关概念的示例。平衡策略用一个例子来说明。基本信息如下:表名:tab_user_login表描述:用于存储用户登录信息节点数:4,点为0、1、2、3,举例如下策略:list:取登录省以余额字段取模hash为例:取模4,以用户id为余额字段取值范围:0到1亿,以用户id为余额字段取模hash,结合范围:先范围,再取模,以用户id为余额字段查询,说明查询操作。基本信息如下:用户表tab_user_info如下:用户登录表tab_login_info的结构如下:排序排序的关键点在于节点之间存在大小关系。一个大的key或keyrange放在一个nodeid大的节点上,然后在该节点上排序。获取数据时,按照节点id的大小依次获取。以下面的sql为例,某个注册时间范围内的用户信息按age和id排序:select*fromtab_user_infotwhereu_reg_dt>=?andu_reg_dt<=?orderbyu_id执行计划可能是:Map:select*fromtab_user_infotwhereu_reg_dt>=?andu_reg_dt<=?orderbyu_idShuffle:执行完成后,本例中,由于需要根据u_id对数据进行shuffle,所以需要根据u_id对每个存储节点进行划分。比如有N个计算节点,那么按照(***u_id-最小u_id)/N平均划分,可以将不同存储节点上相同范围的u_id划分到同一个计算节点(这里的计算节点有大小关系)。Reduce:Select*fromtab_user_infotorderbyu_id分组聚合的关键点类似于排序。节点之间存在大小关系。一个大的key或keyrange放在nodeid大的节点上,然后在该节点上进行分组聚合。获取数据时,是根据节点id的大小依次获取的。下面以sql为例,将一定注册时间范围内的用户按照年龄分组,计算每组用户数:selectage,count(u_id)vfromtab_user_infotwhereu_reg_dt>=?andu_reg_dt<=?groupbyage执行计划可能是:Map:selectage,count(u_id)vfromtab_user_infotwhereu_reg_dt>=?andu_reg_dt<=?groupbyageShuffle:执行完成后,此时需要根据age对数据进行shuffle。考虑到age的唯一值比较小,datashuffling可以将shuffle所有的Records复制到同一个计算节点。reduce:selectage,sum(v)fromtwheregroupbyageconnection首先指定join的字段类型为数值类型和字符串类型,其他类型如日期可以转换为这两种类型。numeric类型的排序很简单,string类型数据的排序需要确定规则,类似mysql中的collat??ion,比较常用的是按照unicode编码顺序,根据实际存储的大小节点等;其次,join方式有equivalentjoin和non-joinEquivalentjoin;以下面常用且比较简单的案例为例。以下面的sql为例,某个注册时间范围内用户的所有登录信息:)执行计划可能是:Map:既然是join,就要查询所有的表,每个表都要打上自己的标签。实现的时候可以加一个表名字段,在所有存储节点上执行selectu_id,u_namefromtab_user_infotwhereu_reg_dt>=?andt1.u_reg_dt<=?selectu_id,login_productfromtab_login_infotShuffle:这种情况下,因为需要根据u_id对数据进行shuffle,考虑到u_id有多个唯一值,每个存储节点需要根据u_id进行划分,比如有N个计算节点,将不同存储节点上相同范围的u_id按照(***u_id-最小u_id)/N。Reduce:selectt1.u_id,t1.u_name,t2.login_productfromtab_user_infot1jointab_login_infot2on(t1.u_id=t2.u_id)subquery由于子查询可以分解为不包含有依赖的子查询的SQL,所以生成的执行计划是多个的执行计划SQL是按照一定的依赖关系顺序执行的。hdfs与现有系统的差异和优势相比,具有规律的数据分布。hdfs启动后,需要执行命令查询文件所在的具体节点;元数据小,记录规则足够,管理成本低,开机速度快。数据放在数据库中,可以很好地利用索引和数据库本身的缓存机制,大大提高数据查询的效率,尤其是在数据量很大的情况下,使用索引查询返回一个小的数据量。可以删除和修改数据,这在基于HDFS的系统中通常很麻烦且效率低下。在计算方面,与MapReduce或其他分布式计算框架(如spark)没有本质区别(需要shuffle)。但是由于数据是有规律分布的,所以有些地方可以做得更好,这在分布式全文索引上就体现出来了。由于线上系统一般使用数据库作为最终存储位置,所以将数据库同步到hdfs比较麻烦,而且对于删除和更新的情况,同步数据麻烦且效率低,速度慢;相比之下,这种方案可以使用数据库本身提供的镜像复制功能进行同步,基本上没有额外的麻烦和低效的工作。基于以上,可以将在线系统(主系统)和离线数据分析挖掘(从系统)做成一个统一的解决方案,见应用架构图。应用场景***列举一些应用场景