### 起因
最近线上后台的日志出现错乱,经常会把今天的日志文件写入到昨天的日志文件中,导致昨天的日志缺失
像是这样
![image.png](https://s2.loli.net/2022/05/09/rFCMifm3eWSUwA1.png)
7号的日志写入到了6号,8号的写入到了7号,而且都丢失了一部分数据。
多亏了这位老哥的[文章](https://blog.csdn.net/Abysscarry/article/details/102847754),现在终于找到了解决办法
### 原因
参考上面的那位老哥的[文章](https://blog.csdn.net/Abysscarry/article/details/102847754),我们的情况和他那个基本一致,因为有两个服务器,导致`logback`写的时候错乱了,有兴趣的可以去那片文章看下,这里简单说一下原因:
原因主要是因为`TimeBasedRollingPolicy`的一个更新规则
`logback` 的这个 `rollingPolicy` 并不是每天0点自动更新日志文件,而是当准备写日志的时候,再去判断下文件的最后修改时间,最后修改时间是一个存在在对象中的变量。
例如
> 机器1和机器2日志的最后修改时间都是昨天11点,最近几个小时内因为没有新的请求,也就没有日志输出,
现在来到了第二天,机器1收到了请求,需要打印日志,然后对比了日期后发现最后修改时间是昨天,就把现在的sys-info.log 改名为昨天的日期.log, 创建一个新的 sys-info.log,然后开始写日志。
> 过了一会,机器2收到了请求,准备写日志,对比了之后发现,最后修改日期还是昨天,于是就把当前的 sys-info.log 改名为昨天的日期.log,创建一个新的 sys-info.log,但是当前的 sys-info.log 是今天的,昨天的已经重命名过了
> 就这样,昨天的日志就被丢失了。
### 解决方案
按照那位老哥的解决方案,他修改的 `TimeBasedRollingPolicy` 的源码,在每次重命名的时候判断一个重命名的文件是否存在,如果已经存在,就说明之前已经滚动过了,不需要重新操作。
不过这个方法也是蛮麻烦的,尤其是配合maven的时候。
不这样修改也可以,问题出在重命名上,所以避免重命名即可。
贴一下之前的logback配置
```xml
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
```
`logback` 当天的日志会按照写到 `file` 标签的文件中,然后达到滚动条件会改名为 `fileNamePattern` 中的名字,然后新的日志继续写到 `file` 中,所以删掉 `file` 标签即可,文件会直接写到 `fileNamePattern` 中,就不会出现文件错乱的问题了。关于这点官方文档有说明
![image.png](https://s2.loli.net/2022/05/09/OBvqpQ82m3HyVUw.png)
同时,也可以加上 `<prudent>true</prudent>` ,来加上文件锁,防止两个机器写日志时,一行没写完,然后被另一个机器打断,虽然这样会降低性能。
## 参考文档
[官方文档-重命名错误](https://logback.qos.ch/codes.html#renamingError)
[官方文档-基于时间的回滚](https://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy)
[多项目写入同一Logback日志文件导致的滚动混乱问题(修改Logback源码)](https://blog.csdn.net/Abysscarry/article/details/102847754)
记一次logback日志错乱问题