最近连续两个月代码出问题,给公司带来了损失,第一次是2000多,第二次直接20000多,这里来做一次总结。
问题
咱们的发布流程是 测试->预发->生产,这样子三个环境,代码到生产环境的时候会检查是否到预发环境。出问题的是Spring的一个定时任务,改了一个和钱有关的比例后按照流程发布上线,过了几天发现有些金额不对,排查后发现多了一个环境[预发2],这个环境和生产环境是共用数据库的,这个环境是为了一些需要生产数据的测试,但是这个当时没人维护了,导致代码落后生产,定时任务执行了原来的逻辑。
第二次问题根本上是自己考虑不周,还是在定时任务上,Spring指定的定时任务执行时间并不保证在那个时间执行,为了防止重复执行其实加了一个一分钟的锁,但任务延后了,并没有锁住,导致数据重复执行,最关键的是一个判断,如果查询数据库有A,那么跳过,没有则执行后续逻辑在插入数据库,这个判断在多实例的分布式环境里出现了问题,都没有查询到A,都插入了数据。
解决方法
第一个问题比较简单,任务只在生产环境执行。
第二个问题改动是Spring的定时任务开始就给一个长时间的锁,得假定任务会执行很长时间,执行完后手动解锁。在进入业务逻辑批处理的时候再对单条A相关的数据加锁,防止看到不一致的状态。所有的锁一定要能够锁住相应的逻辑,尽量手动解锁。
后记
这次问题后深感分布式系统开发起来不容易,处理状态非常麻烦,而我目前的知识也仅仅是使用锁来避免出现不一致的问题,再想想现在的系统里其实非常多的地方有这样的问题,很不严谨。编程之路真实道阻且长。