记一次因为共享缓存导致流水号重复的问题排查过程

2024-03-11 14:36

本文主要是介绍记一次因为共享缓存导致流水号重复的问题排查过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景:

        在开发日终应用或者跑批应用的时候,进行每天凌晨跑批或者全天跑批多次进行表数据清理的时候,每次清理都会登记操作明细到日志表,流水号是根据Oracle号段模式获取1000个流水号段放内存里,不够用再从数据库重新获取一批。跑批应用是连接了多个数据源的(TDSQL 9个分库),每执行完一个分库的清理任务再重新执行下一个分库的。任务调度平台每次到了启动时间就会部署实例,然后再销毁实例。

问题来了:写操作日志的时候,有些分库的error日志会报insert唯一键冲突,但是这个获取流水号的方法是每个分库都独立的,从Oracle的递增序列不断增加的,每个分库获取的一批流水号然后再插入每个分库的日志表理论上是不会重复的,那为什么会出现这样的情况呢?而且这个DuplicateKeyException还是偶发的,并不是每次跑批的时候都会出现,有时候01分库报错,有时候02分库报错,01分库好好的没问题.....

排查思路:

1、初步怀疑是平台部署实例的时候没有销毁掉,而是复用了上一次部署的内存,导致内存里还残留上次缓存的流水号没用完继续用,经咨询发现平台的机制是会销毁重新部署的

2、可能是获取流水号的方法逻辑有问题,排查了一遍代码没发现异常,而且这套流水号方法很多应用使用了很多年没出现过问题;

3、查看日志平台,怀疑是分库的日志显示错乱了,01分库出现的报错日志显示到了02分库上,导致毫无规律可言,经咨询相关平台的同事排除这一可能了

4、比较冲突的流水号以及日志表的流水号规律,发现不是连续的,比如:01分库上午使用了1,2,3;然后02分库的流水号理论上应该也是从1,2,3开始的,但是事实上却不是如此,而是从4,5,6开始;下午执行的时候,02分库应该是从上午的1,2,3开始递增使用4,5,6才对,但是居然又使用了1,2,3

结合任务调度平台多数据源任务的处理机制:每次部署都共享一块内存空间,执行完全部分库任务才会销毁这份内存资源,还有流水号申请一批存放内存的逻辑找到问题归因所在:

​结论:

在开发日终应用或者跑批应用的时候要特别注意,对于分库任务来说,是会共享实例内存的,因此一定要注意内存或缓存使用的场景,很有可能处理异常。以调框架里ISequenceService.getSequence来生成流水号举例:

1)第一次跑批:09分库的任务先发现缓存流水号为空,就会从09分库申请一段流水(1-1000),并放到缓存中使用,若此时97分库的任务也需要使用流水号,发现缓存中有流水号了,就直接使用缓存中的流水号并且同步到数据库,并没有从97分库申请流水。

​2)第二次跑批:97分库的任务先发现缓存流水号为空,就会从97分库申请一段流水(1-1000),并放到缓存中使用,注意本次使用的流水在第一次跑批中已经使用过,如果作为唯一键插入分库中,就会出现唯一键冲突。

​启示:

跑批或日终应用,一定不能使用内存或缓存进行分库级别的处理,否则会分库任务间的处理会互相干扰,因为单次跑批,所有分库任务都是共享实例内存的!尤其注意获取交易流水号的时候影响甚大!

这篇关于记一次因为共享缓存导致流水号重复的问题排查过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/798072

相关文章

Django HTTPResponse响应体中返回openpyxl生成的文件过程

《DjangoHTTPResponse响应体中返回openpyxl生成的文件过程》Django返回文件流时需通过Content-Disposition头指定编码后的文件名,使用openpyxl的sa... 目录Django返回文件流时使用指定文件名Django HTTPResponse响应体中返回openp

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

批量导入txt数据到的redis过程

《批量导入txt数据到的redis过程》用户通过将Redis命令逐行写入txt文件,利用管道模式运行客户端,成功执行批量删除以Product*匹配的Key操作,提高了数据清理效率... 目录批量导入txt数据到Redisjs把redis命令按一条 一行写到txt中管道命令运行redis客户端成功了批量删除k

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Win10安装Maven与环境变量配置过程

《Win10安装Maven与环境变量配置过程》本文介绍Maven的安装与配置方法,涵盖下载、环境变量设置、本地仓库及镜像配置,指导如何在IDEA中正确配置Maven,适用于Java及其他语言项目的构建... 目录Maven 是什么?一、下载二、安装三、配置环境四、验证测试五、配置本地仓库六、配置国内镜像地址

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright