防止 .Net 服务重新启动时数据丢失

Posted

技术标签:

【中文标题】防止 .Net 服务重新启动时数据丢失【英文标题】:Preventing data loss on .Net service restart 【发布时间】:2021-12-19 00:23:03 【问题描述】:

从 .Net 服务中,一些指标被聚合并以每日周期刷新。如果服务关闭/重新启动,在最坏的情况下,丢失的数据可能会从几分钟到一整天不等。

如果我经常记录,为了尽量减少(如果不能防止)损失,比如每小时而不是每天,记录的行数将从每天三位数的百万行猛增到至少两位数十亿行。尝试在服务正常关闭/重新启动之前刷新并不能防止服务突然关闭/重新启动的损失。

哪种类型的 C# 编程结构或事件处理有助于减少记录频率并将损失降至尽可能小的百分比?

(我希望这个问题足够具体/有针对性。如果您认为不是,想在 cmets 中讨论。)

【问题讨论】:

【参考方案1】:

如果您确定服务是正常关闭的,而不是快速而艰难的方式,那么在 .net Web 应用程序中,您可以在需要时将保存数据的内容附加到应用程序停止处理程序。 这样的函数需要能够访问当前的日志状态,所以日志服务需要知道它当前记录的数据状态。

// if IApplicationLifetime wont work, try IHostApplicationLifetime
public class Startup

    public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime)
    
        applicationLifetime.ApplicationStopping.Register(OnShutdown);
        // Additional configurations, etc...
    
 
    private void OnShutdown()
    
         //this code is called when the application stops
    

如果问题在于过多的数据库调用,这会迫使您批量记录日志条目,那么我会先更频繁地将日志记录到本地文件,然后让后台服务定期扫描并将该文件的上下文上传到分批分贝。同样,这需要标记已上传的条目,并且在某些情况下,当进行 db 调用但应用程序在将文件的上下文标记为已上传之前崩溃时,下次将进行重复上传。 这可以通过将文件中的最后一个日志条目与最后一个上传条目进行比较,在数据库中存储一些标记来避免,该标记与日志上传保存在同一事务中,或者通过检查,比如说,上传日志的时间戳与本地存储中的日志。

【讨论】:

同意。将 X 事件或 1 小时的数据记录到文件中。文件填满后,将文件重命名为入站目录,开始记录到新文件。让另一个进程将入站目录中的文件上传到数据库。【参考方案2】:
    每小时保存一次当前聚合值,然后删除前一小时的聚合值 保存一天一次的聚合值并删除最后一个小时的值

缩小数据范围或使用相邻时间重复数据删除可能会有所帮助。

例子,

如果最新数据点在前一个数据点的 0.01% 范围内且在最后 500 毫秒内,则丢弃它 为每个数据点保留观察日期时间和结束日期时间,在这些数据点测量第一次看到值的时间,然后从该日期时间到结束日期时间观察到的所有点都在首次观察值的 0.1% 范围内.这也可能会超时,并且不会让超过 30 秒的数据进入一个样本。

这些都取决于您的业务用户是否同意容差、事件数量的丢失、采样频率等。

【讨论】:

以上是关于防止 .Net 服务重新启动时数据丢失的主要内容,如果未能解决你的问题,请参考以下文章

重新启动应用程序时数据丢失(核心数据)

核心数据 - 重新启动应用程序时部分数据丢失

房间数据库在重新启动应用程序时丢失数据

Heroku:每次测功机重新启动时都会丢失 Django 数据库文件

Docker容器重启不丢失数据

按下浏览器重新加载按钮时防止变量丢失[重复]