第四节:海量数据导出到Excel、百万Excel导入到DB、秒级/分钟级排行版

一. 海量数据导出到Excel

背景:

  但是当处理大数据量的Excel文件导出时,很可能因其内存占用较高而导致内存溢出问题。同时,数据处理过程可能非常耗时,导致用户等待时间过长或请求超时

 

解决方案:

 情况1:小数据量大文件

   A. 可以直接等待生成完毕,直接下载。

   B. 服务器不存档,以文件流的形式给前端,前端直接生成文件

情况2:大数据量的文件

  大文件导出都是异步,前端直接返回,而不是在线等待。

  服务器异步做了三件事:

   A. 利用NPOI生成Excel

   B. 将该Excel保存到文件服务器上

   C. 通知客户端进行下载,通常的方式:SignalR实时通知、发邮件、站内信等等。

 

 

二. 百万Excel导入到DB

背景:

 项目中有一个数据迁移,原来的数据存储在旧的系统,现在系统做了重构,需要迁移到新的系统中,老系统的数据被加工到Excel中了,需要基于Excel实现文件的导入,可能遇到的问题:

1 内存溢出:百万级的excel文件非常大,读取后都加载到内存中可能导致内存溢出。

2 性能问题:百万数据从excel中读取并插入DB这个过程缓慢,需要考虑到性能。

3 错误处理:在文件读取和导入的过程中,会遇到各种各样的问题,需要妥善的处理这些问题。

 

解决方案:

1 解决内存溢出

   首先百万数据存放在excel中的时候,可以分散到不同的sheet中;然后借助线程池,采用多线程读取不同的sheet,读取的过程中,基于NPOI库逐行读取excel中的内容,而非一次性加载到内存中。

2 解决性能问题

   设定一个批次,比如3000条吧,当读取到3000条的时候,就执行一次批量插入操作。

   批量插入借助开源库【EFCore.BulkExtensions】或【Zack.EFCore.Batch】进行插入

3 错误处理

  A. 逐行读取excel的时候要机型数据检查,格式问题提前检查好

   B. 考虑数据重复问题,可以将excel中的几个字段设置成唯一性约束

   C. 执行过程中报错,一般是先重试,还不行的话, 采用 “跳过+打印日志”的方式

 

最终结果:

   一百万数据的excel导入到数据库,大约需要90s左右

 

 

三. 基于Redis中ZSet(Sorted Set)实现秒级排行榜

背景:

  对于周榜、日榜、小时榜等,完全可以基于定时任务、离线任务等生成,直接统计数据然后做排序就行了,难度不大。 难度比较大的就是分钟级或者秒级的榜单的实现,因为数据库的话大量数据的order by会性能很差。

 

分析:

  1 ZSet数据结构形如 key-member-score 结构,其中member不重复

  2 分钟级别和秒级别的排行版最好是脱离DB,直接基于Redis。

  3 排行版肯定是由大到小排行

 

解决方案:

  1 采用ZSet结构存储,key为“myRank1”,member为用户的userId,score为用户的分数值

  2 新用户添加,形如 RedisHelper.ZAdd("myRank1", (80, "10001")); 其中10001为用户的userId,80为该用户的默认分数。

  3 用户分数增加 or 减少,可以:RedisHelper.ZIncrBy("myRank1", "10001", score); 其中score可以是正数 或 负数,在原分数上增加或减少。

  4 可以获取排名前99的用户集合,可以: RedisHelper.ZRange("myRank1", 0, 98);

 

增加难度:

  当用户的积分一样时,按照用户的创建时间来排序,也就是说,如果两个人分数相同,1.1日开通的用户必1.2日开通的用户排名靠前

 

解决方案:

  1 将分数score设置成一个浮点数,其中整数部分为正常的得分,小数部分为时间戳

  PS: 时间戳是这种形式1708746590000 ,共有13位,而1e13是100000 0000 0000,即1后面13个0,所以用时间戳/1e13就能得到一个小数.

  2 score = 分数 + 1-时间戳/1e13

  PS: 因为分数相同,先开通要在前面,所以需要 1-xxx, 后开通的时间戳大, 然后用 1-它,就小了,正好符合先开通的在前面。

 

 

 

 

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2024-07-21 09:11  Yaopengfei  阅读(70)  评论(1编辑  收藏  举报