FLinkCDC读取MySQl中的日期问题

问题描述:

在通过FlinkCDC读取MySQL的BinLog日志的时候,发现读取到日期类型的数据和数据库中存储的相差八小时。flink版本:1.15.1,MySQLCDC版本:2.3.0如下图

解决办法:

自定义时间转换配置。代码如下


package com.yzh;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Properties;

import io.debezium.spi.converter.CustomConverter;
import io.debezium.spi.converter.RelationalColumn;
import org.apache.kafka.connect.data.SchemaBuilder;

/**
 *  @Description:实现CustomConverter接口,重写对应方法对mysql的时间类型进行标准转换
 * @author yzh
 *
 */
public class MySqlDateTimeConverter implements CustomConverter<SchemaBuilder, RelationalColumn> {
	private DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_DATE;
	private DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_TIME;
	private DateTimeFormatter datetimeFormatter = DateTimeFormatter.ISO_DATE_TIME;
	private DateTimeFormatter timestampFormatter = DateTimeFormatter.ISO_DATE_TIME;
	private ZoneId timestampZoneId = ZoneId.systemDefault();

	@Override
	public void configure(Properties properties) {}

	@Override
	public void converterFor(RelationalColumn column, ConverterRegistration<SchemaBuilder> registration) {
		String sqlType = column.typeName().toUpperCase();
		SchemaBuilder schemaBuilder = null;
		Converter converter = null;

		if ("DATE".equals(sqlType)) {
			schemaBuilder = SchemaBuilder.string().optional().name("com.darcytech.debezium.date.string");
			converter = this::convertDate;
		}

		if ("TIME".equals(sqlType)) {
			schemaBuilder = SchemaBuilder.string().optional().name("com.darcytech.debezium.time.string");
			converter = this::convertTime;
		}

		if ("DATETIME".equals(sqlType)) {
			schemaBuilder = SchemaBuilder.string().optional().name("com.darcytech.debezium.datetime.string");
			converter = this::convertDateTime;
		}

		if ("TIMESTAMP".equals(sqlType)) {
			schemaBuilder = SchemaBuilder.string().optional().name("com.darcytech.debezium.timestamp.string");
			converter = this::convertTimestamp;
		}

		if (schemaBuilder != null) {
			registration.register(schemaBuilder, converter);
		}
	}

	private String convertDate(Object input) {
		if (input == null)
			return null;

		if (input instanceof LocalDate) {
			return dateFormatter.format((LocalDate) input);
		}

		if (input instanceof Integer) {
			LocalDate date = LocalDate.ofEpochDay((Integer) input);
			return dateFormatter.format(date);
		}
		return String.valueOf(input);
	}

	private String convertTime(Object input) {
		if (input == null)
			return null;

		if (input instanceof Duration) {
			Duration duration = (Duration) input;
			long seconds = duration.getSeconds();
			int nano = duration.getNano();
			LocalTime time = LocalTime.ofSecondOfDay(seconds).withNano(nano);
			return timeFormatter.format(time);
		}
		return String.valueOf(input);
	}

	private String convertDateTime(Object input) {
		if (input == null)
			return null;

		if (input instanceof LocalDateTime) {
			return datetimeFormatter.format((LocalDateTime) input).replaceAll("T", " ");
		}
		return String.valueOf(input);
	}

	private String convertTimestamp(Object input) {
		if (input == null)
			return null;
		if (input instanceof ZonedDateTime) {
			// mysql的timestamp会转成UTC存储,这里的zonedDatetime都是UTC时间
			ZonedDateTime zonedDateTime = (ZonedDateTime) input;
			LocalDateTime localDateTime = zonedDateTime.withZoneSameInstant(timestampZoneId).toLocalDateTime();
			return timestampFormatter.format(localDateTime).replaceAll("T", " ");
		}
		return String.valueOf(input);
	}
}

--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

		// 关键代码
		Properties debeziumProperties = new Properties();
        debeziumProperties.setProperty("converters", "dateConverters");
        debeziumProperties.setProperty("dateConverters.type", "com.yzh.MySqlDateTimeConverter"); // "com.yzh.MySqlDateTimeConverter" 更换成自己的路径


        MySqlSource<String> sourceFunction = MySqlSource.<String>builder()
                .hostname("localhost")
                .port(3306)
                .username("root")
                .password("root")
                .databaseList("1226")
                .tableList("1226.users")
                .deserializer(new JsonDebeziumDeserializationSchema())
                .startupOptions(StartupOptions.initial())
                .serverTimeZone("Asia/Shanghai")
                .debeziumProperties(debeziumProperties)	// 自定义debeziumProperties
                .build();

结果:

完美解决!!!!!

参考:

实测解决 flink cdc mysql 时间字段差8小时/差13小时问题_普罗米修斯之火的博客-CSDN博客

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Flink CDC是一个可以直接从MySQL数据库读取全量数据和增量变更数据的组件。它是由Flink社区开发的flink-cdc-connectors组件,可用于实时捕获数据库的变动并将其写入消息间件以供其他服务进行订阅和消费。使用Flink CDC读取MySQL数据的过程如下: 1. 首先,确保你已经正确安装和配置了Flinkflink-cdc-connectors组件。 2. 在Flink的作业,使用CDC Connector来定义一个source,用于读取MySQL的数据。通过配置连接参数、数据库表信息和读取起始位置等,你可以指定要读取的数据源和读取的方式。 3. 在作业使用Flink的数据转换和处理算子对读取到的MySQL数据进行处理和转换。你可以根据具体需求进行数据清洗、过滤、聚合等操作。 4. 最后,将处理后的数据发送到目标位置,可以是其他存储系统、消息队列或其他下游服务。 需要注意的是,为了使用Flink CDC读取MySQL数据,你需要确保正确配置了MySQL数据库的连接信息和权限,并在Flink作业正确配置了CDC Connector的参数。此外,你还需要确保Flink作业和MySQL数据库之间的网络连接正常。 引用<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Flink CDC实时获取MySQL数据](https://blog.csdn.net/weixin_41507897/article/details/120123176)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [基于FlinkSQLCDC的实时数据同步方案](https://download.csdn.net/download/weixin_38691199/15541340)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值