元月's blog 元月's blog
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多

元月

临渊羡鱼,不如退而结网
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多
  • Redis

  • Nginx

  • Kafka

  • Shardingsphere

  • Otter

    • otter快速开始
    • otter同步实战
    • otter二次开发-支持分库分表
    • otter二次开发-支持按目标端主键索引Load数据
    • nexus

    • 中间件
    • Otter
    元月
    2024-08-03
    目录

    otter二次开发-支持按目标端主键索引Load数据

    # 一、背景

    由于表主键按id自增,使用分库分表后,分库的表会出现主键相同的情况,在使用otter往下游数据同步,合并成一张表的过程中会导致数据异常,解决办法是将下游的表改成联合主键索引,按照下游表的主键索引进行更新数据。但是otter是按照源端的主键索引load数据的,因此对otter进行二次开发,使其支持目标端主键索引Load数据

    # 二、按目标端主键索引Load数据支持

    基于otter-4.2.18 (opens new window)改造

    完整代码提交记录:https://github.com/HeyouA/otter/commit/2e41b69f0601196f122c4aa3dd8609d4f6e9149c

    # 三、FAQ

    # 3.1、数据合并时(insert+delete)合并失败导致下游数据未删除问题

    业务背景:支持按目标端主键索引Load数据上线后,一个月后,用户反馈报表数据重复,分析后发现下游数据存在少量重复问题

    问题原因

    定位问题后发现,部分业务存在事务A先插入后立马在事务B删除这条数据的场景,示例代码如下

    @Service
    public class TestServiceImpl extends ServiceImpl<UserMapper, User> implements ITestService {
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void testOtter(User entity) {
            this.save(entity);
    
            this.delUser(entity.getId());
        }
    
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void delUser(Integer id) {
            this.removeById(id);
        }
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    otter在load数据时会按table+pk进行数据合并(insert + delete = delete),而我们的支持按目标端主键索引Load数据功能,只有主键变更或者删除才会重新定义pk,导致合并数据失败,有较低的概率出现删除失败的问题。代码片段如下:

       .
       .
       .   
    //重新定义pk字段和其它字段
    //只有主键变更或者删除才需要重新定义,使用目标表的主键索引
    List<EventColumn> columns = data.getColumns();
    List<EventColumn> keys = data.getKeys();
    List<EventColumn> oldKeys = data.getOldKeys();
    boolean existOldKeys = !CollectionUtils.isEmpty(data.getOldKeys());//主键变更
    boolean isDelete = data.getEventType().isDelete();//删除
    if (existOldKeys || isDelete) {
        List<EventColumn> allSourceColumns = new ArrayList<>();//源表所有字段
        allSourceColumns.addAll(keys);
        allSourceColumns.addAll(columns);
       .
       .
       .
       .
    }    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    解决方法

    放开insert限制即可

    #otter#数据库
    otter二次开发-支持分库分表
    mvnw简介

    ← otter二次开发-支持分库分表 mvnw简介→

    最近更新
    01
    mvnw简介
    06-21
    02
    gor流量复制工具
    06-03
    03
    BeyondCompare比较工具
    03-16
    更多文章>
    Theme by Vdoing | Copyright © 2022-2024 元月 | 粤ICP备2022071877号-1
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式