线上问题排查-定时任务状态未复位

项目业务

用户授权登录后,负责把本 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");
        }
    }

解决方式

  1. 加上淘汰时间就好了
  2. 没有其他逻辑,try catch 直接删掉,异常直接框架处理,异常后 key 不删除对代码影响也不大,后续正确后,依然可以同步前面没同步的
  3. 魔法值什么的抽取一下,等小优化

其他,优化思路

当时看这个业务的时候,这个代码也是有点屎山,死活看不懂流程是怎么跑的,在代码中没有看到对应的逻辑,后面才发现用了 MySQL触发器。。。

顺便梳理一下从登录、数据同步、上报给第三方的流程,也当作吐槽的续集 小公司后端架构、代码、流程吐槽

架构图如下:

首先,该项目涉及到四个进程,分别是 app(hn)、第三方授权、redis、MySQL、其他运动平台,前四个都是部署在一个服务器中。

  1. 当用户通过 app(hn)通过手机号注册时,创建账号,绑定用户信息,落库至 hn_uas
  2. 绑定用户信息后,MySQL 触发器调用,往 oauth 库创建账号(直接复制 uid、phone、password),是的,通过 MySQL 触发器的方式直接为其他项目创建账户,难怪死活查不到,数据修改的逻辑不收敛到代码里,难找的要死,高度耦合,表分库但是逻辑不分库,以及懒得再吐槽了,同类的还有很多
  3. 用户创建完成后,去第三方平台绑定 app(hn)信息,这里的绑定逻辑走的是第三方授权项目,由于第二步已经帮助创建账号了,所以跨系统登录是没问题的。登录完成后,往 redis 放置 key1 数据,key 中包含了 uid
  4. 用户使用 app 上传数据,落库至 hn_active,如果能从 redis 中查询到 key1 数据,额外存储到 A_sport_data 中。由于 第三方项目的 uid 是从 app(hn) 复制而来,所以 key1 是可以查询到的
  5. 当数据成功存储进 A_sport_data 后,同样的触发器调用,将数据复制到 oauth的 A_sport_data
  6. 第三方授权项目有一个定时器,定时扫描未同步的 A_sport_data ,进行数据上报,修改状态位

问题很明显,各个模块好像分离,但是又不分离,无用数据多次拷贝,明明是同一个账号缺又是单独的账号系统,两个项目可以合并成一个,app 业务和数据上报使用不同的前缀,用一个网关进行校验转发。就可以去除触发器,另外都是在一台机器上,也没啥业务量压力,分库也显得没有必要了,已经说烂的事情

这是一段防爬代码块,我不介意文章被爬取,但请注明出处
console.log("作者主页:https://www.cnblogs.com/Go-Solo");
console.log("原文地址:https://www.cnblogs.com/Go-Solo/p/18404971");
posted @ 2024-09-09 18:35  Go_Solo  阅读(20)  评论(0编辑  收藏  举报