① 如何利用 python 读取数据科学中常见几种文件
前言
如果你是数据行业的一份子,那么你肯定会知道和不同的数据类型打交道是件多么麻烦的事。不同数据格式、不同压缩算法、不同系统下的不同解析方法——很快就会让你感到抓狂!噢!我还没提那些非结构化数据和半结构化数据呢。
对于所有数据科学家和数据工程师来说,和不同的格式打交道都乏味透顶!但现实情况是,人们很少能得到整齐的列表数据。因此,熟悉不同的文件格式、了解处理它们时会遇到的困难以及处理某类数据时的最佳/最高效的方法,对于任何一个数据科学家(或者数据工程师)而言都必不可少。
在本篇文章中,你会了解到数据科学家或数据工程师必须知道的几种常规格式。我会先向你介绍数据行业里常用的几种不同的文件格式。随后,我会向大家介绍如何在 Python 里读取这些文件格式。
PS:在后文中提到的数据科学家,同样也包括数据工程师以及所有的数据科学专家。
目录
文件格式是什么。数据科学家应当了解各种不同文件格式的原因。不同的文件格式以及从 Python 中读取这些文件的方法。
1. 逗号分隔值
2. XLSX
3. ZIP
4. 纯文本(txt)
5. JSON
6. XML
7. HTML
8. 图像
9. 分层数据格式
10. PDF
11. DOCX
12. MP3
13. MP4
1. 文件格式是什么。
文件格式是计算机为了存储信息而使用的对信息的特殊编码方式。首先,文件格式代表着文件的类型,如二进制文件或者 ASCII 文件等。其次,它体现了信息组织的方式。比如,逗号分隔值(CSV)文件格式用纯文本来储存列表数据。
为了识别一个文件的格式,你通常会去看这个文件的扩展名。比如,一个以“CSV”格式保存的名为“Data”的文件下方的文件名会显示为“Data.csv”。看到“.csv”这个扩展名,我们就会清楚地知道这是一个“CSV”文件,并且还可以知道其中的数据是以表格的形式储存的。
2. 数据科学家应当了解各种不同文件格式的原因。
通常,你碰到的文件类型取决于你当下构造的应用。举个例子,在一个图像处理系统中,你需要把图像作为输入和输出。所以,你所见到的文件大都是jpeg、gif 或者 png 格式的。
作为一个数据科学家,你需要了解各种文件格式的底层结构以及相应的优势和劣势。只有了解了数据的底层结构,你才能够进一步去探索它,或者决定如何来储存相关的数据。
选择一个最理想的文件格式来储存数据能够提升你的模型在处理数据时的性能。
现在,让我们讨论一下下方这些文件格式以及如何在 Python 中读取它们:
逗号分隔值(CSV)XLSXZIP纯文本(txt)JSONXMLHTML图像分层数据格式PDFDOCXMP3MP4
3. 不同的文件格式以及从 Python 中读取这些文件的方法。
3.1 逗号分隔值
逗号分隔值文件格式属于电子表格文件格式的一种。
什么是电子表格文件格式?
在电子表格文件格式中,数据被储存在单元格里。每个单元格都处于特定的行和列中。电子表格文件中的列拥有不同的类型。比如说,它可以是字符串型的、日期型的或者整数型的。最常用的电子表格文件格式包括:逗号分隔值(CSV)、Microsoft Excel 电子表格(xls)以及 Microsoft Excel Open XML 电子表格(xlsx)。
CSV 文件中的每一行都代表一份观察报告,或者也可以说是一条记录。每一个记录都包含一个或者更多由逗号分隔的字段。
有时你看你会遇到用制表符而非逗号来分隔字段的文件。这种文件格式被称为 TSV(制表符分隔值)文件格式。
下面是一个用 Notepad 打开的 CSV 文件。
在Python 中从 CSV 文件里读取数据
现在让我们看看如何在 Python 中读取一个 CSV 文件。你可以用 Python 中的“pandas”库来加载数据。import pandas as pd
df = pd.read_csv(“/home/Loan_Prediction/train.csv”)
上方的代码将会把 train.csv 文件加载进 DataFrame df 中。
3.2 XLSX文件
XLSX 是 Microsoft Excel Open XML 的文件格式,它同样可以归入电子表格文件格式这一类中。它是由 Microsoft Excel 开发的一种基于 XML 文件格式。Microsoft Office 2007 最先采用 XLSX 格式来储存数据。
在XLSX 中,数据被放在工作表的单元格和列当中。每个 XLSX 文件可能包含一个或者更多工作表,所以一个工作簿中可能会包含多个工作表。
下面是一个在 Microsoft Excel 中打开的“xlsx”文件。
上图显示的这个文件里包含多个工作表,这些工作表的名称分别为 Customers、Employees、Invoice 和 Order。图片中显示的是其中一个工作表——“Invoice”——中的数据。
从XLSX 文件读取数据
让我们一起来加载一下来自 XLSX 文件的数据并且定义一下相关工作表的名称。此时,你可以用 Python 中的“pandas”库来加载这些数据。import pandas as pd
df = pd.read_excel(“/home/Loan_Prediction/train.xlsx”,sheetname = “Invoice”)
上方的代码将会把来自“train.xlsx”文件的工作表“Invoice”加载进 DataFrame df 中。
3.3 ZIP 文件
ZIP 格式是一种归档文件格式。
什么是归档文件格式?
在归档文件格式中,你可以创建一个包含多个文件和元数据的文件。归档文件格式通常用于将多个数据文件放入一个文件中的过程。这么做是为了方便对这些文件进行压缩从而减少储存它们所需的存储空间。
有很多种常用的电脑数据归档格式可以创建归档文件。Zip、RAR 和 Tar 是最常用的3种用于压缩数据的归档文件格式。
因此,ZIP 文件格式是一种无损压缩格式,这意味着如果你用 ZIP 格式压缩了多个文件,那么在解压缩之后你能够完全恢复这些数据。ZIP 文件格式使用多种压缩算法来压缩文件。你可以通过 .zip 这个扩展名轻易地识别出一个 ZIP 文件。
在Python 中读取 .ZIP 文件
你可以通过导入“zipfile”包来读取 zip 文件。下方的代码可以实现读取“T.zip”中的“train.csv”文件。import zipfile
在这里我已经讨论了其中一种最常用的归档格式,也已经讨论了如何在 python 中打开这种归档格式。我不会再对其他的归档格式进行展开讨论。如果你想了解不同类型的归档格式并且想对其做出比较
② golang生成的json是格式化后的,有没有提供方法压缩一下
golang生成的json是格式化后的,有没有提供方法压缩一下 那些空格换行也占用不了多少空间, 要压缩可以自己写个正则, 把那些空格、换行去掉就行了。
③ 服务化架构的分布式事务问题用什么方法解决
1. 性能和时延问题
在服务化之前,业务通常都是本地API调用,本地方法调用性能损耗较小。服务化之后,服务提供者和消费者之间采用远程网络通信,增加了额外的性能损耗:
1) 客户端需要对消息进行序列化,主要占用CPU计算资源。
2) 序列化时需要创建二进制数组,耗费JVM堆内存或者堆外内存。
3) 客户端需要将序列化之后的二进制数组发送给服务端,占用网络带宽资源。
4) 服务端读取到码流之后,需要将请求数据报反序列化成请求对象,占用CPU计算资源。
5) 服务端通过反射的方式调用服务提供者实现类,反射本身对性能影响就比较大。
6) 服务端将响应结果序列化,占用CPU计算资源。
7) 服务端将应答码流发送给客户端,占用网络带宽资源。
8) 客户端读取应答码流,反序列化成响应消息,占用CPU资源。
通过分析我们发现,一个简单的本地方法调用,切换成远程服务调用之后,额外增加了很多处理流程,不仅占用大量的系统资源,同时增加了时延。一些复杂
的应用会拆分成多个服务,形成服务调用链,如果服务化框架的性能比较差、服务调用时延也比较大,业务服务化之后的性能和时延将无法满足业务的性能需求。
1.1RPC框架高性能设计
影响RPC框架性能的主要因素有三个。
1) I/O调度模型:同步阻塞I/O(BIO)还是非阻塞I/O(NIO)。
2) 序列化框架的选择:文本协议、二进制协议或压缩二进制协议。
3) 线程调度模型:串行调度还是并行调度,锁竞争还是无锁化算法。
1. I/O调度模型
在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O的
阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大
优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。
JDK1.5_update10版本使用epoll替代了传统的select/poll,极大地提升了NIO通信的性能,它的工作原理如图1-1所示。
图1-1非阻塞I/O工作原理
Netty是一个开源的高性能NIO通信框架:它的I/O线程NioEventLoop由于聚合了多路复用器Selector,可以同时并发处理成
百上千个客户端Channel。由于读写操作都是非阻塞的,这就可以充分提升I/O线程的运行效率,避免由于频繁I/O阻塞导致的线程挂起。另外,由于
Netty采用了异步通信模式,一个I/O线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。
Netty被精心设计,提供了很多独特的性能提升特性,使它做到了在各种NIO框架中性能排名第一,它的性能优化措施总结如下。
1) 零拷贝:(1)Netty的接收和发送ByteBuffer采用DIRECT
BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP
BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送
过程中多了一次缓冲区的内存拷贝。(2)Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer
那样方便地对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。(3)Netty的文件传输采用
了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。
2)
内存池:随着JVM虚拟机和JIT即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓冲区Buffer,情况却稍有不同,特别是对于
堆外直接内存的分配和回收,是一件耗时的操作。为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制。性能测试表明,采用内存池的
ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右(性能数据与使用场景强相关)。
3)
无锁化的串行设计:在大多数场景下,并行多线程处理可以提升系统的并发性能。但是,如果对于共享资源的并发访问处理不当,会带来严重的锁竞争,这最终会导
致性能的下降。为了尽可能地避免锁竞争带来的性能损耗,可以通过串行化设计,即消息的处理尽可能在同一个线程内完成,期间不进行线程切换,这样就避免了多
线程竞争和同步锁。为了尽可能提升性能,Netty采用了串行无锁化设计,在I/O线程内部进行串行操作,避免多线程竞争导致的性能下降。表面上看,串行
化设计似乎CPU利用率不高,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设
计相比一个队列-多个工作线程模型性能更优。
4) 高效的并发编程:volatile的大量、正确使用;CAS和原子类的广泛使用;线程安全容器的使用;通过读写锁提升并发性能。
2. 高性能序列化框架
影响序列化性能的关键因素总结如下。
1) 序列化后的码流大小(网络带宽的占用)。
2) 序列化&反序列化的性能(CPU资源占用)。
3) 是否支持跨语言(异构系统的对接和开发语言切换)。
4) 并发调用的性能表现:稳定性、线性增长、偶现的时延毛刺等。
相比于JSON等文本协议,二进制序列化框架性能更优异,以java原生序列化和Protobuf二进制序列化为例进行性能测试对比,结果如图1-2所示。
图1-2序列化性能测试对比数据
在序列化框架的技术选型中,如无特殊要求,尽量选择性能更优的二进制序列化框架,码流是否压缩,则需要根据通信内容做灵活选择,对于图片、音频、有大量重复内容的文本文件(例如小说)可以采用码流压缩,常用的压缩算法包括GZip、Zig-Zag等。
3. 高性能的Reactor线程模型
该模型的特点总结如下。
1) 有专门一个NIO线程:Acceptor线程用于监听服务端,接收客户端的TCP连接请求。
2) 网络I/O操作:读、写等由一个NIO线程池负责,线程池可以采用标准的JDK线程池实现,它包含一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送。
3) 1个NIO线程可以同时处理N条链路,但是1个链路只对应1个NIO线程,防止产生并发操作。
由于Reactor模式使用的是异步非阻塞I/O,所有的I/O操作都不会导致阻塞,理论上一个线程可以独立处理所有I/O相关的操作,因此在绝大多数场景下,Reactor多线程模型都可以完全满足业务性能需求。
Reactor线程调度模型的工作原理示意如图1-3所示。
图1-3高性能的Reactor线程调度模型
1.2业务最佳实践
要保证高性能,单依靠分布式服务框架是不够的,还需要应用的配合,应用服务化高性能实践总结如下:
1) 能异步的尽可能使用异步或者并行服务调用,提升服务的吞吐量,有效降低服务调用时延。
2) 无论是NIO通信框架的线程池还是后端业务线程池,线程参数的配置必须合理。如果采用JDK默认的线程池,最大线程数建议不超过20个。因为JDK的线程池默认采用N个线程争用1个同步阻塞队列方式,当线程数过大时,会导致激烈的锁竞争,此时性能不仅不会提升,反而会下降。
3)
尽量减小要传输的码流大小,提升性能。本地调用时,由于在同一块堆内存中访问,参数大小对性能没有任何影响。跨进程通信时,往往传递的是个复杂对象,如果
明确对方只使用其中的某几个字段或者某个对象引用,则不要把整个复杂对象都传递过去。举例,对象A持有8个基本类型的字段,2个复杂对象B和C。如果明确
服务提供者只需要用到A聚合的C对象,则请求参数应该是C,而不是整个对象A。
4) 设置合适的客户端超时时间,防止业务高峰期因为服务端响应慢导致业务线程等应答时被阻塞,进而引起后续其他服务的消息在队列中排队,造成故障扩散。
5) 对于重要的服务,可以单独部署到独立的服务线程池中,与其他非核心服务做隔离,保障核心服务的高效运行。
6) 利用Docker等轻量级OS容器部署服务,对服务做物理资源层隔离,避免虚拟化之后导致的超过20%的性能损耗。
7) 设置合理的服务调度优先级,并根据线上性能监控数据做实时调整。
2. 事务一致性问题
服务化之前,业务采用本地事务,多个本地SQL调用可以用一个大的事务块封装起来,如果某一个数据库操作发生异常,就可以将之前的SQL操作进行回滚,只有所有SQL操作全部成功,才最终提交,这就保证了事务强一致性,如图2-1所示。
服务化之后,三个数据库操作可能被拆分到独立的三个数据库访问服务中,此时原来的本地SQL调用演变成了远程服务调用,事务一致性无法得到保证,如图2-2所示。
图2-2服务化之后引入分布式事务问题
假如服务A和服务B调用成功,则A和B的SQL将会被提交,最后执行服务C,它的SQL操作失败,对于应用1消费者而言,服务A和服务B的相关
SQL操作已经提交,服务C发生了回滚,这就导致事务不一致。从图2-2可以得知,服务化之后事务不一致主要是由服务分布式部署导致的,因此也被称为分布
式事务问题。
2.1分布式事务设计方案
通常,分布式事务基于两阶段提交实现,它的工作原理示意图如图2-3所示。
图2-3两阶段提交原理图
阶段1:全局事务管理器向所有事务参与者发送准备请求;事务参与者向全局事务管理器回复自己是否准备就绪。
阶段2:全局事务管理器接收到所有事务参与者的回复之后做判断,如果所有事务参与者都可以提交,则向所有事务提交者发送提交申请,否则进行回滚。事务参与者根据全局事务管理器的指令进行提交或者回滚操作。
分布式事务回滚原理图如图2-4所示。
图2-4分布式事务回滚原理图
两阶段提交采用的是悲观锁策略,由于各个事务参与者需要等待响应最慢的参与者,因此性能比较差。第一个问题是协议本身的成本:整个协议过程是需要加
锁的,比如锁住数据库的某条记录,且需要持久化大量事务状态相关的操作日志。更为麻烦的是,两阶段锁在出现故障时表现出来的脆弱性,比如两阶段锁的致命缺
陷:当协调者出现故障,整个事务需要等到协调者恢复后才能继续执行,如果协调者出现类似磁盘故障等错误,该事务将被永久遗弃。
对于分布式服务框架而言,从功能特性上需要支持分布式事务。在实际业务使用过程中,如果能够通过最终一致性解决问题,则不需要做强一致性;如果能够避免分布式事务,则尽量在业务层避免使用分布式事务。
2.2分布式事务优化
既然分布式事务有诸多缺点,那么为什么我们还在使用呢?有没有更好的解决方案来改进或者替换呢?如果我们只是针对分布式事务去优化的话,发现其实能改进的空间很小,毕竟瓶颈在分布式事务模型本身。
那我们回到问题的根源:为什么我们需要分布式事务?因为我们需要各个资源数据保持一致性,但是对于分布式事务提供的强一致性,所有业务场景真的都需
要吗?大多数业务场景都能容忍短暂的不一致,不同的业务对不一致的容忍时间不同。像银行转账业务,中间有几分钟的不一致时间,用户通常都是可以理解和容忍
的。
在大多数的业务场景中,我们可以使用最终一致性替代传统的强一致性,尽量避免使用分布式事务。
在实践中常用的最终一致性方案就是使用带有事务功能的MQ做中间人角色,它的工作原理如下:在做本地事务之前,先向MQ发送一个prepare消
息,然后执行本地事务,本地事务提交成功的话,向MQ发送一个commit消息,否则发送一个rollback消息,取消之前的消息。MQ只会在收到
commit确认才会将消息投递出去,所以这样的形式可以保证在一切正常的情况下,本地事务和MQ可以达到一致性。但是分布式调用存在很多异常场景,诸如
网络超时、VM宕机等。假如系统执行了local_tx()成功之后,还没来得及将commit消息发送给MQ,或者说发送出去由于网络超时等原因,MQ
没有收到commit,发生了commit消息丢失,那么MQ就不会把prepare消息投递出去。MQ会根据策略去尝试询问(回调)发消息的系统
(checkCommit)进行检查该消息是否应该投递出去或者丢弃,得到系统的确认之后,MQ会做投递还是丢弃,这样就完全保证了MQ和发消息的系统的
一致性,从而保证了接收消息系统的一致性。
3. 研发团队协作问题
服务化之后,特别是采用微服务架构以后。研发团队会被拆分成多个服务化小组,例如AWS的Two Pizza Team,每个团队由2~3名研发负责服务的开发、测试、部署上线、运维和运营等。
随着服务数的膨胀,研发团队的增多,跨团队的协同配合将会成为一个制约研发效率提升的因素。
3.1共用服务注册中心
为了方便开发测试,经常会在线下共用一个所有服务共享的服务注册中心,这时,一个正在开发中的服务发布到服务注册中心,可能会导致一些消费者不可用。
解决方案:可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其他服务),而不注册正在开发的服务,通过直连测试正在开发的服务。
它的工作原理如图3-1所示。
图3-1只订阅,不发布
3.2直连提供者
在开发和测试环境下,如果公共的服务注册中心没有搭建,消费者将无法获取服务提供者的地址列表,只能做本地单元测试或使用模拟桩测试。
还有一种场景就是在实际测试中,服务提供者往往多实例部署,如果服务提供者存在Bug,就需要做远程断点调试,这会带来两个问题:
1) 服务提供者多实例部署,远程调试地址无法确定,调试效率低下。
2) 多个消费者可能共用一套测试联调环境,断点调试过程中可能被其他消费者意外打断。
解决策略:绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式将以服务接口为单位,忽略注册中心的提供者列表。
3.3多团队进度协同
假如前端Web门户依赖后台A、B、C和D
4个服务,分别由4个不同的研发团队负责,门户要求新特性2周内上线。A和B内部需求优先级排序将门户的优先级排的比较高,可以满足交付时间点。但是C和
D服务所在团队由于同时需要开发其他优先级更高的服务,因此把优先级排的相对较低,无法满足2周交付。
在C和D提供版本之前,门户只能先通过打测试桩的方式完成Mock测试,但是由于并没有真实的测试过C和D服务,因此需求无法按期交付。
应用依赖的服务越多,特性交付效率就越低下,交付的速度取决于依赖的最迟交付的那个服务。假如Web门户依赖后台的100个服务,只要1个核心服务没有按期交付,则整个进度就会延迟。
解决方案:调用链可以将应用、服务和中间件之间的依赖关系串接并展示出来,基于调用链首入口的交付日期作为输入,利用依赖管理工具,可以自动计算出调用链上各个服务的最迟交付时间点。通过调用链分析和标准化的依赖计算工具,可以避免人为需求排序失误导致的需求延期。
3.4服务降级和Mock测试
在实际项目开发中,由于小组之间、个人开发者之间开发节奏不一致,经常会出现消费者等待依赖的服务提供者提供联调版本的情况,相互等待会降低项目的研发进度。
解决方案:服务提供者首先将接口定下来并提供给消费者,消费者可以将服务降级同Mock测试结合起来,在Mock测试代码中实现容错降级的业务逻辑(业务放通),这样既完成了Mock测试,又实现了服务降级的业务逻辑开发,一举两得。
3.5协同调试问题
在实际项目开发过程中,各研发团队进度不一致很正常。如果消费者坐等服务提供者按时提供版本,往往会造成人力资源浪费,影响项目进度。
解决方案:分布式服务框架提供Mock桩管理框架,当周边服务提供者尚未完成开发时,将路由切换到模拟测试模式,自动调用Mock桩;业务集成测试和上线时,则要能够自动切换到真实的服务提供者上,可以结合服务降级功能实现。
3.6接口前向兼容性
由于线上的Bug修复、内部重构和需求变更,服务提供者会经常修改内部实现,包括但不限于:接口参数变化、参数字段变化、业务逻辑变化和数据表结构变化。
在实际项目中经常会发生服务提供者修改了接口或者数据结构,但是并没有及时知会到所有消费者,导致服务调用失败。
解决方案:
1) 制定并严格执行《服务前向兼容性规范》,避免发生不兼容修改或者私自修改不通知周边的情况。
2) 接口兼容性技术保障:例如Thrift的IDL,支持新增、修改和删除字段,字段定义位置无关性,码流支持乱序等。
4. 总结
服务化之后,无论是服务化框架,还是业务服务,都面临诸多挑战,本章摘取了其中一些比较重要的问题,并给出解决方案和最佳实践。对于本章节没有列出的问题,则需要服务框架开发者和使用者在实践中探索,找出一条适合自己产品的服务化最佳实践。
④ golang生成的json是格式化后的,有没有提供方法压缩一下
那些空格换行也占用不了多少空间,
要压缩可以自己写个正则,
把那些空格、换行去掉就行了。
⑤ golang生成的json是格式化后的,有没有提供方法压缩一下
golang生成的json是格式化后的,有没有提供方法压缩一下
那些空格换行也占用不了多少空间, 要压缩可以自己写个正则, 把那些空格、换行去掉就行了。
⑥ 求救,分布式事务怎么处理
1.性能和时延问题在服务化之前,业务通常都是本地API调用,本地方法调用性能损耗较小。服务化之后,服务提供者和消费者之间采用远程网络通信,增加了额外的性能损耗:1)客户端需要对消息进行序列化,主要占用CPU计算资源。2)序列化时需要创建二进制数组,耗费JVM堆内存或者堆外内存。3)客户端需要将序列化之后的二进制数组发送给服务端,占用网络带宽资源。4)服务端读取到码流之后,需要将请求数据报反序列化成请求对象,占用CPU计算资源。5)服务端通过反射的方式调用服务提供者实现类,反射本身对性能影响就比较大。6)服务端将响应结果序列化,占用CPU计算资源。7)服务端将应答码流发送给客户端,占用网络带宽资源。8)客户端读取应答码流,反序列化成响应消息,占用CPU资源。通过分析我们发现,一个简单的本地方法调用,切换成远程服务调用之后,额外增加了很多处理流程,不仅占用大量的系统资源,同时增加了时延。一些复杂的应用会拆分成多个服务,形成服务调用链,如果服务化框架的性能比较差、服务调用时延也比较大,业务服务化之后的性能和时延将无法满足业务的性能需求。1.1RPC框架高性能设计影响RPC框架性能的主要因素有三个。1)I/O调度模型:同步阻塞I/O(BIO)还是非阻塞I/O(NIO)。2)序列化框架的选择:文本协议、二进制协议或压缩二进制协议。3)线程调度模型:串行调度还是并行调度,锁竞争还是无锁化算法。1.I/O调度模型在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。JDK1.5_update10版本使用epoll替代了传统的select/poll,极大地提升了NIO通信的性能,它的工作原理如图1-1所示。图1-1非阻塞I/O工作原理Netty是一个开源的高性能NIO通信框架:它的I/O线程NioEventLoop由于聚合了多路复用器Selector,可以同时并发处理成百上千个客户端Channel。由于读写操作都是非阻塞的,这就可以充分提升I/O线程的运行效率,避免由于频繁I/O阻塞导致的线程挂起。另外,由于Netty采用了异步通信模式,一个I/O线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。Netty被精心设计,提供了很多独特的性能提升特性,使它做到了在各种NIO框架中性能排名第一,它的性能优化措施总结如下。1)零拷贝:(1)Netty的接收和发送ByteBuffer采用DIRECTBUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAPBUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。(2)Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便地对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。(3)Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。2)内存池:随着JVM虚拟机和JIT即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓冲区Buffer,情况却稍有不同,特别是对于堆外直接内存的分配和回收,是一件耗时的操作。为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制。性能测试表明,采用内存池的ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右(性能数据与使用场景强相关)。3)无锁化的串行设计:在大多数场景下,并行多线程处理可以提升系统的并发性能。但是,如果对于共享资源的并发访问处理不当,会带来严重的锁竞争,这最终会导致性能的下降。为了尽可能地避免锁竞争带来的性能损耗,可以通过串行化设计,即消息的处理尽可能在同一个线程内完成,期间不进行线程切换,这样就避免了多线程竞争和同步锁。为了尽可能提升性能,Netty采用了串行无锁化设计,在I/O线程内部进行串行操作,避免多线程竞争导致的性能下降。表面上看,串行化设计似乎CPU利用率不高,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队列-多个工作线程模型性能更优。4)高效的并发编程:volatile的大量、正确使用;CAS和原子类的广泛使用;线程安全容器的使用;通过读写锁提升并发性能。2.高性能序列化框架影响序列化性能的关键因素总结如下。1)序列化后的码流大小(网络带宽的占用)。2)序列化&反序列化的性能(CPU资源占用)。3)是否支持跨语言(异构系统的对接和开发语言切换)。4)并发调用的性能表现:稳定性、线性增长、偶现的时延毛刺等。相比于JSON等文本协议,二进制序列化框架性能更优异,以Java原生序列化和Protobuf二进制序列化为例进行性能测试对比,结果如图1-2所示。图1-2序列化性能测试对比数据在序列化框架的技术选型中,如无特殊要求,尽量选择性能更优的二进制序列化框架,码流是否压缩,则需要根据通信内容做灵活选择,对于图片、音频、有大量重复内容的文本文件(例如小说)可以采用码流压缩,常用的压缩算法包括GZip、Zig-Zag等。3.高性能的Reactor线程模型该模型的特点总结如下。1)有专门一个NIO线程:Acceptor线程用于监听服务端,接收客户端的TCP连接请求。2)网络I/O操作:读、写等由一个NIO线程池负责,线程池可以采用标准的JDK线程池实现,它包含一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送。3)1个NIO线程可以同时处理N条链路,但是1个链路只对应1个NIO线程,防止产生并发操作。由于Reactor模式使用的是异步非阻塞I/O,所有的I/O操作都不会导致阻塞,理论上一个线程可以独立处理所有I/O相关的操作,因此在绝大多数场景下,Reactor多线程模型都可以完全满足业务性能需求。Reactor线程调度模型的工作原理示意如图1-3所示。图1-3高性能的Reactor线程调度模型1.2业务最佳实践要保证高性能,单依靠分布式服务框架是不够的,还需要应用的配合,应用服务化高性能实践总结如下:1)能异步的尽可能使用异步或者并行服务调用,提升服务的吞吐量,有效降低服务调用时延。2)无论是NIO通信框架的线程池还是后端业务线程池,线程参数的配置必须合理。如果采用JDK默认的线程池,最大线程数建议不超过20个。因为JDK的线程池默认采用N个线程争用1个同步阻塞队列方式,当线程数过大时,会导致激烈的锁竞争,此时性能不仅不会提升,反而会下降。3)尽量减小要传输的码流大小,提升性能。本地调用时,由于在同一块堆内存中访问,参数大小对性能没有任何影响。跨进程通信时,往往传递的是个复杂对象,如果明确对方只使用其中的某几个字段或者某个对象引用,则不要把整个复杂对象都传递过去。举例,对象A持有8个基本类型的字段,2个复杂对象B和C。如果明确服务提供者只需要用到A聚合的C对象,则请求参数应该是C,而不是整个对象A。4)设置合适的客户端超时时间,防止业务高峰期因为服务端响应慢导致业务线程等应答时被阻塞,进而引起后续其他服务的消息在队列中排队,造成故障扩散。5)对于重要的服务,可以单独部署到独立的服务线程池中,与其他非核心服务做隔离,保障核心服务的高效运行。6)利用Docker等轻量级OS容器部署服务,对服务做物理资源层隔离,避免虚拟化之后导致的超过20%的性能损耗。7)设置合理的服务调度优先级,并根据线上性能监控数据做实时调整。2.事务一致性问题服务化之前,业务采用本地事务,多个本地SQL调用可以用一个大的事务块封装起来,如果某一个数据库操作发生异常,就可以将之前的SQL操作进行回滚,只有所有SQL操作全部成功,才最终提交,这就保证了事务强一致性,如图2-1所示。服务化之后,三个数据库操作可能被拆分到独立的三个数据库访问服务中,此时原来的本地SQL调用演变成了远程服务调用,事务一致性无法得到保证,如图2-2所示。图2-2服务化之后引入分布式事务问题假如服务A和服务B调用成功,则A和B的SQL将会被提交,最后执行服务C,它的SQL操作失败,对于应用1消费者而言,服务A和服务B的相关SQL操作已经提交,服务C发生了回滚,这就导致事务不一致。从图2-2可以得知,服务化之后事务不一致主要是由服务分布式部署导致的,因此也被称为分布式事务问题。2.1分布式事务设计方案通常,分布式事务基于两阶段提交实现,它的工作原理示意图如图2-3所示。图2-3两阶段提交原理图阶段1:全局事务管理器向所有事务参与者发送准备请求;事务参与者向全局事务管理器回复自己是否准备就绪。阶段2:全局事务管理器接收到所有事务参与者的回复之后做判断,如果所有事务参与者都可以提交,则向所有事务提交者发送提交申请,否则进行回滚。事务参与者根据全局事务管理器的指令进行提交或者回滚操作。分布式事务回滚原理图如图2-4所示。图2-4分布式事务回滚原理图两阶段提交采用的是悲观锁策略,由于各个事务参与者需要等待响应最慢的参与者,因此性能比较差。第一个问题是协议本身的成本:整个协议过程是需要加锁的,比如锁住数据库的某条记录,且需要持久化大量事务状态相关的操作日志。更为麻烦的是,两阶段锁在出现故障时表现出来的脆弱性,比如两阶段锁的致命缺陷:当协调者出现故障,整个事务需要等到协调者恢复后才能继续执行,如果协调者出现类似磁盘故障等错误,该事务将被永久遗弃。对于分布式服务框架而言,从功能特性上需要支持分布式事务。在实际业务使用过程中,如果能够通过最终一致性解决问题,则不需要做强一致性;如果能够避免分布式事务,则尽量在业务层避免使用分布式事务。2.2分布式事务优化既然分布式事务有诸多缺点,那么为什么我们还在使用呢?有没有更好的解决方案来改进或者替换呢?如果我们只是针对分布式事务去优化的话,发现其实能改进的空间很小,毕竟瓶颈在分布式事务模型本身。那我们回到问题的根源:为什么我们需要分布式事务?因为我们需要各个资源数据保持一致性,但是对于分布式事务提供的强一致性,所有业务场景真的都需要吗?大多数业务场景都能容忍短暂的不一致,不同的业务对不一致的容忍时间不同。像银行转账业务,中间有几分钟的不一致时间,用户通常都是可以理解和容忍的。在大多数的业务场景中,我们可以使用最终一致性替代传统的强一致性,尽量避免使用分布式事务。在实践中常用的最终一致性方案就是使用带有事务功能的MQ做中间人角色,它的工作原理如下:在做本地事务之前,先向MQ发送一个prepare消息,然后执行本地事务,本地事务提交成功的话,向MQ发送一个commit消息,否则发送一个rollback消息,取消之前的消息。MQ只会在收到commit确认才会将消息投递出去,所以这样的形式可以保证在一切正常的情况下,本地事务和MQ可以达到一致性。但是分布式调用存在很多异常场景,诸如网络超时、VM宕机等。假如系统执行了local_tx()成功之后,还没来得及将commit消息发送给MQ,或者说发送出去由于网络超时等原因,MQ没有收到commit,发生了commit消息丢失,那么MQ就不会把prepare消息投递出去。MQ会根据策略去尝试询问(回调)发消息的系统(checkCommit)进行检查该消息是否应该投递出去或者丢弃,得到系统的确认之后,MQ会做投递还是丢弃,这样就完全保证了MQ和发消息的系统的一致性,从而保证了接收消息系统的一致性。3.研发团队协作问题服务化之后,特别是采用微服务架构以后。研发团队会被拆分成多个服务化小组,例如AWS的TwoPizzaTeam,每个团队由2~3名研发负责服务的开发、测试、部署上线、运维和运营等。随着服务数的膨胀,研发团队的增多,跨团队的协同配合将会成为一个制约研发效率提升的因素。3.1共用服务注册中心为了方便开发测试,经常会在线下共用一个所有服务共享的服务注册中心,这时,一个正在开发中的服务发布到服务注册中心,可能会导致一些消费者不可用。解决方案:可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其他服务),而不注册正在开发的服务,通过直连测试正在开发的服务。它的工作原理如图3-1所示。图3-1只订阅,不发布3.2直连提供者在开发和测试环境下,如果公共的服务注册中心没有搭建,消费者将无法获取服务提供者的地址列表,只能做本地单元测试或使用模拟桩测试。还有一种场景就是在实际测试中,服务提供者往往多实例部署,如果服务提供者存在Bug,就需要做远程断点调试,这会带来两个问题:1)服务提供者多实例部署,远程调试地址无法确定,调试效率低下。2)多个消费者可能共用一套测试联调环境,断点调试过程中可能被其他消费者意外打断。解决策略:绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式将以服务接口为单位,忽略注册中心的提供者列表。3.3多团队进度协同假如前端Web门户依赖后台A、B、C和D4个服务,分别由4个不同的研发团队负责,门户要求新特性2周内上线。A和B内部需求优先级排序将门户的优先级排的比较高,可以满足交付时间点。但是C和D服务所在团队由于同时需要开发其他优先级更高的服务,因此把优先级排的相对较低,无法满足2周交付。在C和D提供版本之前,门户只能先通过打测试桩的方式完成Mock测试,但是由于并没有真实的测试过C和D服务,因此需求无法按期交付。应用依赖的服务越多,特性交付效率就越低下,交付的速度取决于依赖的最迟交付的那个服务。假如Web门户依赖后台的100个服务,只要1个核心服务没有按期交付,则整个进度就会延迟。解决方案:调用链可以将应用、服务和中间件之间的依赖关系串接并展示出来,基于调用链首入口的交付日期作为输入,利用依赖管理工具,可以自动计算出调用链上各个服务的最迟交付时间点。通过调用链分析和标准化的依赖计算工具,可以避免人为需求排序失误导致的需求延期。3.4服务降级和Mock测试在实际项目开发中,由于小组之间、个人开发者之间开发节奏不一致,经常会出现消费者等待依赖的服务提供者提供联调版本的情况,相互等待会降低项目的研发进度。解决方案:服务提供者首先将接口定下来并提供给消费者,消费者可以将服务降级同Mock测试结合起来,在Mock测试代码中实现容错降级的业务逻辑(业务放通),这样既完成了Mock测试,又实现了服务降级的业务逻辑开发,一举两得。3.5协同调试问题在实际项目开发过程中,各研发团队进度不一致很正常。如果消费者坐等服务提供者按时提供版本,往往会造成人力资源浪费,影响项目进度。解决方案:分布式服务框架提供Mock桩管理框架,当周边服务提供者尚未完成开发时,将路由切换到模拟测试模式,自动调用Mock桩;业务集成测试和上线时,则要能够自动切换到真实的服务提供者上,可以结合服务降级功能实现。3.6接口前向兼容性由于线上的Bug修复、内部重构和需求变更,服务提供者会经常修改内部实现,包括但不限于:接口参数变化、参数字段变化、业务逻辑变化和数据表结构变化。在实际项目中经常会发生服务提供者修改了接口或者数据结构,但是并没有及时知会到所有消费者,导致服务调用失败。解决方案:1)制定并严格执行《服务前向兼容性规范》,避免发生不兼容修改或者私自修改不通知周边的情况。2)接口兼容性技术保障:例如Thrift的IDL,支持新增、修改和删除字段,字段定义位置无关性,码流支持乱序等。4.总结服务化之后,无论是服务化框架,还是业务服务,都面临诸多挑战,本章摘取了其中一些比较重要的问题,并给出解决方案和最佳实践。对于本章节没有列出的问题,则需要服务框架开发者和使用者在实践中探索,找出一条适合自己产品的服务化最佳实践。
⑦ 针对android的性能优化集中哪些方面
一、概要:
本文主要以Android的渲染机制、UI优化、多线程的处理、缓存处理、电量优化以及代码规范等几方面来简述Android的性能优化
二、渲染机制的优化:
大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染, 如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。
*关于JobScheler的更多知识可以参考http://hukai.me/android-training-course-in-chinese/background-jobs/scheling/index.html
七、代码规范
1)for loop中不要声明临时变量,不到万不得已不要在里面写try catch。
2)明白垃圾回收机制,避免频繁GC,内存泄漏,OOM(有机会专门说)
3)合理使用数据类型,StringBuilder代替String,少用枚举enum,少用父类声明(List,Map)
4)如果你有频繁的new线程,那最好通过线程池去execute它们,减少线程创建开销。
5)你要知道单例的好处,并正确的使用它。
6)多用常量,少用显式的"action_key",并维护一个常量类,别重复声明这些常量。
7)如果可以,至少要弄懂设计模式中的策略模式,组合模式,装饰模式,工厂模式,观察者模式,这些能帮助你合理的解耦,即使需求频繁变更,你也不用害怕牵一发而动全身。需求变更不可怕,可怕的是没有在写代码之前做合理的设计。
8)View中设置缓存属性.setDrawingCache为true.
9)cursor的使用。不过要注意管理好cursor,不要每次打开关闭cursor.因为打开关闭Cursor非常耗时。Cursor.require用于刷cursor.
10)采用SurfaceView在子线程刷新UI,避免手势的处理和绘制在同一UI线程(普通View都这样做)
11)采用JNI,将耗时间的处理放到c/c++层来处理
12)有些能用文件操作的,尽量采用文件操作,文件操作的速度比数据库的操作要快10倍左右
13)懒加载和缓存机制。访问网络的耗时操作启动一个新线程来做,而不要再UI线程来做
14)如果方法用不到成员变量,可以把方法申明为static,性能会提高到15%到20%
15)避免使用getter/setter存取field,可以把field申明为public,直接访问
16)私有内部类要访问外部类的field或方法时,其成员变量不要用private,因为在编译时会生成setter/getter,影响性能。可以把外部类的field或方法声明为包访问权限
17)合理利用浮点数,浮点数比整型慢两倍
18)针对ListView的性能优化,ListView的背景色与cacheColorHint设置相同颜色,可以提高滑动时的渲染性能。ListView中getView是性能是关键,这里要尽可能的优化。
getView方法中要重用view;getView方法中不能做复杂的逻辑计算,特别是数据库操作,否则会严重影响滑动时的性能
19)不用new关键词创建类的实例,用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。
clone()方法不会调用任何类构造函数。在使用设计模式(Design Pattern)的场合,如果用Factory模式创建对象,则改用clone()方法创建新的对象实例非常简单。例如,下面是Factory模式的一个典型实现:
20)public static Credit getNewCredit() {
return new Credit();
}
改进后的代码使用clone()方法,如下所示:
private static Credit BaseCredit = new Credit();
public static Credit getNewCredit() {
return (Credit) BaseCredit.clone();
}
上面的思路对于数组处理同样很有用。
21)乘法和除法
考虑下面的代码:
for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; }
用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码:
for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; }
22)ViewPager同时缓存page数最好为最小值3,如果过多,那么第一次显示时,ViewPager所初始化的pager就会很多,这样pager累积渲染耗时就会增多,看起来就卡。
23)每个pager应该只在显示时才加载网络或数据库(UserVisibleHint=true),最好不要预加载数据,以免造成浪费
24)提高下载速度:要控制好同时下载的最大任务数,同时给InputStream再包一层缓冲流会更快(如BufferedInputStream)
25)提供加载速度:让服务端提供不同分辨率的图片才是最好的解决方案。还有合理使用内存缓存,使用开源的框架
引用:Android性能优化的浅谈
⑧ golang生成的json是格式化后的,有没有提供方法压缩一下
innodb_data_home_dir = /longxibendi/mysql/mysql/var/
#innodb_data_file_path = ibdata1:1G:autoextend
innodb_data_file_path = ibdata1:500M;ibdata2:2210M:autoextend #表空间
innodb_file_io_threads = 4 #io线程数
⑨ 如何打造高性能大数据分析平台
1.大数据是什么?
大数据是最近IT界最常用的术语之一。然而对大数据的定义也不尽相同,所有已知的论点例如结构化的和非结构化、大规模的数据等等都不够完整。大数据系统通常被认为具有数据的五个主要特征,通常称为数据的5 Vs。分别是大规模,多样性,高效性、准确性和价值性。
据Gartner称,大规模可以被定义为“在本(地)机数据采集和处理技术能力不足以为用户带来商业价值。当现有的技术能够针对性的进行改造后来处理这种规模的数据就可以说是一个成功的大数据解决方案。
这种大规模的数据没将不仅仅是来自于现有的数据源,同时也会来自于一些新兴的数据源,例如常规(手持、工业)设备,日志,汽车等,当然包括结构化的和非结构化的数据。
据Gartner称,多样性可以定义如下:“高度变异的信息资产,在生产和消费时不进行严格定义的包括多种形式、类型和结构的组合。同时还包括以前的历史数据,由于技术的变革历史数据同样也成为多样性数据之一 “。
高效性可以被定义为来自不同源的数据到达的速度。从各种设备,传感器和其他有组织和无组织的数据流都在不断进入IT系统。由此,实时分析和对于该数据的解释(展示)的能力也应该随之增加。
根据Gartner,高效性可以被定义如下:“高速的数据流I/O(生产和消费),但主要聚焦在一个数据集内或多个数据集之间的数据生产的速率可变上”。
准确性,或真实性或叫做精度是数据的另一个重要组成方面。要做出正确的商业决策,当务之急是在数据上进行的所有分析必须是正确和准确(精确)的。
大数据系统可以提供巨大的商业价值。像电信,金融,电子商务,社交媒体等,已经认识到他们的数据是一个潜在的巨大的商机。他们可以预测用户行为,并推荐相关产品,提供危险交易预警服务,等等。
与其他IT系统一样,性能是大数据系统获得成功的关键。本文的中心主旨是要说明如何让大数据系统保证其性能。
2.大数据系统应包含的功能模块
大数据系统应该包含的功能模块,首先是能够从多种数据源获取数据的功能,数据的预处理(例如,清洗,验证等),存储数据,数据处理、数据分析等(例如做预测分析,生成在线使用建议等等),最后呈现和可视化的总结、汇总结果。
下图描述了大数据系统的这些高层次的组件:
2.1各种各样的数据源
当今的IT生态系统,需要对各种不同种类来源的数据进行分析。这些来源可能是从在线Web应用程序,批量上传或feed,流媒体直播数据,来自工业、手持、家居传感的任何东西等等。
显然从不同数据源获取的数据具有不同的格式、使用不同的协议。例如,在线的Web应用程序可能会使用SOAP / XML格式通过HTTP发送数据,feed可能会来自于CSV文件,其他设备则可能使用MQTT通信协议。
由于这些单独的系统的性能是不在大数据系统的控制范围之内,并且通常这些系统都是外部应用程序,由第三方供应商或团队提供并维护,所以本文将不会在深入到这些系统的性能分析中去。
2.2数据采集
第一步,获取数据。这个过程包括分析,验证,清洗,转换,去重,然后存到适合你们公司的一个持久化设备中(硬盘、存储、云等)。
在下面的章节中,本文将重点介绍一些关于如何获取数据方面的非常重要的技巧。请注意,本文将不讨论各种数据采集技术的优缺点。
2.3存储数据
第二步,一旦数据进入大数据系统,清洗,并转化为所需格式时,这些过程都将在数据存储到一个合适的持久化层中进行。
在下面的章节中,本文将介绍一些存储方面的最佳实践(包括逻辑上和物理上)。在本文结尾也会讨论一部分涉及数据安全方面的问题。
2.4数据处理和分析
第三步,在这一阶段中的一部分干净数据是去规范化的,包括对一些相关的数据集的数据进行一些排序,在规定的时间间隔内进行数据结果归集,执行机器学习算法,预测分析等。
在下面的章节中,本文将针对大数据系统性能优化介绍一些进行数据处理和分析的最佳实践。
2.5数据的可视化和数据展示
最后一个步骤,展示经过各个不同分析算法处理过的数据结果。该步骤包括从预先计算汇总的结果(或其他类似数据集)中的读取和用一种友好界面或者表格(图表等等)的形式展示出来。这样便于对于数据分析结果的理解。
3.数据采集中的性能技巧
数据采集是各种来自不同数据源的数据进入大数据系统的第一步。这个步骤的性能将会直接决定在一个给定的时间段内大数据系统能够处理的数据量的能力。
数据采集过程基于对该系统的个性化需求,但一些常用执行的步骤是 – 解析传入数据,做必要的验证,数据清晰,例如数据去重,转换格式,并将其存储到某种持久层。
涉及数据采集过程的逻辑步骤示如下图所示:
下面是一些性能方面的技巧:
●来自不同数据源的传输应该是异步的。可以使用文件来传输、或者使用面向消息的(MoM)中间件来实现。由于数据异步传输,所以数据采集过程的吞吐量可以大大高于大数据系统的处理能力。 异步数据传输同样可以在大数据系统和不同的数据源之间进行解耦。大数据基础架构设计使得其很容易进行动态伸缩,数据采集的峰值流量对于大数据系统来说算是安全的。
●如果数据是直接从一些外部数据库中抽取的,确保拉取数据是使用批量的方式。
●如果数据是从feed file解析,请务必使用合适的解析器。例如,如果从一个XML文件中读取也有不同的解析器像JDOM,SAX,DOM等。类似地,对于CSV,JSON和其它这样的格式,多个解析器和API是可供选择。选择能够符合需求的性能最好的。
●优先使用内置的验证解决方案。大多数解析/验证工作流程的通常运行在服务器环境(ESB /应用服务器)中。大部分的场景基本上都有现成的标准校验工具。在大多数的情况下,这些标准的现成的工具一般来说要比你自己开发的工具性能要好很多。
●类似地,如果数据XML格式的,优先使用XML(XSD)用于验证。
●即使解析器或者校等流程使用自定义的脚本来完成,例如使用java优先还是应该使用内置的函数库或者开发框架。在大多数的情况下通常会比你开发任何自定义代码快得多。
●尽量提前滤掉无效数据,以便后续的处理流程都不用在无效数据上浪费过多的计算能力。
●大多数系统处理无效数据的做法通常是存放在一个专门的表中,请在系统建设之初考虑这部分的数据库存储和其他额外的存储开销。
●如果来自数据源的数据需要清洗,例如去掉一些不需要的信息,尽量保持所有数据源的抽取程序版本一致,确保一次处理的是一个大批量的数据,而不是一条记录一条记录的来处理。一般来说数据清洗需要进行表关联。数据清洗中需要用到的静态数据关联一次,并且一次处理一个很大的批量就能够大幅提高数据处理效率。
●数据去重非常重要这个过程决定了主键的是由哪些字段构成。通常主键都是时间戳或者id等可以追加的类型。一般情况下,每条记录都可能根据主键进行索引来更新,所以最好能够让主键简单一些,以保证在更新的时候检索的性能。
●来自多个源接收的数据可以是不同的格式。有时,需要进行数据移植,使接收到的数据从多种格式转化成一种或一组标准格式。
●和解析过程一样,我们建议使用内置的工具,相比于你自己从零开发的工具性能会提高很多。
●数据移植的过程一般是数据处理过程中最复杂、最紧急、消耗资源最多的一步。因此,确保在这一过程中尽可能多的使用并行计算。
●一旦所有的数据采集的上述活动完成后,转换后的数据通常存储在某些持久层,以便以后分析处理,综述,聚合等使用。
●多种技术解决方案的存在是为了处理这种持久(RDBMS,NoSQL的分布式文件系统,如Hadoop和等)。
●谨慎选择一个能够最大限度的满足需求的解决方案。
4.数据存储中的性能技巧
一旦所有的数据采集步骤完成后,数据将进入持久层。
在本节中将讨论一些与数据数据存储性能相关的技巧包括物理存储优化和逻辑存储结构(数据模型)。这些技巧适用于所有的数据处理过程,无论是一些解析函数生的或最终输出的数据还是预计算的汇总数据等。
●首先选择数据范式。您对数据的建模方式对性能有直接的影响,例如像数据冗余,磁盘存储容量等方面。对于一些简单的文件导入数据库中的场景,你也许需要保持数据原始的格式,对于另外一些场景,如执行一些分析计算聚集等,你可能不需要将数据范式化。
●大多数的大数据系统使用NoSQL数据库替代RDBMS处理数据。
●不同的NoSQL数据库适用不同的场景,一部分在select时性能更好,有些是在插入或者更新性能更好。
●数据库分为行存储和列存储。
●具体的数据库选型依赖于你的具体需求(例如,你的应用程序的数据库读写比)。
●同样每个数据库都会根据不同的配置从而控制这些数据库用于数据库复制备份或者严格保持数据一致性。
●这些设置会直接影响数据库性能。在数据库技术选型前一定要注意。
●压缩率、缓冲池、超时的大小,和缓存的对于不同的NoSQL数据库来说配置都是不同的,同时对数据库性能的影响也是不一样的。
●数据Sharding和分区是这些数据库的另一个非常重要的功能。数据Sharding的方式能够对系统的性能产生巨大的影响,所以在数据Sharding和分区时请谨慎选择。
●并非所有的NoSQL数据库都内置了支持连接,排序,汇总,过滤器,索引等。
●如果有需要还是建议使用内置的类似功能,因为自己开发的还是不灵。
●NoSQLs内置了压缩、编解码器和数据移植工具。如果这些可以满足您的部分需求,那么优先选择使用这些内置的功能。这些工具可以执行各种各样的任务,如格式转换、压缩数据等,使用内置的工具不仅能够带来更好的性能还可以降低网络的使用率。
●许多NoSQL数据库支持多种类型的文件系统。其中包括本地文件系统,分布式文件系统,甚至基于云的存储解决方案。
●如果在交互式需求上有严格的要求,否则还是尽量尝试使用NoSQL本地(内置)文件系统(例如HBase 使用HDFS)。
●这是因为,如果使用一些外部文件系统/格式,则需要对数据进行相应的编解码/数据移植。它将在整个读/写过程中增加原本不必要的冗余处理。
●大数据系统的数据模型一般来说需要根据需求用例来综合设计。与此形成鲜明对比的是RDMBS数据建模技术基本都是设计成为一个通用的模型,用外键和表之间的关系用来描述数据实体与现实世界之间的交互。
●在硬件一级,本地RAID模式也许不太适用。请考虑使用SAN存储。
5.数据处理分析中的性能技巧
数据处理和分析是一个大数据系统的核心。像聚合,预测,聚集,和其它这样的逻辑操作都需要在这一步完成。
本节讨论一些数据处理性能方面的技巧。需要注意的是大数据系统架构有两个组成部分,实时数据流处理和批量数据处理。本节涵盖数据处理的各个方面。
●在细节评估和数据格式和模型后选择适当的数据处理框架。
●其中一些框架适用于批量数据处理,而另外一些适用于实时数据处理。
●同样一些框架使用内存模式,另外一些是基于磁盘io处理模式。
●有些框架擅长高度并行计算,这样能够大大提高数据效率。
●基于内存的框架性能明显优于基于磁盘io的框架,但是同时成本也可想而知。
●概括地说,当务之急是选择一个能够满足需求的框架。否则就有可能既无法满足功能需求也无法满足非功能需求,当然也包括性能需求。
●一些这些框架将数据划分成较小的块。这些小数据块由各个作业独立处理。协调器管理所有这些独立的子作业
●在数据分块是需要当心。
●该数据快越小,就会产生越多的作业,这样就会增加系统初始化作业和清理作业的负担。
●如果数据快太大,数据传输可能需要很长时间才能完成。这也可能导致资源利用不均衡,长时间在一台服务器上运行一个大作业,而其他服务器就会等待。
●不要忘了查看一个任务的作业总数。在必要时调整这个参数。
●最好实时监控数据块的传输。在本机机型io的效率会更高,这么做也会带来一个副作用就是需要将数据块的冗余参数提高(一般hadoop默认是3份)这样又会反作用使得系统性能下降。
●此外,实时数据流需要与批量数据处理的结果进行合并。设计系统时尽量减少对其他作业的影响。
●大多数情况下同一数据集需要经过多次计算。这种情况可能是由于数据抓取等初始步骤就有报错,或者某些业务流程发生变化,值得一提的是旧数据也是如此。设计系统时需要注意这个地方的容错。
●这意味着你可能需要存储原始数据的时间较长,因此需要更多的存储。
●数据结果输出后应该保存成用户期望看到的格式。例如,如果最终的结果是用户要求按照每周的时间序列汇总输出,那么你就要将结果以周为单位进行汇总保存。
●为了达到这个目标,大数据系统的数据库建模就要在满足用例的前提下进行。例如,大数据系统经常会输出一些结构化的数据表,这样在展示输出上就有很大的优势。
●更常见的是,这可能会这将会让用户感觉到性能问题。例如用户只需要上周的数据汇总结果,如果在数据规模较大的时候按照每周来汇总数据,这样就会大大降低数据处理能力。
●一些框架提供了大数据查询懒评价功能。在数据没有在其他地方被使用时效果不错。
●实时监控系统的性能,这样能够帮助你预估作业的完成时间。
6.数据可视化和展示中的性能技巧
精心设计的高性能大数据系统通过对数据的深入分析,能够提供有价值战略指导。这就是可视化的用武之地。良好的可视化帮助用户获取数据的多维度透视视图。
需要注意的是传统的BI和报告工具,或用于构建自定义报表系统无法大规模扩展满足大数据系统的可视化需求。同时,许多COTS可视化工具现已上市。
本文将不会对这些个别工具如何进行调节,而是聚焦在一些通用的技术,帮助您能打造可视化层。
●确保可视化层显示的数据都是从最后的汇总输出表中取得的数据。这些总结表可以根据时间短进行汇总,建议使用分类或者用例进行汇总。这么做可以避免直接从可视化层读取整个原始数据。
●这不仅最大限度地减少数据传输,而且当用户在线查看在报告时还有助于避免性能卡顿问题。
●重分利用大化可视化工具的缓存。缓存可以对可视化层的整体性能产生非常不错的影响。
●物化视图是可以提高性能的另一个重要的技术。
●大部分可视化工具允许通过增加线程数来提高请求响应的速度。如果资源足够、访问量较大那么这是提高系统性能的好办法。
●尽量提前将数据进行预处理,如果一些数据必须在运行时计算请将运行时计算简化到最小。
●可视化工具可以按照各种各样的展示方法对应不同的读取策略。其中一些是离线模式、提取模式或者在线连接模式。每种服务模式都是针对不同场景设计的。
●同样,一些工具可以进行增量数据同步。这最大限度地减少了数据传输,并将整个可视化过程固化下来。
●保持像图形,图表等使用最小的尺寸。
●大多数可视化框架和工具的使用可缩放矢量图形(SVG)。使用SVG复杂的布局可能会产生严重的性能影响。
7.数据安全以及对于性能的影响
像任何IT系统一样安全性要求也对大数据系统的性能有很大的影响。在本节中,我们讨论一下安全对大数据平台性能的影响。
– 首先确保所有的数据源都是经过认证的。即使所有的数据源都是安全的,并且没有针对安全方面的需求,那么你可以灵活设计一个安全模块来配置实现。
– 数据进过一次认证,那么就不要进行二次认证。如果实在需要进行二次认证,那么使用一些类似于token的技术保存下来以便后续继续使用。这将节省数据一遍遍认证的开销。
– 您可能需要支持其他的认证方式,例如基于PKI解决方案或Kerberos。每一个都有不同的性能指标,在最终方案确定前需要将其考虑进去。
– 通常情况下数据压缩后进入大数据处理系统。这么做好处非常明显不细说。
– 针对不同算法的效率、对cpu的使用量你需要进行比较来选出一个传输量、cpu使用量等方面均衡的压缩算法。
– 同样,评估加密逻辑和算法,然后再选择。
– 明智的做法是敏感信息始终进行限制。
– 在审计跟踪表或登录时您可能需要维护记录或类似的访问,更新等不同的活动记录。这可能需要根据不同的监管策略和用户需求个性化的进行设计和修改。
– 注意,这种需求不仅增加了数据处理的复杂度,但会增加存储成本。
– 尽量使用下层提供的安全技术,例如操作系统、数据库等。这些安全解决方案会比你自己设计开发性能要好很多。
8.总结
本文介绍了各种性能方面的技巧,这些技术性的知道可以作为打造大数据分析平台的一般准则。大数据分析平台非常复杂,为了满足这种类型系统的性能需求,需要我们从开始建设的时候进行考量。
本文介绍的技术准则可以用在大数据平台建设的各个不同阶段,包括安全如何影响大数据分析平台的性能。