cjuexuan / mynote

237 stars 34 forks source link

spark3升级过程中遇到的一些问题 #73

Open cjuexuan opened 4 years ago

cjuexuan commented 4 years ago

spark3升级过程

最近在持续推进着spark3的升级,这里说一下到目前为止发现的问题,以及我这里总结的一些升级建议。

本文分成两个部分,一部分是展示下我们的升级利器-流量校验平台,另一块是我们在从spark2.4到spark3升级过程中发现的一些问题

流量校验平台

trafficValidate.png 我们从2018年开始就搭建了一套用于升级校验的流量校验平台,帮助我们团队应对了多次的版本升级和内部引擎重构

这是流量校验平台的大致架构 我们会在线上部署两个环境,一个是生产环境,跑着现在的稳定版本,另一个是我们经过单测和集成测试后,待发布的新版本引擎,都部署在线上可以让我们不用担心beta版本无法访问线上数据

流量校验程序将不断抽取线上成功运行的流量,然后通过sql改写,改成将数据落到线上的影子库,将改写的sql的发送给beta环境,等待任务执行,将结果记录到db中 然后在现有的可视化平台上配置出任务执行的报表,管理员每天花一些时间解决下发现问题,持续推动升级工作的进行

engine.png

unicorn.png

升级过程中遇到的一些问题

升级过程中遇到的问题很多在官方升级指南中都有说明,这里再稍微提一下,其他小伙伴升级过程中还是要仔细阅读官方的升级指南

  1. 类型隐式转换
case when length(update_timestamp) = 0  or update_timestamp is  null or  update_timestamp = '' then '2000-01-01 00:00:00' else update_timestamp end as update_timestamp 

这里举一个例子,例子里当update_timestamp是空的时候,用户会给一个写死的值,否则取数据里的update_timestamp

这个sql在spark3默认会报错

Cannot safely cast 'update_timestamp': string to bigint

问题也比较好跟踪,源代码主要在org.apache.spark.sql.catalyst.expressions.Cast

我们需要将spark.sql.storeAssignmentPolicy暂时设置成LEGACY来暂时绕过问题

  1. show create table的结果不一致

spark3中hive serDe的表也会返回spark的ddl,导致结果不一致

这里放一下官方原文

In Spark 3.0, SHOW CREATE TABLE always returns Spark DDL, even when the given table is a Hive SerDe table. For generating Hive DDL, use SHOW CREATE TABLE AS SERDE command instead.

不过这个基本都是用户的临时查询,所以影响不大

  1. 一些时间格式parquet读取不兼容

由于使用java8的时间api导致一些老数据不能读取的问题,暂时将spark.sql.legacy.parquet/avro.datetimeRebaseModeInRead" 设置成LEGACY

caused by: You may get a different result due to the upgrading of Spark 3.0: reading dates before 1582-10-15 or timestamps before 1900-01-01T00:00:00Z from Parquet files can be ambiguous, as the files may be written by Spark 2.x or legacy versions of Hive, which uses a legacy hybrid calendar that is different from Spark 3.0+'s Proleptic Gregorian calendar. See more details in SPARK-31404. You can set spark.sql.legacy.parquet.datetimeRebaseModeInRead to 'LEGACY' to rebase the datetime values w.r.t. the calendar difference during reading. Or set spark.sql.legacy.parquet.datetimeRebaseModeInRead to 'CORRECTED' to read the datetime values as it is.
  1. 时间格式导致date_fromat语法不兼容
select DATE_FORMAT(create_time,'Y-M') as create_time,count(*) from t group by DATE_FORMAT(create_time,'Y-M')

和上述问题类似,也是先将行为兼容,保证上线后不报错,然后推动用户再改

caused by: You may get a different result due to the upgrading of Spark 3.0: Fail to recognize 'Y-M' pattern in the DateTimeFormatter. 
1) You can set spark.sql.legacy.timeParserPolicy to LEGACY to restore the behavior before Spark 3.0.
2) You can form a valid datetime pattern with the guide from https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html

其他问题建议大家仔细阅读升级指南