MapReduce思路生成PDF大文件解决方案

个人博客请访问 http://www.x0100.top  

最近一段时间公司搞个项目,其中有个将数据按照一定的格式生成PDF文件的功能。在网上搜寻以后决定采用itextpdf插件来实现生成PDF的功能。最初的生成思路比较老套,简单四句话,将要输出的格式做成html,在程序中读取html文件,从数据库获取数据替换html文件中的替换符,用itextpdf将html转换成pdf后保存到硬盘在数据库保存PDF路径。

功能完成后经过QA同事的测试上线了。但是上线后发现总有那么几个用户的文件生成不了,总是报内存溢出错我。经过线上排查发现,这几个用户的数据量都在万条以上,有个用户甚至超过了10万条,这个规模的数据一次从数据库取出来,然后生成PDF,不内存溢出才怪呢。

针对这个问题,又开始了网上搜寻。网上有的说专门找台机器,给这个机器足够大的内存,起一个JVM来生成PDF。这种方式从硬件角度来解决,但是这样会增加硬件成本,而且针对这个问题找OPS估计他们也不会过,没办法只能从软件角度来解决。

在之前的文章中分享过《海量数据面试题分析》。文章中针对海量超过内存的数据处理提供了几种思路,哈希切分、位图、布隆过滤、哈希表、堆等。乍一看有点懵,不过仔细分析后发现虽然方式不同,但是基本思路一样,就是将大数据切分成小的数据,然后一个一个处理,最后再针对各个小数据的结果进行处理,也就是大数据处理的MapReduce思路。

看到这里,举一反三,那么生成PDF是否也可以这样呢。比如:先生成小的PDF,每个小PDF 500条数据,等生成完后再把生成的小PDF集合成一个大的PDF,这样就可以从开发角度来解决生成PDF内存溢出的问题。

好了,思路已经理清,接下来我们来看具体实现。

Pom.xml中引入itextpdf包

MapReduce思路生成PDF大文件解决方案

实现字符串生成PDF的方法:

MapReduce思路生成PDF大文件解决方案

分批取出数据生成单个的PDF,记录生成的PDF路径。

分批取数据的实现思路:以一个表的不重复字段为条件,设置这个字段的最小值,分页从数据库查询记录,查询出来后循环数据的时候看这个字段的记录值是否大于当前值,如果大于则用记录值替换当前值。循环结束后再次查询数据库,直到数据库查询不出数据为止。具体代码如下(代码有些长,不用特别在意实现细节,每个公司的业务都不一样,关注实现思路即可):

MapReduce思路生成PDF大文件解决方案

MapReduce思路生成PDF大文件解决方案

MapReduce思路生成PDF大文件解决方案

MapReduce思路生成PDF大文件解决方案

MapReduce思路生成PDF大文件解决方案

MapReduce思路生成PDF大文件解决方案

MapReduce思路生成PDF大文件解决方案

合并生成的小PDF为一个大的PDF文件:

MapReduce思路生成PDF大文件解决方案

合并完成后将大PDF的路径保存到数据库,小的PDF从硬盘删除即可。

这种实现方案解决了生成PDF内存溢出的问题,但是还有两个问题没有解决。

  • 生成文件的时间过长,如果是同步的话那么链接早就断开,会影响其它功能的正常使用。

  • 对硬盘IO带来一定压力。

针对第一个问题可以采用将同步变异步的方式来解决,每个公司的异步实现方案可能所有不同,一般使用消息队列或者线程池。使用线程池的话需要注意线程安全和IO问题。

对硬盘IO带来的压力,目前来看可以忽略。

关注微信公众号和今日头条,精彩文章持续更新中。。。。。

 

 

掌握分布式mapreduce与raft算法与分布式数据MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念Map(映射)和Reduce(归约),是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。它极大地方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。 当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归约)函数,用来保证所有映射的键值对中的每一个共享相同的键组。MapReduce是面向大数据并行处理的计算模型、框架和平台,它隐含了以下三层含义:1)MapReduce是一个基于集群的高性能并行计算平台(Cluster Infrastructure)。它允许用市场上普通的商用服务器构成一个包含数十、数百至数千个节点的分布和并行计算集群。2)MapReduce是一个并行计算与运行软件框架(Software Framework)。它提供了一个庞大但设计精良的并行计算软件框架,能自动完成计算任务的并行化处理,自动划分计算数据和计算任务,在集群节点上自动分配和执行任务以及收集计算结果,将数据分布存储、数据通信、容错处理等并行计算涉及到的很多系统底层的复杂细节交由系统负责处理,大大减少了软件开发人员的负担。3)MapReduce是一个并行程序设计模型与方法(Programming Model & Methodology)。它借助于函数式程序设计语言Lisp的设计思想,提供了一种简便的并行程序设计方法,用Map和Reduce两个函数编程实现基本的并行计算任务,提供了抽象的操作和并行编程接口,以简单方便地完成大规模数据的编程和计算处理Raft 是一种为了管理复制日志的一致性算法。它提供了和 Paxos 算法相同的功能和性能,但是它的算法结构和 Paxos 不同,使得 Raft 算法更加容易理解并且更容易构建实际的系统。为了提升可理解性,Raft 将一致性算法分解成了几个关键模块,例如leader人选举、日志复制和安全性。同时它通过实施一个更强的一致性来减少需要考虑的状态的数量。从一个用户研究的结果可以证明,对于学生而言,Raft 算法比 Paxos 算法更加容易学习。Raft 算法还包括一个新的机制来允许集群成员的动态改变,它利用重叠的大多数来保证安全性。 一致性算法允许一组机器像一个整体一样工作,即使其中一些机器出现故障也能够继续工作下去。正因为如此,一致性算法在构建可信赖的大规模软件系统中扮演着重要的角色。在过去的 10 年里,Paxos 算法统治着一致性算法这一领域:绝大多数的实现都是基于 Paxos 或者受其影响。同时 Paxos 也成为了教学领域里讲解一致性问题时的示例。 但是不幸的是,尽管有很多工作都在尝试降低它的复杂性,但是 Paxos 算法依然十分难以理解。并且,Paxos 自身的算法结构需要进行大幅的修改才能够应用到实际的系统中。这些都导致了工业界和学术界都对 Paxos 算法感到十分头疼。 和 Paxos 算法进行过努力之后,我们开始寻找一种新的一致性算法,可以为构建实际的系统和教学提供更好的基础。我们的做法是不寻常的,我们的首要目标是可理解性:我们是否可以在实际系统中定义一个一致性算法,并且能够比 Paxos 算法以一种更加容易的方式来学习。此外,我们希望该算法方便系统构建者的直觉的发展。不仅一个算法能够工作很重要,而且能够显而易见的知道为什么能工作也很重要。 Raft 一致性算法就是这些工作的结果。在设计 Raft 算法的时候,我们使用一些特别的技巧来提升它的可理解性,包括算法分解(Raft 主要被分成了leader人选举,日志复制和安全三个模块)和减少状态机的状态(相对于 Paxos,Raft 减少了非确定性和服务器互相处于非一致性的方式)。一份针对两所大学 43 个学生的研究表明 Raft 明显比 Paxos 算法更加容易理解。在这些学生同时学习了这两种算法之后,和 Paxos 比起来,其中 33 个学生能够回答有关于 Raft 的问题。 Raft 算法在许多方面和现有的一致性算法都很相似(主要是 Oki 和 Liskov 的 Viewstamped Replication),但是它也有一些独特的特性: 强leader:和其他一致性算法相比,Raft 使用一种更强的leader能力形式。比如,日志条目只从leader发送给其他的服务器。这种方式简化了对复制日志的管理并且使得 Raft 算法更加易于理解。leader选举:Raft 算法使用一个随机计时器来选举leader。这种方式只是在任何一致性算法都必须实现的心跳机制上增加了一点机制。在解决冲突的时候会更加简单快捷。成员关系调整:Raft 使用一种共同一致的方法来处理集群成员变换的问
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值