当今时代,企业数据愈加膨胀。数据是企业的价值,但数据处理也是一种技术挑战。在海量数据处理的场景,即便单机计算能力再强,也没法知足日益增加的数据处理需求。因此,分布式才是解决该类问题的根本解决方案。而在分布式领域,有两类典型产品,分别是分布式存储和分布式计算。用户只有将二者的特性充分利用,才能够真正发挥分布式架构的存储和计算能力。java
本文介绍 SequoiaDB(分布式存储)和 Spark(分布式计算)两款产品的对接使用,以及在海量数据场景下如何提升统计分析性能。node
01 SequoiaDB 与 SparkSQL 介绍sql
SequoiaDB 是一款开源的金融级分布式关系型数据库,支持标准 SQL 和事务功能,支持复杂索引查询、与 Hadoop、Hive、Spark 都有较深度的集成。SequoiaDB 在分布式存储功能上,较通常的大数据产品能提供更多的数据切分规则,包括:水平切分、范围切分、主子表切分(相似 partition 分区)和多维切分方式,用户能够根据不用的场景选择相应的切分方式,以提升系统的存储能力和操做性能。数据库
Spark 近年来发展特别迅猛,使用 SparkSQL 作大数据处理和分析的开发者愈来愈多。SparkSQL 是 Spark 产品中一个组成部分,SQL 的执行引擎使用 Spark 的 RDD 和 Dataframe 实现。apache
SparkSQL 和另一款流行的大数据 SQL 产品— Hive 有类似之处,可是两款产品仍是有本质上的区别,最大的不一样点在于执行引擎,Hive 默认支持 Hadoop 和 Tez 计算框架,而 SparkSQL 只支持 Spark RDD 计算框架,可是 SparkSQL 的拥有更加深度的执行计划优化和处理引擎优化。性能优化
02 SequoiaDB 与 SparkSQL 如何整合?服务器
Spark 自己是一款分布式计算框架。它不像 Hadoop 同样,同时为开发者提供分布式计算和分布式存储,而是开放了存储层的开发接口,只要开发者按照 Spark 的接口规范实现了接口方法,任何存储产品均可以成为 Spark 数据计算的来源,同时也包括 SparkSQL 的数据来源。网络
SequoiaDB 是一款分布式数据库,可以为用户存储海量的数据,可是若是要对海量数据作统计、分析,仍是须要借助分布式计算框架的并发计算性能,提升计算效率。因此 SequoiaDB 为 Spark开发了 SequoiaDB for Spark 的链接器,让 Spark 支持从SequoiaDB 中并发获取数据,再完成相应的数据计算。架构
Spark 和 SequoiaDB 对接方式比较简单,用户只要将 SequoiaDB for Spark 链接器 spark-sequoiadb.jar 和 SequoiaDB 的 java 驱动 sequoiadb.jar 加入到每一个 Spark Worker 的 CLASSPATH 中便可。并发
例如,用户但愿 SparkSQL 对接到 SequoiaDB,能够为 spark-env.sh 配置文件中增长 SPARK_CLASSPATH 参数,若是该参数已经存在,则将新 jar 包添加到 SPARK_CLASSPATH 参数上,如:
SPARK_CLASSPATH="/media/psf/mnt/sequoiadb-driver-2.9.0-SNAPSHOT.jar:/media/psf/mnt/spark-sequoiadb_2.11-2.9.0-SNAPSHOT.jar"
用户修改完 spark-env.sh 配置后,重启 spark-sql 或者 thriftserver 就完成了 Spark 和 SequoiaDB 的对接。
03 SequoiaDB 与 SparkSQL 性能优化
Spark SQL+SequoiaDB 的性能优化将会从 connector 计算技术原理、SparkSQL 优化、SequoiaDB 优化和 connector 参数优化4个方面进行介绍。
3.1 SequoiaDB for SparkSQL
A) connector 工做原理
Spark 产品虽然为用户提供了多种功能模块,可是都只是数据计算的功能模块。Spark 产品自己没有任何的存储功能,在默认状况下,Spark 是从本地文件服务器或者 HDFS 上读取数据。而 Spark 也将它与存储层的接口开放给广大开发者,开发者只要按照 Spark 接口规范实现其存储层链接器,任何数据源都可称为 Spark 计算的数据来源。
下图为 Spark worker 与存储层中 datanode 的关系。
图1
Spark 计算框架与存储层的关系,能够从下图中了解其原理。Spark master 在接收到一个计算任务后,首先会与存储层作一次通信,从存储层的访问快照或者是存储规划中,获得本次计算任务所设计的全部数据的存储状况。存储层返回给 Spark master 的结果为数据存储的 partition 队列。
而后 Spark master 会将数据存储的 partition 队列中的 partition 逐个分配给给 Spark worker。Spark work 在接收到数据的 partition 信息后,就可以了解如何获取计算数据。而后 Spark work 会主动与存储层的 node 节点进行链接,获取数据,再结合 Spark master 下发给 Spark worker 的计算任务,开始数据计算工做。
图2
SequoiaDB for Spark 的链接器的实现原理和上述描述基本一致,只是在生成数据计算的 partition 任务时,链接器会根据 Spark 下压的查询条件到 SequoiaDB 中生成查询计划。
若是 SequoiaDB 可以根据查询条件作索引扫描,链接器生成的 partition 任务将是让Spark work 直接链接 SequoiaDB 的数据节点。
若是 SequoiaDB 没法根据查询条件作索引扫描,链接器将获取相关数据表的全部数据块信息,而后根据 partitionblocknum 和 partitionmaxnum 参数生成包含若干个数据块链接信息的 partititon 计算任务。
B) Connector 参数
SequoiaDB for Spark 链接器在 SequoiaDB 2.10以后进行了重构,提升 Spark 并发从SequoiaDB 获取数据的性能,参数也有相应的调整。
用户在 SparkSQL 上建立数据源为 SequoiaDB 的 table,建表模版以下:
create [temporary] <table|view> <name>[(schema)] using com.sequoiadb.spark options (<options>);
SparkSQL 创表命令的关键字介绍:
1. temporary 关键字,表明该表或者视图是否为邻时建立的,若是用户标记了temporary 关键字,则该表或者视图在客户端重启后将自动被删除;
2. 建表时用户能够选择不指定表结构,由于若是用户不显式指定表结构,SparkSQL 将在建表时自动检测已经存在数据的表结构;
3. com.sequoiadb.spark 关键字为 SequoiaDB for Spark connector 的入口类;
4. options 为 SequoiaDB for Spark connector 的配置参数;
SparkSQL 建表例子以下:
create table tableName (name string, id int) using com.sequoiadb.spark options (host 'sdb1:11810,sdb2:11810,sdb3:11810', collectionspace 'foo', collection 'bar', username 'sdbadmin', password 'sdbadmin');
SparkSQL for SequoiaDB 的建表 options 参数列表以下:
表1
3.2 SparkSQL 优化
用户若是要使用 SparkSQL 对海量数据作统计分析操做,那么应该从3个方面进行性能调优:
1. 调大 Spark Worker 最大可用内存大小,防止在计算过程当中数据超出内存范围,须要将部分数据写入到临时文件上;
2. 增长 Spark Worker 数目,而且设置每一个 Worker 都可以使用当前服务器左右 CPU 资源,以提升并发能力;
3. 调整 Spark 的运行参数;
用户能够对 spark-env.sh 配置文件进行设置,SPARK_WORKER_MEMORY 为控制 Worker 可用内存的参数,SPARK_WORKER_INSTANCES 为每台服务器启动多少个 Worker 的参数。
若是用户须要调整 Spark 的运行参数,则应该修改 spark-defaults.conf 配置文件,对优化海量数据统计计算有较明显提高的参数有:
1. spark.storage.memoryFraction, 该参数控制 Worker 多少内存比例用户存储临时计算数据,默认为0.6,表明60%的含义;
2. spark.shuffle.memoryFraction, 该参数控制计算过程当中 shuffle 时可以占用每一个 Worker 的内存比例,默认为0.2,表明20%的含义,若是临时存储的计算数据较少,而计算中有较多的 group by, sort, join 等操做,应该考虑将spark.shuffle.memoryFraction 调大,spark.storage.memoryFraction 调小,避免超出内存部分须要写入临时文件中;
3. spark.serializer, 该参数设置 Spark 在运行时使用哪一种序列化方法,默认为 org.apache.spark.serializer.JavaSerializer, 可是为了提高性能,应该选择 org.apache.spark.serializer.KryoSerializer 序列化。
3.3 SequoiaDB 优化
SparkSQL+SequoiaDB 这种组合,因为数据读取是从 SequoiaDB 中进行,因此在性能优化应该考虑三点
1. 尽量将大表的数据分布式存储,因此建议符合二维切分条件的 table 应该采用主子表+ Hash 切分两种数据均衡方式进行数据分布式存储;
2. 数据导入时,应该避免同时对相同集合空间的多个集合作数据导入,由于同一个集合空间下的多个集合是共用相同一个数据文件,若是同时向相同集合空间的多个集合作数据导入,会致使每一个集合下的数据块存储过于离散,从而致使在 Spark SQL 从SequoiaDB 获取海量数据时,须要读取的数据块过多;
3. 若是 SparkSQL 的查询命令中包含查询条件,应该对应地在 SequoiaDB 中创建对应字段的索引。
3.4 connector 优化
SequoiaDB for Spark 链接器的参数优化,主要分两个场景,一是数据读,另一个是数据写入。
数据写入的优化空间较少,只有一个参数能够调整,即bulksize参数,该参数默认值为500,表明链接器向 SequoiaDB 写入数据时,以500条记录组成一个网络包,再向 SequoiaDB 发送写入请求,一般设置 bulksize 参数,以一个网络包不超过2MB为准。
数据读取的参数优化,用户则须要关注 partitionmode, partitionblocknum 和 partitionmaxnum 三个参数。
partitionmode,链接器的分区模式,可选值有single、sharding、datablock、auto,默认值为auto,表明链接器智能识别。
1. single 值表明 SparkSQL 在访问 SequoiaDB 数据时,不考虑并发性能,只用一个线程链接 SequoiaDB 的 Coord 节点,通常该参数在建表作表结构数据抽样时采用;
2. sharding 值表明 SparkSQL 访问 SequoiaDB 数据时,采用直接链接 SequoiaDB 各个 datanode 的方式,该参数通常采用在 SQL 命令包含查询条件,而且该查询能够在 SequoiaDB 中使用索引查询的场景;
3. datablock 值表明 SparkSQL 访问 SequoiaDB 数据时,采用并发链接 SequoiaDB 的数据块进行数据读取,该参数通常使用在SQL命令没法在 SequoiaDB 中使用索引查询,而且查询的数据量较大的场景;
4. auto 值表明 SparkSQL 在向 SequoiaDB 查询数据时,访问 SequoiaDB 的方式将由链接器根据不一样的状况分析决定。
partitionblocknum,该参数只有在 partitionmode=datablock 时才会生效,表明每一个 Worker 在作数据计算时,一次获取多少个 SequoiaDB 数据块读取任务,该参数默认值为4。若是 SequoiaDB 中存储的数据量较大,计算时涉及到的数据块较多,用户应该调大该参数,使得 SparkSQL 的计算任务保持在一个合理范围,提升数据读取效率。
partitionmaxnum,该参数只有在 partitionmode=datablock 时才会生效,表明链接器最多可以生成多少个数据块读取任务,该参数的默认值为1000。该参数主要是为了不因为 SequoiaDB 中的数据量过大,使得总的数据块数量太大,致使 SparkSQL 的计算任务过多,最后使得整体计算性能降低。
04 总结
文章从 Spark、SequoiaDB 以及 SequoiaDB for Spark connector 三个方面向读者们介绍了海量数据下使用 SparkSQL+SequoiaDB 的性能调优方法。
文章中介绍的方法具备必定的参考意义,可是性能调优一直都是最考验技术人员的工做。技术人员在对分布式环境作性能调优时,须要综合考虑多个方面的数据,例如:服务器的硬件资源使用状况、Spark 运行情况、SequoiaDB 数据分布是否合理、连机器的参数设置是否正确、SQL 命令是否有调优的空间等,要想性能提高,重点是要求技术人员找到整个系统中的性能短板,而后经过调整不一样的参数或者修改存储方案,从而让系统运行得更加高效。