重复插入

 最近业务方,又反馈1个问题,违约邮件没有发送。

经排查,1个人的信用表,出现了重复数据。

1个人的信用主要由 userId和业务类型categoryId决定。


结果,categoryId为空,getByUserIdAndCategoryId 因为categoryId为null,总是查询不到数据,最终重复插入。

坑!


要点总结

1、jmq接收的消息,需要检查参数合法性。

  早期接收的数据,categoryId字段没有传。

  至少需要留个error日志。

2、getByUserIdAndCategoryId 查询,其中1个字段为null,所以总是查询不到。

判定1个人的信用记录不存在,继续插入,最终出现了1个人有17次的记录。

3、清理数据

试运行的时候,没有清除预约记录的数据,只是清除了 黑名单等数据。

--------------------------------------------迷之自信-------------------------------------

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2


第1次总结之后,在写作总结的过程中,发现根本无法解释 代码抛出的异常。

既然categoryId为null,那应该一直是查询不到。

如果查询的到,不会重复插入。


再次分析。

出现问题的人,一部人人次数在3~17,还有一批人都是2,都是2的,就有规律了。为啥不都是3,不都是4?

我们只能假设:3~17次的人,都是脏数据引起的,经排查他们至少有2个人的categoryId都是null。


都是2的这批人,可能是另外1个原因导致的。


本着认真负责的态度,我和某某再次梳理了这个问题产生的原因,发现刚刚的结论有稍许问题。

结论如下:

1、预约记录脏数据,对咱们的系统有影响,但不是造成“违约邮件发送失败”的根本原因。

2、咱们的系统,在处理“1个人批量取消记录造成的违约时”,逻辑有问题,最终导致邮件发送失败。

  查询数据,发现7月31日,有用户(或者健身房预约系统触发),同1分钟,取消了2016年的10几条预约记录。

  所以,主要问题在于自身逻辑不对,上游B系统正好触发了这种场景。

--------------------------------------------解决办法-------------------------------------

老代码,大多是单线程处理任务的。

后来jmq消息异步处理,2台机器,同时处理了1个人的10条记录,每台机器分5台(举例子),就产生了重复插入的问题。


多线程处理插入,1种方式,使用分布式锁,把 userId和categoryId等业务参数,交给第三方锁。

另外1种方式,数据库增加唯一索引或主键,重复插入的时候,数据库会报错。

在报错的时候,再次查询1次(咱们那个项目需要再次查询,然后更新)。


------------------------------------------其它2个问题------------------------------------

1、自己构造的 分布式锁,主要用来 让定时任务,只执行1个。

释放锁的过程,必须放到finally里。

之前一直是把 系统标准资源的释放过程,比如io、file,放到finally。


2、filter过滤器,没有execlude这个排除url的配置。

网上,只找到1个人这么用,但是大多数网友,都是认为 自定义 1个参数。

公司内部,有个同事 自定义了1个filter,自定义了1个参数,正好叫做execlude,让另外一个同事,以为 java的filter有这个 标准化参数配置。

©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值