工业级数仓分层及高并发松耦合大数据平台架构深入剖析-DW商业环境实战

1,933 阅读15分钟

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。QQ邮箱地址:1120746959@qq.com,如有任何技术交流,可随时联系。

1:数据分层重要性

  • 屏蔽业务的影响,不必改一次业务就需要重新接入数据(进行业务解耦)。

  • 减少重复开发,开发一些通用的中间层数据,能够减少极大的重复计算(抽取通用数据,形成维度)

  • 一个复杂的任务分解成多个步骤来完成,每一层只处理单一的步骤,比较简单和容易理解。而且便于维护数据的准确性,当数据出现问题之后,可以不用修复所有的数据,只需要从有问题的步骤开始修复。(数据分层开发以及有步骤修复)

  • 清晰数据结构:每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解。(STAGE ,ODS ,DWD,DWS作用域各司其职)

2:工业级数据仓库分层规划与质量监控

优雅地把数据DWD层和轻度汇总层放在同一个层级上,同时独立出来了维表和临时表。

  • STAGE 层(与业务系统数据保持一致,多数据源的临时存储) STAGE 层作为数据缓冲层,主要负责采集不同类型的业务系统数据并保存一定期限内的相关业务数据,完成不同类型数据源的统一临时存储,同时避免 ETL 操作对业务系统性能造成影响,STAGE 层数据在数据结构、数据之间的逻辑关系上都与业务系统基本保持一致。

  • ODS 数据层(与业务系统数据保持一致,进行数据清洗及规范化,保证不同源数据的最终数据一致性,得到业务要求的指标数据表) ODS(Operational Data Store)层数据来源于 STAGE 层,它的数据经过了对 STAGE 层数据的清洗,包括编码表去重、去空、垃圾数据过滤、数据类型规则化等。

  • DWD 数据层(添加代理键,形成关联体系,可单独对外提供查询服务) 把 ODS 数据表结构改变成项目主题数据仓库的表结构,对 DWD 层的所有表添加了代理键,标准化了业务系统编码类型不统一的问题,建立了数据仓库维度表和事实表的关联体系,也为缓慢变化维的实现奠定了基础。

  • DWS:轻度汇总层(数据汇总,可与DWD进行并行存在) DWS:轻度汇总层,从ODS层中对用户的行为做一个初步的汇总,抽象出来一些通用的维度:时间、ip、id,并根据这些维度做一些统计值,比如用户每个时间段在不同登录ip购买的商品数等。这里做一层轻度的汇总会让计算更加的高效,在此基础上如果计算仅7天、30天、90天的行为的话会快很多。我们希望80%的业务都能通过我们的DWS层计算,而不是ODS。

    ODS -> DWS: 没必要经过 dwd。我举个例子,你的浏览商品行为,我做一层轻度汇总,就直接放在 dws 了

    DWD -> DWS: 如果所需要的资料表,要从好多表凑成一份,我们从四五份个人资料表中凑出来了一份完整的资料表放在了 dwd 中。然后在 app 层,我们要出一张画像表,包含用户资料和用户近一年的行为,我们就直接从dwd中拿资料, 然后再在 dws 的基础上做一层统计,就成一个app表了。当然,这不是绝对,dws 和 dwd 有没有依赖关系主要看有没有这种需求。

  • DWC 数据层(数据推送到业务系统,如通过消息队列进行解耦) DWC(Data Warehouse Center)层主要管理固化报表的数据存储,数据主要来源于 DWD 层,根据前台所需数据建立物理模型,使用 ETL 抽取 DWD 层数据推送给 DWC 层,这样显著减少前台应用直接关联 DWD 层查询明细数据的成本,提高平台数据获取的速度。

  • TMP:临时表(临时表关联) TMP每一层的计算都会有很多临时表,专设一个DWTMP层来存储我们数据仓库的临时表。

  • DM 数据层(数据主题) DM(Data Mart)层即数据集市,将指标与维度建立物理模型组成数据集市,这是 OLAP 的数据基础。该层实现了合并不同系统的数据源来满足面向主题的业务需求,它的建模是终端用户驱动的,也是由业务需求驱动的。按主题,维度及 KPI 指标对 DM 层进行模型设计、建模,DM 层数据是将 DWD 层数据进行进一步整合、转换、汇总、计算等 ETL 操作处理获取的。

3 工业级数仓平台承载千万级别流量架构

3.1 设计准则

  • 摒弃Mysql数据库集群(线上8主8从,32核+128G+SSD固态硬盘)承载高并发数据接入。
  • 计算与存储分离,层次要清晰。
  • kv存储对高并发的支撑能力至少是MySQL的数倍甚至数十倍,比如Redis每秒承载几万并发,Hbase高性能的读取和写入性能。
  • Spark SQL计算引擎的深入使用。
  • MQ削峰填谷以及流量控制,减轻kv存储存储压力。
  • Spark 的广播变量的使用以及cache静态数据缓存。
  • MQ消费者流量控制系统重点实现数据校验、过滤无效数据、切分数据分片、数据同步的幂等机制、100%保证数据落地到kv集群的机制保障

3.2 高并发数据接入架构设计

3.3 高可用工业数据接入架构设计

  • 异步转同步 ->限流算法 ->选择性丢弃流量
  • 开启限流开关 –> 临时扩容Spark Slave集群 -> hash算法分发数据->小时级粒度(磁盘+内存双存储)
  • 计算任务重分配 + 主备切换机制+YARN资源Fair队列调度(或K8s集群资源调度)
  • 缓存集群AutoLoadCache 解决方案+ JVM本地缓存 + 限流机制
  • 冷数据高频查询缓存(T+1模式下离线日志高频用户分析 )
  • MQ要求消费者配置副本机制和Ack应答机制。
  • MQ要求在高并发情况下,需要考虑千兆带宽和万兆带宽对集群规模的规划。
  • MQ要求在执行限流操作时,还需要考虑数据持久性对集群规模的规划。

4: 工业级数据质量管理

数据异常如果由客户方发现的而不是你,那么它带来的负面影响会超过你之前做的所有业务带来的正面影响。

  • 规则引擎(通用模板建立)
  1. 数据落地监控
  2. 数据掉0监控:实际扩展一下就是数据量阈值监控,少于某个量就告警
  3. 重复数据监控:很多表一定要监控重复数据的,这点至关重要。
  4. 关键指标监控
  5. 数据同比环比监控
  • 数据对账 Kafka数据落地,必须要有一个监控机制来知道我们的数据落地情况,离线数据同样需要数据对账,对账方法有很多,比如可以和业务库来对比。

  • 性能监控

  1. 查询性能,比如es的某个索引,在不同时间段的查询响应速度,同理presto、hive、kylin这些的查询都需要注意一下,这点可以通过任务监控来观察。
  2. 数据读写影响,机器故障影响,在写入数据的时候其实会影响读数据的,需要监控一下,并做相应调整。
  • 数据质量4要素 数据质量的评估,可以从完整性、准确性、一致性和及时性来考虑。

5: Kylin+BI平台的高可用系统架构设计

  • Kylin 可扩展: 指可以对其主要依赖的三个模块做任意的扩展和替换,Kylin 的三大依赖模块分别是数据源(Hive)、构建引擎(MR)和存储引擎(HBase)

  • Layered Cubing构建算法: 四维 Cube 需要五轮的 MapReduce 来完成:第一轮 MR 的输入是源数据,这一步会对维度列的值进行编码,并计算 ABCD 组合的结果。接下来的 MR 以上一轮的输出结果为输入,向上聚合计算三个维度的组合:ABC、BCD、ABD和ACD;依此类推,直到算出所有的维度组合。问题是不能充分利用系统的资源以及缓存中间计算结果,存在shuffle过程,重点是稳定

  • Fast Cubing 构建算法:最大化利用 Mapper 端的 CPU 和内存,对分配的数据块,将需要的组合全都做计算后再输出给 Reducer;由 Reducer 再做一次合并(Merge),从而计算出完整数据的所有组合。配置方式kylin_job_conf_inmem.xml,包含了 MR 任务的配置项,当 Cube 构建算法是 Fast Cubing 时,会根据该文件的设置调整构建任务中的 MR 参数

  • 调优必填项:

         #KYLIN配置
         kylin.query.force-limit 默认是没有限制,推荐设置为 1000;
         kylin.storage.hbase.hfile-size-gb 可以设置为 1,有助于加快 MR 速度;
         kylin.storage.hbase.min-region-count 可以设置为 HBase 节点数,强制数据分散在 N 个节点;
         kylin.storage.hbase.compression-codec 默认没有进行压缩,推荐在环境运行情况下配置压缩算法。
    
         #Hadoop配置
         yarn.nodemanager.resource.memory-mb 配置项的值不小于 8192MB
         yarn.scheduler.maximum-allocation-mb 配置项的值不小于 4096MB
         mapreduce.reduce.memory.mb 配置项的值不小于 700MB
         mapreduce.reduce.java.opts 配置项的值不小于 512MB
         yarn.nodemanager.resource.cpu-vcores 配置项的值不小于 8
         
         //运行在yarn-cluster模式,当然可以配置为独立 Spark 集群:spark://ip:7077
         kylin.engine.spark-conf.spark.master=yarn
         kylin.engine.spark-conf.spark.submit.deployMode=cluster 
         
         //启动动态资源分配
         kylin.engine.spark-conf.spark.dynamicAllocation.enabled=true
         kylin.engine.spark-conf.spark.dynamicAllocation.minExecutors=2
         kylin.engine.spark-conf.spark.dynamicAllocation.maxExecutors=1000
         kylin.engine.spark-conf.spark.dynamicAllocation.executorIdleTimeout=300
         kylin.engine.spark-conf.spark.shuffle.service.enabled=true
         kylin.engine.spark-conf.spark.shuffle.service.port=7337
         
         //内存设置
         kylin.engine.spark-conf.spark.driver.memory=2G
         
         //数据规模较大或者字典较大时,调大 executor 内存
         kylin.engine.spark-conf.spark.executor.memory=8G 
         kylin.engine.spark-conf.spark.executor.cores=4
         //心跳超时
         kylin.engine.spark-conf.spark.network.timeout=600
         //分区大小
         kylin.engine.spark.rdd-partition-cut-mb=100
    
  • Count_Distinct 度量:

      近似实现:基于 HyperLogLog 算法,可接受的错误率(从9.75% 到 1.22%),低错误率需要更多存储;
      精确实现:基于 Bitmap(位图)算法,对于数据型为 tinyint、smallint 和 int 的数据,
                将把数据对应的值直接打入位图;对于数据型为 long,string 和其他的数
                据,将它们编码成字符串放入字典,然后再将对应的值打入位图。
                返回的度量结果是已经序列化的位图数据,而不仅是计算的值。
    
  • EXTEND_COLUMN 优化设置,解决存在对某个 id 进行过滤,但查询结果要展示为 name 的情况。

  • 聚合组(Aggregation Group)

  • 必要维度(Mandatory Dimension)

  • 层级维度 (Hierachy Dimension)

  • 联合维度(Joint Dimension)

  • Rowkeys编码,推荐的顺序为:Mandatory 维度、where 过滤条件中出现频率较多的维度、高基数维度、低基数维度。这样做的好处是,充分利用过滤条件来缩小在 HBase 中扫描的范围,从而提高查询的效率

      dict:适用于大部分字段,默认推荐使用,但在超高基情况下,可能引起内存不足的问题;
      boolean:适用于字段值为true, false, TRUE, FALSE, True, False, t, f, T, F, yes, no, YES, NO, Yes, No, y, n, Y, N, 1, 0;integer:适用于字段值为整数字符。
      date:适用于字段值为日期字符,支持的格式包括yyyyMMdd、yyyy-MM-dd、yyyy-MM-dd HH:mm:ss、yyyy-MM-dd HH:mm:ss.SSS,其中如果包含时间戳部分会被截断;
      fix_length:适用于超高基场景,将选取字段的前 N 个字节作为编码值,当 N 小于字段长度,会造成字段截断
    
  • ShardBy 设置:建议选择基数较大的列作为 ShardBy 列,以使得数据可以均匀分布;

5.1 单节点部署模式

5.2 集群部署模式

Kylin 实例是无状态的服务,运行时的状态信息存储在 HBase metastore 中。 出于负载均衡的考虑,您可以启用多个共享一个 metastore 的 Kylin 实例,使得各个节点分担查询压力且互为备份,从而提高服务的可用性。

Kylin 集群模式部署 如果您需要将多个 Kylin 节点组成集群,请确保他们使用同一个 Hadoop 集群、HBase 集群。然后在每个节点的配置文件 $KYLIN_HOME/conf/kylin.properties 中执行下述操作:

  • 配置相同的 kylin.metadata.url 值,即配置所有的 Kylin 节点使用同一个 HBase metastore。
  • 配置 Kylin 节点列表 kylin.server.cluster-servers,包括所有节点(包括当前节点),当事件变化时,接收变化的节点需要通知其他所有节点(包括当前节点)。
  • 配置 Kylin 节点的运行模式 kylin.server.mode,参数值可选 all, job, query 中的一个,默认值为 all。 job 模式代表该服务仅用于任务调度,不用于查询;query 模式代表该服务仅用于查询,不用于构建任务的调度;all 模式代表该服务同时用于任务调度和 SQL 查询。
  • 注意:默认情况下只有一个实例用于构建任务的调度 (即 kylin.server.mode 设置为 all 或者 job 模式)。

  • 任务引擎高可用 从 v2.0 开始, Kylin 支持多个任务引擎一起运行,相比于默认单任务引擎的配置,多引擎可以保证任务构建的高可用。

  • 使用多任务引擎,你可以在多个 Kylin 节点上配置它的角色为 job 或 all。为了避免它们之间产生竞争,需要启用分布式任务锁,请在 kylin.properties 里配置:

      kylin.job.scheduler.default=2
      kylin.job.lock=org.apache.kylin.storage.hbase.util.ZookeeperJobLock
    

5.3 读写分离部署模式

  • 通过架构图可以看到Kylin会访问两个集群的HDFS,建议两个集群的NameService务必不能相同,尤其是集群启用NameNode HA时,相同的NameService会导致组件在跨集群访问HDFS时因无法区分NameService而出现问题。
  • 搭建两个Hadoop环境当做Hadoop集群,一个集群部署HDFS、Hive、MR、YARN作为计算集群,负责Cube构建。一个集群部署HDFS、YARN、HBase负责Cube存储。

53.4 备份Kylin的元数据

  • 从Kylin的配置文件kylin.properties中查看到:

          ## The metadata store in hbase
          kylin.metadata.url=kylin_metadata@hbase
          表示Kylin的元数据被保存在HBase的kylin_metadata表中
    
  • 备份Kylin的元数据

          /bin/metastore.sh backup
          这将备份元数据到本地目录KYLIN_HOME/metadata_backps下面,目录的命名格式为:
          KYLIN_HOME/meta_backups/meta_year_month_day_hour_minute_second
          比如我的Kylin的家目录为/var/lib/kylin/kylin,那么备份数据的目录为:
          /var/lib/kylin/kylin/meta_backups/meta_2018_01_04_11_50_32
    
  • 恢复元数据

    首先reset当前Kylin的元数据存储,这将清理掉所有存储在HBase中的Kylin元数据,确保在此之前做过备份。

      ./bin/metastore.sh reset
    

    上传备份的元数据到Kylin的元数据中

      ./bin/metastore.sh restore$KYLIN_HOME/meta_backups/meta_xxxx_xx_xx_xx_xx_xx 
    
  • 从Kylin元数据中清理掉无用的资源

      (1)首先,执行检查,这是安全的操作,不会修改任何内容:
      ./bin/metastore.sh clean
      将需要被删除的资源(resources)罗列出来
      
      (2)添加“--delete true”参数,这样就会清理掉哪些无用的资源。
          切记,在这个命令操作之前,一定要备份Kylin元数据: 
      ./bin/metastore.sh clean --delete true
    

5.5: 工业数据计算平台与业务系统解耦设计

  • 消息中间件削峰填谷

  • 手动流量开关配合数据库运维操作

  • 多系统同时订阅数据(广播模式fanout)

  • 实时数据计算限流控制,把消息系统作为数据存储中间引擎,通过设置不同的消费速度进行数据的流入管控。

6:工业数据查询平台的架构优化(数据库集群方案优化)

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。QQ邮箱地址:1120746959@qq.com,如有任何技术交流,可随时联系。

6.1 纯MySQL分库分表及冷热数据存储弊端

  • 如果完全用MySQL数据库集群方案来承载是很不靠谱的,数据量是不断增加,而且增速很快,每天都新增几千万,再强悍的分库分表方案都是不合适的。
  • 为对冷数据的查询,一般都是针对大量数据的查询,比如用户会选择过去几个月,甚至一年的数据进行分析查询,此时如果纯用MySQL必定是灾难性的。

6.2 查询平台数据存储优化(冷热数据分层)

6.2.1 冷数据的查询基本都是200毫秒以内的响应速度
  • 冷数据全部采用ES+HBase来进行存储,ES中主要存放要对冷数据进行筛选的各种条件索引,比如日期以及各种维度的数据,然后HBase中会存放全量的数据字段。
6.2.2 热数据实现负载高并发的每秒十万级别的查询,
  • 热数据缓存(Redis及Codis)集群(优先查询缓存)。
  • 热数据数据库集群(其次查询),主库与从库同步,分库分表方案,实现基于Mysql热数据查询。

  • 90%以上的高并发查询都走缓存集群,剩下10%的查询落地到数据库集群

7 工业领域数据分析业务模型

  • 车辆热区分布
  • 车辆行驶区域模型
  • 充电区域模型
  • 车辆补贴预测计算
  • 每一辆车辆闲置率计算排序
  • 单台车按月进行运行强度计算,进行多月份对比展示
  • 所有车辆进行运行强度排序,辅助调度。
  • 每一辆上个月每天平均行驶里程
  • 每一辆车上个月总运行天数
  • 维保预测
  • 每一台车每个月总耗电量成本(充电),结合运营商力度,评估电池性能
  • 每一台车平均每天的耗电量
  • 每一台车综合质量系数 = 1/月综合故障次数
  • 每一台车百公里耗电量
  • 每一台车综合成本系数 =上个月百公里回馈电量/上个月最高百公里回馈电量
  • 汽车载重分布、满载率分布
  • 车速分布统计和经济性驾驶分析

8 总结

工业级大数据平台的系统要求非常高,对于高并发的场景犹如家常便饭,这也是我为什么花费大量笔墨来解析我主导的工业大数据仓库的主要原因,到目前为止,这个架构是我最成功的平台案例。包含了几乎主流的大数据组件。当然还有Kylin,今天收到Kylin团队的邀请,希望未来能够为国产的优秀开源项目做一点贡献。

版权声明:本套技术专栏是作者(秦凯新)平时工作的总结和升华,通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。QQ邮箱地址:1120746959@qq.com,如有任何技术交流,可随时联系。

秦凯新 于深圳