2.亿级积分数据分库分表:增量数据同步之代码双写,为什么没用Canal?

1.亿级积分数据分库分表:总体方案设计 上一篇博客中写了一下积分数据分库分表的总体方案设计,里面说了采用应用程序代码双写的方式实现的增量数据同步,本篇就对这一块进行一些细化的介绍,包括:

为什么不用Canal监听数据库binlog,有哪些优缺点吗?

为什么要用代码双写,有哪些优缺点吗?代码双写怎么实现的?

Canal监听binlog

实现流程

        Canal监听binlog的方案大致流程如下图所示:

  1. 对原有老的单表添加Canal监听,老表的增删改操作会产生binlog,通过Canal将binlog转发到kafka,消费kafka的消息将增量的数据通过分库分表中间件写的新的分表中
  2. 对老的单表的创建时间在Canal监听时间点之前的数据全量迁移到新的分表
  3. 数据核对校验新老表的数据;灰度切流验证,这一步没有画出来
  4. 在运行一段时间后,发现没有什么数据不一致了,并且增量数据同步追上了老表数据,就可以将程序的写切到新分表了

        上面说了要增量数据同步追上老表数据,但是因为应用程序一直在产生新的写操作导致一直有新的binlog产生,导致只能无限逼近老的数据而无法追平,所以在第4步切写分表之前要将老表先短暂停写一小段时间,等binlog消费完就可以切写了。

优缺点

优点:

  1. 功能逻辑实现简单

缺点:

  1. 数据增量同步有短暂的秒级延迟;
  2. 切写分表的时候要停写,对业务有影响
  3. 积分应用程序代码没有通过分库分表中间件做过写入操作,直接切写分表有很大的风险
  4. 引入了新的Canal中间件,提升了复杂性

        正是因为考虑到使用Canal做增量数据同步需要短暂停写,对业务有影响,还有就是切写分表的风险,所以我们这边才没有使用Canal,而是采用了代码双写。

代码双写

 实现流程    

上一篇博客中关于双写有如下的操作步骤

  1. 改造双写代码预发测试(多种case跑一下,双写开关等校验),没问题发布上线,上线时双写开关默认关闭,可以通过配置中心动态开启,打开双写开关(新表写入失败先忽略,因为更新和删除操作会因为新表数据不存在而失败),记录双写开始时间点A
  2. 将老表的积分明细的createTime小于等于双写开始时间点A+5分钟(防止时间不同步导致少迁移数据,预留一些缓冲时间)的数据进行全量迁移到分表
  3. 新老数据全量数据校验,查看数据是否一致;同时定时任务每隔一小段时间进行增量校验,增量数据因为读取新老数据存在短暂时间差可能会瞬时不一致,这种数据隔一段时间再次校验,多次校验还不一致的数据进行数据订正(老表数据覆盖到新表数据)
  4. 改造代码,添加双读的逻辑上线(读新表的开关默认关闭)
  5. 低流量节点(凌晨过后)进行白名单、灰度切流userId%10000,进行验证,逐步流量打开,持续观察
  6. 双写开关切到新表,保证只写新表(也可以继续写老表一段时间,或者创建一个新表往老表同步的canal任务,方便回滚),完成数据迁移方案
  7. 系统稳定运行一段时间,迁移&双写代码下线,老表进行资源释放

优缺点

优点:

  1. 增量数据同步延迟比较低
  2. 切换写新的积分多表时可以直接切换,无需停写
  3. 积分应用程序代码通过分库分表中间件做过各种增删改查操作,各种条件case都跑过,后面切写分表就没有风险了

缺点:

  1. 双写逻辑实现起来相对复杂一些

具体实现

双写改造点:增、删、改

双写开关有两个(通过配置中心实时切换):

  1. 写老表开关:默认开启,新表写入没有问题时可以进行关闭,也可以继续写一段时间老表
  2. 写新表开关:默认关闭,需要开启时打开

        新老表的开关同时打开时,表示要进行双写

通过配置中心动态进行切换,双写期间需要注意的问题如下:

  • 对写新表操作需要记录日志
  • 新表不要求一定写成功(不影响服务,记录错误日志告警通知等,有数据校验订正任务兜底)

         程序双写的逻辑,可以通过对mapper接口添加AOP切面,拦截到需要分表的mapper的写方法,判断需要双写的时候切换数据源双写到新的分表中,通过这种方式,可以对原有代码基本上实现零侵入。

        AOP切面代码大致如下所示:

@Aspect
@Component
@Slf4j
public class DoubleWriteMapperAop {Set<String> shardMapperSet = Sets.newHashSet(PointInfoMapper.class.getSimpleName());@Around("execution(* com.wkp.sharding.mapper.*.*(..))")public Object doAroundMapper(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();Method method = signature.getMethod();String clazzName = method.getDeclaringClass().getSimpleName();//不用分表的mapper不用特殊处理直接返回if (!shardMapperSet.contains(clazzName)) {return proceedingJoinPoint.proceed();}//双写前和双写时这里写的老表,最后切到写分表时这里写的分表Object result = proceedingJoinPoint.proceed();//获取当前mapper的方法上有没有加分片写的注解ShardWrite shardWrite = method.getAnnotation(ShardWrite.class);//是写方法 && threadlocal里面获取到了需要双写的标识if (shardWrite != null && DoubleWriteThreadLocal.needDoubleWrite()) {//切数据源,写分表,这里执行双写逻辑 proceedingJoinPoint.proceed();}return result;}
}

         DoubleWriteThreadLocal.needDoubleWrite(),DoubleWriteThreadLocal是个ThreadLocal,里面获取到是否需要双写的标识,这个ThreadLocal的值是前面通过配置中心判断是否双写开关开着,如果开着双写会将ThreadLocal的双写标识设置为true。

        AOP切面这里通过ThreadLocal判断,而没有通过读取配置中心,原因是可能前面配置中心打开了双写,但是执行到切面时恰好配置中心将开关从双写切到写分表了,那么这里就不会双写分表了,分表就会丢失一条数据。

        后面切写的时候直接通过配置中心切换开关,即可动态切换只写到分表中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/751666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【S5PV210】 | GPIO编程

【S5PV210】 | GPIO编程 时间:2024年3月17日22:02:32 目录 [TOC] 1.参考 1.s5pv210开发与学习:1.5之裸机汇编流水点灯_s5pv210汇编指令集-CSDN博客 2.s5pv210开发与学习:1.8之裸机蜂鸣器实验_pv210 蜂鸣器-CSDN博客 3.s5pv210开发与学习:1.9之裸机按键控制LED_s5pv210 按键…

机器学习——压缩网络作业

文章目录 任务描述介绍知识蒸馏网络设计 Baseline实践 任务描述 网络压缩&#xff1a;使用小模型模拟大模型的预测/准确性。在这个任务中&#xff0c;需要训练一个非常小的模型来完成HW3&#xff0c;即在food-11数据集上进行分类。 介绍 有许多种网络/模型压缩的类型&#xff0…

代码随想录day23(2)二叉树:从中序与后序遍历序列构造二叉树(leetcode106)

题目要求&#xff1a;根据一棵树的中序遍历与后序遍历构造二叉树。 思路&#xff1a;408的经典题目&#xff0c;思路和手撕的思路差不多&#xff0c;先从后序中找到根节点&#xff0c;再从中序中找到此节点&#xff0c;然后分割成左右子树&#xff0c;记录一下左右子树的节点个…

PyQt5使用

安装Pyqt5信号与槽使用可视化界面编辑UI (Pyside2)ui生成之后的使用(两种方法)1 ui转化为py文件 进行import2 动态调用UI文件 安装Pyqt5 pip install pyqt5-tools这时候我们使用纯代码实现一个简单的界面 from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButto…

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛——B 题:基于多模态特征融合的图像文本检索完整思路与源代码分享

一、问题背景 随着近年来智能终端设备和多媒体社交网络平台的飞速发展&#xff0c;多媒体数据呈现海量增长 的趋势&#xff0c;使当今主流的社交网络平台充斥着海量的文本、图像等多模态媒体数据&#xff0c;也使得人 们对不同模态数据之间互相检索的需求不断增加。有效的信…

Rocket MQ 从入门到实践

为什么要使用消息队列&#xff0c;解决什么问题&#xff1f;&#xff08;消峰、解藕、异步&#xff09; 消峰填谷 客户端》 网关 〉 消息队列》秒杀服务 异步解耦 消息队列中的重要概念理解。&#xff08;主题、消费组、队列&#xff0c;游标&#xff1f;&#xff09; 主题&…

新手向-从VNCTF2024的一道题学习QEMU Escape

[F] 说在前面 本文的草稿是边打边学边写出来的&#xff0c;文章思路会与一个“刚打完用户态 pwn 题就去打 QEMU Escape ”的人的思路相似&#xff0c;在分析结束以后我又在部分比较模糊的地方加入了一些补充&#xff0c;因此阅读起来可能会相对轻松&#xff08;当然也不排除这是…

Transformer总结

1.Transform背景介绍 1.1Transform的优势 相比于之前占领市场的LSTM和GRU模型&#xff0c;Transformer有两个显著的优势&#xff1a; &#xff08;1&#xff09;Transform能够使用分布式GPU进行并行训练&#xff0c;提升模型训练效率 &#xff08;2&#xff09; 在分析预测…

zookeeper基础学习之六: zookeeper java客户端curator

简介 Curator是Netflix公司开源的一套zookeeper客户端框架&#xff0c;解决了很多Zookeeper客户端非常底层的细节开发工作&#xff0c;包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt&#xff08;Zookeeper&#xff09;以一句“Guava is to Java…

【算法刷题 | 数组】3.12(二分查找、移除元素、有序数组的平方、长度最小的子数组、螺旋矩阵2)

文章目录 1.二分查找1.1题目1.2思路&#xff08;核心&#xff1a;区间的定义&#xff09;1.3左闭右闭1.4左闭右开1.5总结 2.移除元素2.1题目2.1思路2.2.1暴力解法2.2.2双指针法 23总结 3.有序数组的平方3.1题目3.2思路3.2.1暴力解法3.2.2双指针法 4.长度最小的子数组4.1题目4.2…

Linux中文件和目录管理(创建删除移动复制)

目录 1——一次建立一个或多个目录&#xff1a;mkdir ​2——创建一个空文件&#xff1a;touch 3——移动和重命名&#xff1a;mv 4——复制文件和目录&#xff1a;cp 5—— 删除目录和文件&#xff1a;rmdir和rm 在学习文件与目录的管理的一些命令之前&#xff0c;我们先…

深度学习-面经(part2、CNN)

2 CNN 对图像&#xff08;不同的数据窗口数据&#xff09;和滤波矩阵做内积&#xff08;逐个元素相乘再求和&#xff09;的操作就是所谓的『卷积』操作。 卷积神经网络由输入层、卷积层、激励层、池化层、全连接层组成。 ① 最左边: 数据输入层&#xff0c;对数据做一些处理…

数字后端 EDA 软件分享

数字后端 EDA 软件分享 推荐这几家的EDA工具吧&#xff0c;虽说我也支持国产工具&#xff0c;但是我还是选择了这几家的工具 apache cadence mentor synopsys 下图我现在用的eda环境&#xff0c;利用网上的资源&#xff0c;自己独立在vmware上搭建好的EDA环境 除去pdk&#…

从政府工作报告探究计算机行业发展

从政府工作报告探计算机行业发展 政府工作报告作为政府工作的全面总结和未来规划&#xff0c;不仅反映了国家整体的发展态势&#xff0c;也为各行各业提供了发展的指引和参考。随着信息技术的快速发展&#xff0c;计算机行业已经成为推动经济社会发展的重要引擎之一。因此&…

计算机考研|怎么备考「科软」?

学好408和考研数学就可以了 大家对于科软已经回到了理性的区间&#xff0c;很难再出现刚开始的300分上科软的现象&#xff0c;也不会再出现388分炸穿地心的现象。 如果大家想报考科软&#xff0c;我觉得一定要认真对待复习&#xff0c;不要抱有抄底的心态去复习。 众所周知&am…

7.JavaWebHTML:构建数字世界的语言和结构

目录 导语&#xff1a; 第一部分&#xff1a;Web概念与作用 1.1 Web的定义 1.2 Web的作用 1.3 JavaWeb 第二部分&#xff1a;HTML概念与内容 2.1 HTML的定义 2.2 HTML的内容 第三部分&#xff1a;HTML的作用 3.1 HTML的作用 3.2 HTML在现代Web开发中的角色 …

[Redis]——主从同步原理(全量同步、增量同步)

目录 Redis集群&#xff1a; 主从同步原理&#xff1a; replid和offset: 全量同步和增量同步&#xff1a; repl_baklog文件&#xff1a; 主从集群的优化&#xff1a; Redis集群&#xff1a; 部署多台Redis我们称之为Redis集群&#xff0c;他有一个主节点(负责写操作)&…

爱普生晶振发布RTC模块晶振(压电侠)

爱普生晶振一直以”省&#xff0c;小&#xff0c;精”技术作为资深核心&#xff0c;并且已经建立了一个原始的垂直整合制造模型&#xff0c;可以自己创建独特的核心技术和设备&#xff0c;使用这些作为基地的规划和设计提供独特价值的产品. 世界领先的石英晶体技术精工爱普生公…

中国联通智慧矿山行业解决方案

中国联通国际公司以其全球化服务能力&#xff0c;针对矿山行业的特殊挑战提供了定制化的解决方案&#xff0c;尤其是在网络通信基础设施搭建和智能应用部署方面&#xff0c;助力企业克服远程作业环境下的通信难题&#xff0c;并有效拓展海外市场。 对于矿山类企业而言&#xf…

【遍历方法】浅析Java中字符串、数组、集合的遍历

目录 前言 字符串篇 1.1 使用 for 循环和 charAt 方法 1.2 使用增强 for 循环&#xff08;forEach 循环&#xff09; 1.3 使用 Java 8 的 Stream API 最终效果 数组篇 2.1 使用普通 for 循环 2.2 使用增强型 for 循环( forEach 循环) 2.3 使用 Arrays.asList 和 forE…