服务器时区与数据库时区不一致导致时间bug记录

1、背景

一个活动,需要按照自然月刷新,每月一期,以活动开始当月作为第一期,每期可配置不同数据。问题出现在:活动开始时间为本月,但是查询用户数据发现当前为第二期,反复查看代码,确定计算期数逻辑无问题,十分诡异。期数计算代码如下:

java 复制代码
protected int getPeriod(Date begin, Date now) {
        // DateUtil为工具类,format方法将时间转化为 yyyy-MM-dd格式
        String beginTime = DateUtil.format(begin, DateUtil.FORMATTER_YYYYMMDD_STR);
        String nowTime = DateUtil.format(now, DateUtil.FORMATTER_YYYYMMDD_STR);
        int beginYear = Integer.valueOf(beginTime.substring(0, 4));
        int nowYear = Integer.valueOf(nowTime.substring(0, 4));
        int beginMonth = (beginTime.charAt(5) - '0') * 10 + (beginTime.charAt(6) - '0');
        int nowMonth = (nowTime.charAt(5) - '0') * 10 + (nowTime.charAt(6) - '0');
        // 计算期数(可能出现跨年,需要考虑年份)
        return nowMonth + 12 * (nowYear - beginYear) - beginMonth + 1;
    }

2、排查

服务为分布式架构,有多个节点,发现只有少数节点会产生异常数据(本次活动只配置了一期,计算结果为第二期时会因拿不到配置数据而空指针,根据报错日志判断)。查看配置数据,发现活动开始时间为本月1日00点00分00秒,因此数个小时的时差即会导致月份出现偏差,猜测服务器时区问题,date -R检查服务器时区,正常节点与异常节点时区一致,暂时不考虑时区问题。

配置数据会加载进内存,当修改配置数据时,会修改有改动表的版本号,定时任务根据表版本号去刷新配置。考虑是配置人员中途改过数据,定时任务出现问题导致配置没有更新。观察日志,发现刷新配置的时间异常,时区与机器时区不一致。

date -R 结果(+0900 东九区):

Wed, 12 Jun 2024 22:59:25 +0900

服务器日志时间:

java 复制代码
2024-06-12T01:17:22.506+0000

3、结论

出现错误的原因为:进程时区与数据库时区没有保持一致,导致进程内时间与实际要配置的时间出现偏差,最终导致计算出错。

4、总结

(1)临界点时间(跨天、跨月、跨年)极易受时区影响导致极大误差,出现时间问题时可第一时间查看时区问题

(2)机器时区与进程时区并不总是一致,需要摆脱这个惯性思维,用其他方式(如日志)确定进程时区。

相关推荐
jghhh011 分钟前
LT喷泉码编解码的MATLAB实现
数据库·算法·matlab
PD我是你的真爱粉42 分钟前
MySQL8新特性
数据库·mysql
shalou29011 小时前
Spring 核心技术解析【纯干货版】- Ⅶ:Spring 切面编程模块 Spring-Instrument 模块精讲
前端·数据库·spring
eWidget1 小时前
政务电子证照系统重构:如何解决跨模态数据的“一致性”与“安全合规”难题?
数据库·mongodb·kingbase·数据库平替用金仓·金仓数据库·文档数据库
芝士爱知识a3 小时前
【FinTech前沿】AlphaGBM:重塑期权交易的智能分析引擎——从原理到实践
数据结构·数据库·人工智能·alphagbm·期权
AC赳赳老秦3 小时前
2026主权AI趋势:DeepSeek搭建企业自有可控AI环境,保障数据安全实战
大数据·数据库·人工智能·python·科技·rabbitmq·deepseek
仍然.3 小时前
MYSQL---事务
数据库·mysql
king_harry3 小时前
openGauss 6.0 主备集群备份与恢复实战指南:基于 gs_probackup
数据库·opengauss·gs_probackup
ruxshui3 小时前
MySQL备份核心指南
数据库·mysql
霖霖总总3 小时前
[小技巧73]MySQL UUID 全面解析:UUID 的原理、结构与最佳实践
数据库·mysql