线上问题排查-定时任务状态未复位
项目业务
用户授权登录后,负责把本 app 的运动同步到第三方,分别对接了 A、B、C、D 等第三方,各个平台的推送方式不太一样,有一些是主动查询,有一些是主动推送
场景
周五线上 Redis 报了内存不足,代码排查后发现用户数据占用了很大一部分,并且只存储不查询也不设置过期事件也没有内存淘汰策略,不知道写这个代码的人怎么想的,所以就设置了淘汰策略并把存储的逻辑删掉了,发包到线上;
发完包后,有用户反馈数据一直没同步
解决
这里处理比较简单,由于之前打了日志,问题比较直观,不需要工具排查,每次执行都进入 try 的 else 分支,很明显 redis 的 key 状态没有复位,并且没有其他机制(比如过期删除、超时复位逻辑)保证,导致无法同步
由于没有查询到 key 在其他位置的使用,并且任务中不存在死循环、死锁、等待等问题,大概率是定时任务执行的过程中,进程直接被杀死导致的
代码如下
@Scheduled(initialDelay = 1000, fixedDelay = 6000)
public void task2() {
log.info("执行开始:");
try {
Object gd_job = this.redisTemplate.opsForValue().get("gd_job");
if (null != gd_job && gd_job.equals("N")) {
this.redisTemplate.opsForValue().set("gd_job", "Y");
// 业务
this.redisTemplate.opsForValue().set("gd_job", "N");
log.info("执行结束:");
} else {
log.info("其他任务进行中此次终止:");
}
} catch (final Exception e) {
e.printStackTrace();
log.info("异常:", e);
this.redisTemplate.opsForValue().set("gd_job", "N");
}
}
解决方式
- 加上淘汰时间就好了
- 没有其他逻辑,try catch 直接删掉,异常直接框架处理,异常后 key 不删除对代码影响也不大,后续正确后,依然可以同步前面没同步的
- 魔法值什么的抽取一下,等小优化
其他,优化思路
当时看这个业务的时候,这个代码也是有点屎山,死活看不懂流程是怎么跑的,在代码中没有看到对应的逻辑,后面才发现用了 MySQL触发器。。。
顺便梳理一下从登录、数据同步、上报给第三方的流程,也当作吐槽的续集 小公司后端架构、代码、流程吐槽
架构图如下:
首先,该项目涉及到四个进程,分别是 app(hn)、第三方授权、redis、MySQL、其他运动平台,前四个都是部署在一个服务器中。
- 当用户通过 app(hn)通过手机号注册时,创建账号,绑定用户信息,落库至 hn_uas
- 绑定用户信息后,MySQL 触发器调用,往 oauth 库创建账号(直接复制 uid、phone、password),是的,通过 MySQL 触发器的方式直接为其他项目创建账户,难怪死活查不到,数据修改的逻辑不收敛到代码里,难找的要死,高度耦合,表分库但是逻辑不分库,以及懒得再吐槽了,同类的还有很多
- 用户创建完成后,去第三方平台绑定 app(hn)信息,这里的绑定逻辑走的是第三方授权项目,由于第二步已经帮助创建账号了,所以跨系统登录是没问题的。登录完成后,往 redis 放置 key1 数据,key 中包含了 uid
- 用户使用 app 上传数据,落库至 hn_active,如果能从 redis 中查询到 key1 数据,额外存储到 A_sport_data 中。由于 第三方项目的 uid 是从 app(hn) 复制而来,所以 key1 是可以查询到的
- 当数据成功存储进 A_sport_data 后,同样的触发器调用,将数据复制到 oauth的 A_sport_data
- 第三方授权项目有一个定时器,定时扫描未同步的 A_sport_data ,进行数据上报,修改状态位
问题很明显,各个模块好像分离,但是又不分离,无用数据多次拷贝,明明是同一个账号缺又是单独的账号系统,两个项目可以合并成一个,app 业务和数据上报使用不同的前缀,用一个网关进行校验转发。就可以去除触发器,另外都是在一台机器上,也没啥业务量压力,分库也显得没有必要了,已经说烂的事情
这是一段防爬代码块,我不介意文章被爬取,但请注明出处
console.log("作者主页:https://www.cnblogs.com/Go-Solo");
console.log("原文地址:https://www.cnblogs.com/Go-Solo/p/18404971");