原创 PowerData谢帮桂 PowerData
本文由PowerData谢帮桂贡献 姓名:谢帮桂 花名:谢帮桂 微信:xc606060\_ 年龄:90后 工作经验:5-10年 工作内容:数仓,数分 自我介绍:一美联物业数仓负责人,主要负责数仓规划和数据开发,下方是作者帅照喔。
全文共 2969 个字,建议阅读 13 分钟
一、背景
企业背景
美联物业属于香港美联集团成员,于1973年成立,并于1995年在香港联合交易所挂牌上市(香港联交所编号:1200),2008年美联工商铺于主板上市(香港联交所编号:459), 成为拥有两家上市公司的地产代理企业。拥有40余载房地产销售行业经验,业务涵盖中、小型住宅、豪宅及工商铺,提供移民顾问、金融、测量、按揭转介等服务,业务遍布中国香港地区、中国澳门地区、中国内地。
其次,美联物业是一家传统型的老牌企业,深耕香港和深圳多年,在以前大多数的数据分析工作都基于文本文件和依赖人力手工进行统计,为实现数据驱动业务,方便进行有效的目标管理,搭建数仓体系。
面临的问题
- 没有统一数据管理体系和数据治理,数据质量较差,如多部门、多系统、多字段,命名随意、表违反范式结构混乱。
- 没有统一的分析处理平台,关系数据库分表分库无法做到上亿数据秒级分析查询。
- 没有充分利用数据驱动业务,数据需求流程冗长+烟囱式开发。
- 没有数据资产管理体系,无法实现数据的降本复用。
- 部门之间严重依赖文本文档处理工作,效率低下。
主要需求
- 业务部门的数据报表需求
- app的数据接口需求
- 快速的自助分析场景等
首期目标
- 建立初段数据管理体系,搭建美联数据仓库。
- 搭建业务报表平台和报表需求+开发流程体系。
- 实现报表和分析需求能够快速反应和交付
二、总体架构
运行架构
和大部分公司的数仓有不同的是,我们摒弃了之前使用的Hadoop、Hive、Spark体系建立的数仓,完全改用Apache Doris作为数仓主体进行开发,摒弃Hadoop全家桶主要有是几个原因:
①过于笨重:对于传统公司的计算量和数据量,Hadoop显得杀鸡用牛刀。
②效率低下:T-1的调度时效和脚本动辄花费1小时的计算时间很影响数据开发工作。
③维护成本高:组件过多,排查故障链路过长,且部门同事之间熟悉各个组件需要大量沟通成本。
改用Apache Doris主要有几个方面原因:
足够简单
传统公司数据部门不像互联网公司一样,数据部门几十个人,传统公司大部分对数据人员的要求除了数据开发之外,也要兼顾一些运维和架构规划的工作,因此我们选择数仓组件的第一原则就是"简单",比如统一开发语言SQL,部门之间以SQL为主的开发语言,统一语言利于开发效率和共识统一,Apache Doris基本脚本就是SQL开发。另外Apache Doris的组件架构FE+BE理解起来也非常简单,运维工作相对轻松,排查故障的链路也非常清晰。
快速响应
无需面对C端群体,不需要要求系统有很高的并发特性和PB级存储,销售行业讲究的是业务需求要快速响应,因此很多时候需要数据实时交付和分钟级交付。Doris也满足这点。
健壮活跃
选择开源组件也是因为公司没有自研方面的预算,但要求选择的开源产品一定是要有健壮性,不能产生严重的生产故障。Doris在百度内部已经深耕多年,这一点也是有保障,另外Doris社区和SelectDB社区的大佬们也非常热情和活跃,遇到问题大家会积极响应。
业务模型
- 业务模型是最常见的分钟级调度ETL。
- 离线数据利用DataX进行增量和全量调度,部分指标需要实时统计,因此也借助了Flink CDC 对源表进行实时同步,利用Doris的物化视图或者Aggregate模型表进行实时汇总处理。
- 脚本语言采用bash+SQL,或者是纯SQL,在Apache Dolphinscheduler上进行管理和发布。
- 所有层级表模型大部分采用Unique key模型,可以有效保证数据脚本的结果幂等性,Unique key模型完美解决下游数据重复的问题,但是要注意主键不可以重复。
- BI系统选择的帆软
一些截图:
Apache Dolphinscheduler的Doris脚本可以进行版本控制,有效控制生产环境发生错误,及时回滚。
发布ETL脚本后导入数据,直接帆软系统进行页面制作,可以基于登陆账号控制页面权限,也可以利用SQL控制到表级别、甚至行级别权限。
一键发布及热部署数据报表
整个业务链路在美联物业提出数据需求,最快可以在当天进行数据交付,直接在帆软BI进行自助取数和分析,另外整个数仓的权限控制、容灾恢复、集群监控、数据安全内容较多,此处不过多展开。
数据模型
纵向分域
房地产中介行业的大数据主题大致如上,围绕这些主题进行数仓建模。建模主题域核心围绕"企业用户""客户""房源""组织"几个业务实体展开的以部门功能为依据的主题域数据模型,核心也是围绕这些个业务实体进行维度表和事实表创建等。
横向分层
主要是利用Apache Doris + Apache Dolphinscheduler进行调度脚本处理。
早上8点到晚上12点基本采用增量策略,凌晨执行全量策略,目的是为了补数和修正历史状态变化数据。
层级
备注
存储策略
ODS
利用Datax Doris write进行数据的本地导入要注意参数设置exec\_mem\_limit参数大小,部分全量数据较大超过限制会导致stream load 失败
8-0点增量策略凌晨全量策略一次
DWD
部分事实表涉及缓慢变化维,需要进行拉链存储。
8-0点增量策略凌晨全量策略一次部分表拉链存储
DWS 与ADS
注意数据校验问题,加入审计时间,如etl\_time,last\_etl\_time,create\_time等字段,方便后续故障排查
8-0点增量策略凌晨全量策略一次
DIM
维度表存放层,基于业务实体,如客户,房源,职员,职级,岗位等
每小时整点全量
增量策略
- where >=业务时间 -1 天
为什么不是where = 业务时间来增量当天数据,是为了避免数据漂移的情况。
- 每次跑增量脚本前获取表中最大的主键ID存入辅助表,where >= 辅助表记录ID
这种自增策略用在什么场景?比如Doris表如果是Unique key模型,恰好是组合主键,主键组合在源表发生了变化,这时候where >= 业务时间-1天会将这种同一记录,但是主键发生了变化的数据给load进来,造成数据重复。
但是这种自增策略存在局限性就是,要建立在源表自带业务自增主键的情况
- 表分区
如日志表等是基于时间自增数据,且历史数据和状态基本不会变更,数据量非常大,这种存储需要对Doris表进行建表分区,每次增量进行分区替换操作即可。
全量策略
- Truncate Table 清空表插入
后再把源表表进行导入。如果是面向C端用户的公司和白天调度时间千万别这么做,会有一段时间没有数据,适合数据量较小的表格和凌晨没有用户使用系统的公司。
- ALTER TABLE tbl1 REPLACE WITH TABLE tbl2 表替换
这种方式是一种原子操作。可以每次执行脚本前先create 一张相同的临时表,把全量数据load进去临时表,再执行表替换操作,可以无缝衔接。适合数据量大的全量表。
三、实践经验
- 内存一直不释放
Doris的BE节点在旧版本是开启PageCache 和 ChunkAllocator 的。目的是为了减少查询的延迟,这两个功能会占用一定比例的内存,并且一直不会释放,时间就后就会导致be计算资源越来越紧张。新版本直接禁用了这两个配置,在查询延迟上进行了一些取舍。美联物业这边是开启了这2项配置,并且每天凌晨进行be滚动重启的。既能保证be内存不会一直不释放,也能方便查询延迟更低。
- 数据导入和 Catalog Doris
Catalog方式可以利用Mysql JDBC类型的连接方式,来对Doris生产集群数据进行读取,这样方便生产数据直接load进测试服务器。
但这种方式对FE节点的压力会很大,在导入过程中可明显观察FE节点CPU资源被拉满,不知道是版本原因还未优化,还是其他原因,总之如果Fe资源并不充足的情况下,还是选用Stream load的方式进行数据导入,如Datax。
在数据导入方式上,大部分返回结果不是同步的,是异步操作,但是在Dolphinscheduler上会误以为该脚本已经执行成功,但在Doris里该导入任务状态有可能是失败的,因此在bash等脚本里执行Doris的导入操作,记得去判断上游任务状态是否成功,可以在脚本里执行show load再利用正则去过滤状态进行判断。
- 数据备份
目前Doris的备份依赖Broker load,只能基于BOS、HDFS 等文件系统,对于没有安装HDFS这类的服务器基本用不了。
这一部分只能依赖其他第三方运维组件进行数据表的备份操作了,希望后期可以直接基于服务器本地进行备份操作。
- 前缀索引
尽量把非字符类型的,如int类型的、where条件中最常用的字段放前排36个字节内,在点查表过程中过滤这些字段,基本是毫秒级别,充分利用这个特性进行数据表输出。
- 数据字典
利用Doris自带的information\_schema元数据可以制作简单的数据字典,这一点对公司还未建立数据治理体系前是非常重要的一步,方便低成本管理数仓人员的操作规范。
想要加入社区或对本文有任何疑问,可直接添加作者微信交流。
图:作者微信
我们是由一群数据从业人员,因为热爱凝聚在一起,以开源精神为基础,组成的PowerData数据之力社区。
可关注下方公众号后点击“加入我们”,与PowerData一起成长
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。