华为云用户手册

  • 安装VNC Server 默认情况下,Ubuntu 20.04操作系统没有安装图形环境或VNC Server。本示例中,桌面环境使用Xfce,它是一个精简的轻量化桌面,与Gnome和KDE相比更小巧,并且界面美观、对用户友好,适合云服务器远程连接场景下使用。 远程登录云服务器。 账号:root;密码:您在创建云服务器时设置的密码。 执行以下命令,更新软件列表。 sudo apt update 安装Xfce桌面环境。 sudo apt install xfce4 xfce4-goodies 执行完成后,安装TightVNC服务器。 sudo apt install tightvncserver 执行完成后,使用vncserver命令进行配置。 当您第一次运行vncserver时,它会创建一个默认启动脚本。按照提示进行配置: 密码:长度为6~8个字符。超过8个字符的密码将自动截断。请牢记该密码,VNC Viewer连接云服务器时会使用。 验证密码:再次输入密码。 是否创建仅查看密码:使用仅查看密码登录的用户将无法使用鼠标或键盘控制云服务器。此处输入“n”。
  • 建站常见问题 使用弹性云服务器搭建网站过程中,由于各种原因可能会遇到一些问题,常见问题及处理方法如下: 服务器登录问题 云服务器登录前的准备工作有哪些? 无法登录到Windows云服务器怎么办? 无法登录到Linux云服务器怎么办? 更多登录类问题请参见弹性云服务器登录类常见问题。 安全组问题 变更安全组规则和网络ACL规则时,是否对原有流量实时生效? 弹性云服务器加入安全组过后能否变更安全组? 更多安全组问题请参见安全组常见问题。 网络类问题 弹性云服务器IP获取不到时,如何排查? EIP连接出现问题时,如何排查? 弹性云服务器的网卡绑定虚拟IP地址后,该虚拟IP地址无法ping通时,如何排查? 更多网络类问题请参见VPC常见问题。 操作系统问题 Windows云服务器带宽和CPU利用率高问题排查方法 Linux云服务器带宽和CPU占用率高问题排查方法 更多操作系统问题请参见操作系统类常见问题。 DNS常见问题 怎么测试 域名 解析是否生效 解析不生效有哪些原因 更多DNS问题请参见DNS常见问题。 其它常见问题 无法访问E CS 实例上运行的网站 云服务器端口不通怎样排查?
  • 自助建站 步骤 在华为云搭建一个网站,并实现在Internet上通过域名访问该网站,您需要完成以下几步: 准备服务器 准备服务器时,需要考虑服务器的CPU、内存、硬盘以及网络带宽等的配置。通常情况下,首先要满足运行网站相关软件的最低资源要求,其次需要结合网站的类型、规模以及访问量等相关因素进行相应的资源规划。 弹性云服务器的计费方式分为按需、包年/包月(按月、按年)、竞价3种,您可以根据业务的特点选择最合适的计费方式,详细的计费规则请参见计费模式概述。您也可以通过价格计算器了解不同规格配置的实例对应的价格。 如果已经有合适规格的实例,可以使用已有的实例直接部署网站。如果没有合适规格的实例,请先购买实例,详细操作请参见购买指引。 部署网站 根据需要部署的网站类型,可以选择镜像部署或者手工搭建,具体部署方法请参见搭建网站汇总。 购买域名 为了便于网站的访问和使用,可以给网站设置一个单独的域名,使用域名访问网站。如果已有可用的域名,可以直接认证使用,如果没有域名,需要先购买域名,具体操作请参见域名注册流程。 备案网站和域名 备案是中国大陆的一项法规,使用大陆节点服务器提供服务的网站,必须先办理备案,备案成功并获取通信管理局下发的ICP备案号后才能开通访问。 华为云提供免费的备案服务,具体操作请参见快速完成网站备案。 更多关于华为云备案的内容,请参考网站备案。 配置域名解析。 配置域名解析后才能使用注册的域名访问网站。具体操作请参见配置域名解析。 例如,配置的域名为“www.example.com”,配置成功后,可在浏览器地址栏中输入“http://www.example.com”访问部署的网站。
  • 建站方式 华为云当前支持自助建站,通过企业门户服务建站,使用云市场的模板建站和通过云市场进行网站定制四种方式,详细信息如表1所示。本页面重点介绍自助建站,通过企业门户服务建站请参考企业门户服务的帮助文档,其它建站方式请参考云市场服务提供商提供的使用指南。 表1 建站方式 建站方式 特点 适用场景 自助建站 部署时间长,过程复杂,需要自行购买服务器、搭建并维护网站,可以满足个性化的部署需求。 适用于有一定动手能力,有意愿自行设计和搭建个人或者小企业网站的用户;或者刚接触公有云,对建站不太了解,借助搭建个人或者小企业网站学习和了解公有云的用户。 企业门户 企业门户服务是一款帮助您搭建网站的华为云服务。提供多终端独立版和多终端自适应版两种建站规格,上千套免费模板任您挑选。无需代码,自由拖拽,快速生成中小企业网站及网店、微信网店等。 多终端独立版站点提供PC、手机、微信公众号、小程序、APP五站合一的模板建站产品,适用于贸易类企业的B2C交易类型网站和跨境官网电商等网站建设。多终端自适应版站点提供PC、手机、Pad三站合一的模板建站产品,适用于企业官网、个人博客、政府门户网站等网站的建设。 云市场模板建站 云市场中的模板是华为云合作伙伴提供的专业建站模板,可以通过云市场购买合适的模板,部署时间短,过程简单,后台管理方便,且有专人提供网站维护支持。 适用于需求简单,云市场模板可以满足需求的个人或者中小企业用户。有PC、手机、微信等多种渠道可选择,部署使用简单,成本较低。 云市场网站定制 华为云市场是一个云上的软件和服务商城,可以通过云市场获取 网站定制服务 ,专人服务,定制化开发,后台管理方便,且有专人提供网站维护支持。 适用于对网站有个性化需求,且预算充足的企业用户。提供一对一专业定制化开发,省心省力,同时节省企业自有人力。 Solution as Code一键式部署 为帮助企业高效上云,华为云Solution as Code萃取丰富上云成功实践,提供一系列基于华为云可快速部署的解决方案,帮助用户降低上云门槛。同时开放完整源码,支持个性化配置,解决方案开箱即用,所见即所得。 适用于跨境电商、运维监控、云上建站、开源自建、企业上云等场景。部署使用简单、成本较低。
  • 主机迁移服务(推荐) 服务简介 主机迁移服务(Server Migration Service)是一种P2V/V2V迁移服务,可以帮您把X86物理服务器,或者私有云、公有云平台上的虚拟机迁移到华为云弹性云服务器上,从而帮助您轻松地把服务器上的应用和数据迁移到华为云。 主机迁移服务支持迁移的源端服务器OS类型请参见兼容性列表。 使用主机迁移服务时,对于源端服务器的约束与限制请参见约束与限制。 图1 主机迁移服务工作原理 主机迁移服务的工作原理如下,其中第1步和第3步需要用户操作,其余步骤由主机迁移服务自动完成。 用户在源端服务器上安装迁移Agent,具体操作方法请您参见安装Agent。 源端服务器上的迁移Agent向主机迁移服务注册自身连接状态并将源端服务器信息上报到主机迁移服务,完成迁移可行性检查。 通过迁移可行性检查后,用户开始创建迁移任务,具体操作方法请您参见创建迁移任务。 迁移Agent获取并执行主机迁移服务发送的迁移指令。 开始迁移源端服务器系统盘。 开始迁移源端服务器数据盘。 源端:指迁移任务中的源端服务器。 目的端:指迁移任务中的目的端服务器。 服务端:指主机迁移服务。 服务入口
  • 新建外部链接 参考登录零代码工作台中操作,登录AstroZero零代码工作台。 在全部应用中,单击应用后的“...”,选择“编辑”,进入编辑应用页面。 在左侧导航栏中,单击“新建”,选择“新建外部链接”。 设置外部链接信息。 图1 新建外部链接 页面名称:设置页面名称。 URL:输入外部页面链接地址。 打开方式-新页面打开:勾选后,在新页面打开。 隐藏PC端:在PC端隐藏该外部链接。 隐藏移动端:在移动端隐藏该外部链接。 设置完成后,单击“确定”。 在左侧表单列表中,可查看到已新建的外部链接。单击该链接,可跳转到对应页面。 图2 外部链接地址 如果新建外部链接时,勾选了“隐藏PC端”,在应用查看页面,将无法查看到该外部链接。 图3 隐藏外部链接
  • 新建外部链接 参考登录AstroZero移动端零代码工作台中操作,登录AstroZero移动端零代码工作台。 在全部应用中,单击已创建的应用,进入应用。 在应用页面的右下方,单击。 在弹出的页面,单击,选择“编辑应用”。 图1 编辑应用 在导航设置页签,单击“新建”,选择“新建外部链接”。 图2 选择新建外部链接 设置外部链接信息。 图3 新建外部链接 设置完成后,单击“确定”。 在导航设置中,可查看到已新建的外部链接。单击该链接,可跳转到对应页面。 图4 外部链接地址
  • 建议 基于Flink的流式写入的表,在数据量超过2亿条记录,采用Bucket索引,2亿以内可以采用Flink状态索引。 参照Flink状态索引的特点,Hudi表超过一定数据量后,Flink作业状态后端压力很大,需要优化状态后端参数才能维持性能;同时由于Flink冷启动的时候需要遍历全表数据,大数据量也会导致Flink作业启动缓慢。因此基于简化使用的角度,针对大数据量的表,可以通过采用Bucket索引来避免状态后端的复杂调优。 如果Bucket索引+分区表的模式无法平衡Bueckt桶过大的问题,还是可以继续采用Flink状态索引,按照规范去优化对应的配置参数即可。 基于Bucket索引的表,按照单个Bucket 2GB数据量进行设计。 为了规避单个Bucket过大,建议单个Bucket的数据量不要超过2GB(该2GB是指数据内容大小,不是指数据行数也不是parquet的数据文件大小),目的是将对应的桶的Parquet文件大小控制在256MB范围内(平衡读写内存消耗和HDFS存储有效利用),因此可以看出2GB的这个限制只是一个经验值,因为不同的业务数据经过列存压缩后大小是不一样的。 为什么建议是2GB? 2GB的数据存储成列存Parquet文件后,大概的数据文件大小是150MB ~ 256MB左右。不同业务数据会有出入。而HDFS单个数据块一般会是128MB,这样可以有效的利用存储空间。 数据读写占用的内存空间都是原始数据大小(包括空值也是会占用内存的),2GB在大数据计算过程中,处于单task读写可接受范围之内。 如果是单个Bucket的数据量超过了该值范围,可能会有什么影响? 读写任务可能会出现OOM的问题,解决方法就是提升单个task的内存占比。 读写性能下降,因为单个task的处理的数据量变大,导致处理耗时变大。
  • 规则 禁止修改表索引类型。 Hudi表的索引会决定数据存储方式,随意修改索引类型会导致表中已有的存量数据与新增数据之间出现数据重复和数据准确性问题。常见的索引类型如下: 布隆索引:Spark引擎独有索引,采用bloomfiter机制,将布隆索引内容写入到Parquet文件的footer中。 Bucket索引:在写入数据过程中,通过主键进行Hash计算,将数据进行分桶写入;该索引写入速度最快,但是需要合理配置分桶数目;Flink、Spark均支持该索引写入。 状态索引:Flink引擎独有索引,是将行记录的存储位置记录到状态后端的一种索引形式,在作业冷启动过程中会遍历所有数据存储文件生成索引信息。 用Flink状态索引,Flink写入后,不支持Spark继续写入。 Flink在写Hudi的MOR表只会生成log文件,后续通过compaction操作,将log文件转为parquet文件。Spark在更新Hudi表时严重依赖parquet文件是否存在,如果当前Hudi表写的是log文件,采用Spark写入就会导致重复数据的产生。在批量初始化阶段 ,先采用Spark批量写入Hudi表,在用Flink基于Flink状态索引写入不会有问题,原因是Flink冷启动的时候会遍历所有的数据文件生成状态索引。 实时入湖场景中,Spark引擎采用Bucket索引,Flink引擎可以用Bucket索引或者状态索引。 实时入湖都是需要分钟内或者分钟级的高性能入湖,索引的选择会影响到写Hudi表的性能。在性能方面各个索引的区别如下: Bucket索引 优点:写入过程中对主键进行hash分桶写入,性能比较高,不受表的数据量限制。Flink和Spark引擎都支持,Flink和Spark引擎可以实现交叉混写同一张表。 缺点:Bucket个数不能动态调整,数据量波动和整表数据量持续上涨会导致单个Bucket数据量过大出现大数据文件。需要结合分区表来进行平衡改善。 Flink状态索引 优点:主键的索引信息存在状态后端,数据更新只需要点查状态后端即可,速度较快;同时生成的数据文件大小稳定,不会产生小文件、超大文件问题。 缺点:该索引为Flink特有索引。在表的总数据行数达到数亿级别,需要优化状态后端参数来保持写入的性能。使用该索引无法支持Flink和Spark交叉混写。 对于数据总量持续上涨的表,采用Bucket索引时,须使用时间分区,分区键采用数据创建时间。 参照Flink状态索引的特点,Hudi表超过一定数据量后,Flink作业状态后端压力很大,需要优化状态后端参数才能维持性能;同时由于Flink冷启动的时候需要遍历全表数据,大数据量也会导致Flink作业启动缓慢。因此基于简化使用的角度,针对大数据量的表,可以通过采用Bucket索引来避免状态后端的复杂调优。 如果Bucket索引+分区表的模式无法平衡Bueckt桶过大的问题,还是可以继续采用Flink状态索引,按照规范去优化对应的配置参数即可。
  • 在对性能要求比较高的场景下,可以使用Kryo优化序列化性能 Spark提供了两种序列化实现: org.apache.spark.serializer.KryoSerializer:性能好,兼容性差 org.apache.spark.serializer.JavaSerializer:性能一般,兼容性好 使用:conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") 为什么不默认使用Kryo序列化? Spark默认使用的是Java的序列化机制,也就是ObjectOutputStream/ObjectInputStream API来进行序列化和反序列化。但是Spark同时支持使用Kryo序列化库,Kryo序列化类库的性能比Java序列化类库的性能要高很多。官方介 绍,Kryo序列化机制比Java序列化机制,性能高10倍左右。Spark之所以默认没有使用Kryo作为序列化类库,是因为Kryo要求要注册所有需要进行序列化的自定义类型,因此对于开发者来说,这种方式比较麻烦。
  • RDD多次使用时,建议将RDD持久化 RDD在默认情况下的存储级别是StorageLevel.NONE,即既不存磁盘也不放在内存中,如果某个RDD需要多次使用,可以考虑将该RDD持久化,方法如下: 调用spark.RDD中的cache()、persist()、persist(newLevel:StorageLevel)函数均可将RDD持久化,cache()和persist()都是将RDD的存储级别设置为StorageLevel.MEMORY_ONLY,persist(newLevel:StorageLevel)可以为RDD设置其他存储级别,但是要求调用该方法之前RDD的存储级别为StorageLevel.NONE或者与newLevel相同,也就是说,RDD的存储级别一旦设置为StorageLevel.NONE之外的级别,则无法改变。 如果想要将RDD去持久化,那么可以调用unpersist(blocking:Boolean = true),该函数功能如下: 将该RDD从持久化列表中移除,RDD对应的数据进入可回收状态; 将RDD的存储级别重新设置为StorageLevel.NONE。
  • 在业务情况允许的情况下使用高性能算子 使用reduceByKey/aggregateByKey替代groupByKey。 所谓的map-side预聚合,说的是在每个节点本地对相同的key进行一次聚合操作,类似于MapReduce中的本地combiner。 map-side预聚合之后,每个节点本地就只会有一条相同的key,因为多条相同的key都被聚合起来了。其他节点在拉取所有节点上的相同key时,就会大大减少需要拉取的数据数量,从而也就减少了磁盘IO以及网络传输开销。通常来说,在可能的情况下,建议使用reduceByKey或aggregateByKey算子来替代掉groupByKey算子。因为reduceByKey和aggregateByKey算子都会使用用户自定义的函数对每个节点本地的相同key进行预聚合。而groupByKey算子是不会进行预聚合的,全量的数据会在集群的各个节点之间分发和传输,性能相对来说比较差。 使用mapPartitions替代普通map。 mapPartitions类的算子,一次函数调用会处理一个partition所有的数据,而不是一次函数调用处理一条,性能相对来说会高一些。 但是有的时候,使用mapPartitions会出现OOM(内存溢出)的问题。因为单次函数调用就要处理掉一个partition所有的数据,如果内存不够,垃圾回收时是无法回收掉太多对象的,很可能出现OOM异常。所以使用这类操作时要慎重! 使用filter之后进行coalesce操作。 通常对一个RDD执行filter算子过滤掉RDD中较多数据后(比如30%以上的数据),建议使用coalesce算子,手动减少RDD的partition数量,将RDD中的数据压缩到更少的partition中去。因为filter之后,RDD的每个partition中都会有很多数据被过滤掉,此时如果照常进行后续的计算,其实每个task处理的partition中的数据量并不是很多,有一点资源浪费,而且此时处理的task越多,可能速度反而越慢。因此用coalesce减少partition数量,将RDD中的数据压缩到更少的partition之后,只要使用更少的task即 可处理完所有的partition。在某些场景下,对于性能的提升会有一定的帮助。 使用repartitionAndSortWithinPartitions替代repartition与sort类操作。 repartitionAndSortWithinPartitions是Spark官网推荐的一个算子,官方建议,如果需要在 repartition重分区之后,还要进行排序,建议直接使用repartitionAndSortWithinPartitions 算子。因为该算子 可以一边进行重分区的shuffle操作,一边进行排序。shuffle与sort两个操作同时进行,比先shuffle再sort来说,性能可能是要高的。 使用foreachPartitions替代foreach。 原理类似于“使用mapPartitions替代map”,也是一次函数调用处理一个partition的所有数据,而不是一次函数调用处理一条数 据。在实践中发现,foreachPartitions类的算子,对性能的提升还是很有帮助的。比如在foreach函数中,将RDD中所有数据写 MySQL,那么如果是普通的foreach算子,就会一条数据一条数据地写,每次函数调用可能就会创建一个数据库连接,此时就势必会频繁地创建和销毁数据库连接,性能是非常低下;但是如果用foreachPartitions算子一次性处理一个partition的数据,那么对于每个 partition,只要创建一个数据库连接即可,然后执行批量插入操作,此时性能是比较高的。
  • Hive JDBC驱动的加载 客户端程序以JDBC的形式连接HiveServer时,需要首先加载Hive的JDBC驱动类org.apache.hive.jdbc.HiveDriver。 故在客户端程序的开始,必须先使用当前类加载器加载该驱动类。 如果classpath下没有相应的jar包,则客户端程序抛出Class Not Found异常并退出。 如下: Class.forName("org.apache.hive.jdbc.HiveDriver").newInstance();
  • 关闭数据库连接 客户端程序在执行完HQL之后,注意关闭数据库连接,以免内存泄露,同时这是一个良好的编程习惯。 需要关闭JDK的两个对象statement和connection。 如下: finally { if (null != statement) { statement.close(); } // 关闭JDBC连接 if (null != connection) { connection.close(); } }
  • 使用WebHCat的REST接口以Streaming方式提交MR任务的前置条件 本接口需要依赖hadoop的streaming包,在以Streaming方式提交MR任务给WebHCat前,需要将“hadoop-streaming-2.7.0.jar”包上传到HDFS的指定路径下:“hdfs:///apps/templeton/hadoop-streaming-2.7.0.jar”。首先登录到安装有客户端和Hive服务的节点上,以客户端安装路径为“/opt/client”为例: source /opt/client/bigdata_env 使用kinit登录人机用户或者机机用户。 hdfs dfs -put ${BIGDATA_HOME}/ FusionInsight _HD_8.1.0.1/FusionInsight-Hadoop-*/hadoop/share/hadoop/tools/lib/hadoop-streaming-*.jar /apps/templeton/ 其中/apps/templeton/需要根据不同的实例进行修改,默认实例使用/apps/templeton/,Hive1实例使用/apps1/templeton/,以此类推。
  • HQL语法规则之判空 判断字段是否为“空”,即没有值,使用“is null”;判断不为空,即有值,使用“is not null”。 要注意的是,在HQL中String类型的字段若是空字符串, 即长度为0,那么对它进行IS NULL的判断结果是False。此时应该使用“col = '' ”来判断空字符串;使用“col != '' ”来判断非空字符串。 正确示例: select * from default.tbl_src where id is null; select * from default.tbl_src where id is not null; select * from default.tbl_src where name = ''; select * from default.tbl_src where name != ''; 错误示例: select * from default.tbl_src where id = null; select * from default.tbl_src where id != null; select * from default.tbl_src where name is null; select * from default.tbl_src where name is not null; 注:表tbl_src的id字段为Int类型,name字段为String类型。
  • 客户端配置参数需要与服务端保持一致 当集群的Hive、YARN、HDFS服务端配置参数发生变化时,客户端程序对应的参数会被改变,用户需要重新审视在配置参数变更之前提交到HiveServer的配置参数是否和服务端配置参数一致,如果不一致,需要用户在客户端重新调整并提交到HiveServer。例如下面的示例中,如果修改了集群中的YARN配置参数时,Hive客户端、示例程序都需要审视并修改之前已经提交到HiveServer的配置参数: 初始状态: 集群YARN的参数配置如下: mapreduce.reduce.java.opts=-Xmx2048M 客户端的参数配置如下: mapreduce.reduce.java.opts=-Xmx2048M 集群YARN修改后,参数配置如下: mapreduce.reduce.java.opts=-Xmx1024M 如果此时客户端程序不做调整修改,则还是以客户端参数有效,会导致reducer内存不足而使MR运行失败。
  • 获取数据库连接 使用JDK的驱动管理类java.sql.DriverManager来获取一个Hive的数据库连接。 Hive的数据库URL为url="jdbc:hive2://xxx.xxx.xxx.xxx:2181,xxx.xxx.xxx.xxx:2181,xxx.xxx.xxx.xxx:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver;sasl.qop=auth-conf;auth=KERBEROS;principal=hive/hadoop.hadoop.com@HADOOP.COM;user.principal=hive/hadoop.hadoop.com;user.keytab=conf/hive.keytab"; 以上已经经过安全认证,所以Hive数据库的用户名和密码为null或者空。 如下: // 建立连接 connection = DriverManager.getConnection(url, "", "");
  • 执行HQL 执行HQL,注意HQL不能以";"结尾。 正确示例: String sql = "SELECT COUNT(*) FROM employees_info"; Connection connection = DriverManager.getConnection(url, "", ""); PreparedStatement statement = connection.prepareStatement(sql); resultSet = statement.executeQuery(); 错误示例: String sql = "SELECT COUNT(*) FROM employees_info;"; Connection connection = DriverManager.getConnection(url, "", ""); PreparedStatement statement = connection.prepareStatement(sql); resultSet = statement.executeQuery();
  • 多线程安全登录方式 如果有多线程进行login的操作,当应用程序第一次登录成功后,所有线程再次登录时应该使用relogin的方式。 login的代码样例: private Boolean login(Configuration conf){ boolean flag = false; UserGroupInformation.setConfiguration(conf); try { UserGroupInformation.loginUserFromKeytab(conf.get(PRINCIPAL), conf.get(KEYTAB)); System.out.println("UserGroupInformation.isLoginKeytabBased(): " +UserGroupInformation.isLoginKeytabBased()); flag = true; } catch (IOException e) { e.printStackTrace(); } return flag; } relogin的代码样例: public Boolean relogin(){ boolean flag = false; try { UserGroupInformation.getLoginUser().reloginFromKeytab(); System.out.println("UserGroupInformation.isLoginKeytabBased(): " +UserGroupInformation.isLoginKeytabBased()); flag = true; } catch (IOException e) { e.printStackTrace(); } return flag; }
  • 中小规模数据量维度表可以采用内存维度表(如Hudi) 内存维度表:将维度数据加载到内存当中,每个TM都会加载全量的数据,在内存内实现数据点查关联。若数据量过大,需要给TM分配大的内存空间,否则容易导致作业异常。 外置维度表:将维度数据存在高速的K-V数据库中,通过远程的K-V查询实现点查关联,常用的开源K-V库有HBase。 状态维度表:将维度表数据当做流表,实时读入到流式作业当中,通过数据的回撤流能力实现维度更新和数据不对齐场景下的数据一致性保证。维度表保存时间比较长,当前Flink on Hudi能力可以针对Hudi作为维度表单独设置TTL时长。 表2 维度表实现方式对比 维度 内存维度表(hive/hudi表) 外置维度表(HBase) 状态维度表 性能 非常高(毫秒内) 中(毫秒级) 高(毫秒内~毫秒级) 数据量 小,建议单个TM保持1GB以内 大,TB级 中,GB级 存储资源 内存消耗大,单个TM全量存储 外置存储,无存储资源消耗 各TM分散存储,内存+磁盘存储 时效性 周期性数据加载,时效低 相对高 高 关联数据结果 低 中 -
  • 高可用性下考虑提高Checkpoint保存数 Checkpoint保存数默认是1,也就是只保存最新的Checkpoint的状态文件,当进行状态恢复时,如果最新的Checkpoint文件不可用(比如HDFS文件所有副本都损坏或者其他原因),那么状态恢复就会失败。如果设置Checkpoint保存数为2,即使最新的Checkpoint恢复失败,那么Flink会回滚到之前那一次Checkpoint的状态文件进行恢复。所以可以增加Checkpoint保存数。 【示例】配置Checkpoint文件保存数为2: state.checkpoints.num-retained: 2
  • 使用Hive SQL时如果Flink语法不兼容则可切换Hive方言 当前Flink支持的SQL语法解析引擎有default和Hive两种,第一种为Flink原生SQL语言,第二种是Hive SQL语言。因为部分Hive语法的DDL和DML无法用Flink SQL运行,所以遇到这种SQL可直接切换成Hive的dialect。使用Hive dialect需要注意: Hive dialect只能用于操作Hive表,不能用于普通表。Hive方言应与HiveCatalog一起使用。 虽然所有Hive版本都支持相同的语法,但是是否有特定功能仍然取决于使用的Hive版本。例如仅在Hive-2.7.0或更高版本中支持更新数据库位置。 Hive和Calcite具有不同的保留关键字。例如default在Calcite中是保留关键字,在Hive中是非保留关键字。所以在使用Hive dialect时,必须使用反引号(`)引用此类关键字,才能将其用作标识符。 在Hive中不能查询在Flink中创建的视图。 【示例】修改SQL解析为Hive语法(sql-submit-defaults.yaml): configuration: table.sql-dialect: hive
  • 使用EXACTLY ONCE流处理语义保证端到端的一致性 流处理语义有三种:EXACTLY ONCE、AT LEAST ONCE、AT MOST ONCE。 AT MOST ONCE:无法保证数据处理的完整性,但性能相比最好。 AT LEAST ONCE:可以保证数据处理的完整性,但无法保证数据处理的准确性,性能适中。 EXACTLY ONCE:可以保证数据处理的准确性,但性能最差。 首先需要确认能否保证EXACTLY_ONCE(严格一次),因为端到端EXACTLY ONCE语义需要输入数据源的可回放(例如Kafka可回放数据),输出数据源的事务性(例如MySQL可原子性写入数据)。在无法满足这些条件的情况下,可以视情况将其降级为AT LEAST ONCE或者AT MOST ONCE。 在无法满足输入源的可回放时,只能保证AT MOST ONCE。 在无法满足输出目的的原子性写入时,只能保证AT LEAST ONCE。 【示例】API方式设置Exactly once语义: env.getCheckpointConfig.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE) 【示例】资源文件方式设置Exactly once语义: # checkpoint的语义 execution.checkpointing.mode: EXACTLY_ONCE
  • 生产环境使用增量Rocksdb作为State Backend Flink提供了三种状态后端:MemoryStateBackend,FsStateBackend,和RocksDBStateBackend。 MemoryStateBackend是将state存储在JobManager的Java堆上,每个状态的大小不能超过akka帧的大小,且总量不能超过JobManager的堆内存大小。所以只适合于本地开发调试,或状态大小有限的一些小状态的场景。 FsStateBackend是文件系统状态后端,正常情况下将state存储在TaskManager堆内存中,当Checkpoint时将state存储在文件系统上,而JobManager内存中存储极少的元数据(高可用场景下存储在ZooKeeper)。因为文件系统的存储空间足够,适合于大状态,长窗口,或大键值状态的有状态处理任务,也适合于高可用方案。 RocksDBStateBackend是内嵌数据库后端,正常情况下state存储在RocksDB数据库中,该数据库数据放在本地磁盘上,在Checkpoint时将state存储在配置的文件系统上而JobManager内存中存储极少的元数据(高可用场景下存储在ZooKeeper),同时是唯一一个可以增量Checkpoint的状态后端,除了适合于FsStateBackend的场景,还适用于超大状态的场景。 表1 Flink状态后端 类别 MemoryStateBackend FsStateBackend RocksDBStateBackend 方式 Checkpoint数据直接返回给Master节点,不落盘 数据写入文件,将文件路径传给Master 数据写入文件,将文件路径传给Master 存储 堆内存 堆内存 Rocksdb(本地磁盘) 性能 相比最好(一般不用) 性能好 性能不好 缺点 数据量小、易丢失 容易OOM风险 需要读写、序列化、IO等耗时 是否支持增量 不支持 不支持 支持 【示例】配置RockDBStateBackend(flink-conf.yaml): state.backend: rocksdb state.checkpoints.dir: hdfs://namenode:40010/flink/checkpoints
  • 通过查看监控信息定位Back Pressure点 Flink提供了很多的监控指标,根据这些指标可以分析任务过程中的性能状况及瓶颈。 【示例】配置采样的样本数和时间间隔: # 有效的反压结果被废弃并重新进行采样的时间,单位ms web.backpressure.refresh-interval: 60000 # 用于确定反压采样的样本数 web.backpressure.num-samples: 100 # 用于确定反压采样的间隔时间,单位ms web.backpressure.delay-between-samples: 50 可以在Job的Overview选项卡后面查看BackPressure,如下图表示采样进行中,默认情况下,大约需要5秒完成采样。 图1 采样进行中 如下图显示“OK”表示没有反压,“HIGH”表示对应SubTask被反压。 图2 无反压状态 图3 反压状态
  • 确认表内桶数 Hudi表的桶数设置,关系到表的性能,需要格外引起注意。 以下几点,是设置桶数的关键信息,需要建表前确认。 非分区表 单表数据总条数 = select count(1) from tablename(入湖时需提供); 单条数据大小 = 平均 1KB(华为建议通过select * from tablename limit 100将查询结果粘贴在notepad++中得出100条数据的大小再除以100得到单条平均大小) 单表数据量大小(G) = 单表数据总条数*单表数据大小/1024/1024 非分区表桶数 = MAX(单表数据量大小(G)/2G*2,再向上取整,4) 分区表 最近一个月最大数据量分区数据总条数 = 入湖前咨询产品线 单条数据大小 = 平均 1KB(华为建议通过select * from tablename limit 100将查询结果粘贴在notepad++中得出100条数据的大小再除以100得到单条平均大小) 单分区数据量大小(G) = 最近一个月最大数据量分区数据总条数*单表数据大小/1024/1024 分区表桶数 = MAX(单分区数据量大小(G)/2G,再后向上取整,1) 需要使用的是表的总数据大小,而不是压缩以后的文件大小 桶的设置以偶数最佳,非分区表最小桶数请设置4个,分区表最小桶数请设置1个。
  • 确认建表SQL DataArts支持通过Spark JDBC方式和Spark API方式操作Hudi表: Spark JDBC方式使用公用资源,不用单独起Spark作业,但是不能指定执行SQL所需要的资源以及配置参数,因此建议用来做建表操作或小数据量的查询操作。 Spark API方式执行的SQL独立起Spark作业,有一定的耗时,但是可以通过配置运行程序参数来指定作业所需要的资源等参数,建议批量导入等 作业使用API方式来指定资源运行,防止占用jdbc资源长时间阻塞其他任务。 DataArts使用Spark API方式操作Hudi表,必须要添加参数--conf spark.support.hudi=true,并且通过执行调度来运行作业。
  • 判断使用分区表还是非分区表 根据表的使用场景一般将表分为事实表和维度表: 事实表通常整表数据规模较大,以新增数据为主,更新数据占比小,且更新数据大多落在近一段时间范围内(年或月或天),下游读取该表进行ETL计算时通常会使用时间范围进行裁剪(例如最近一天、一月、一年),这种表通常可以通过数据的创建时间来做分区已保证最佳读写性能。 维度表数据量一般整表数据规模较小,以更新数据为主,新增较少,表数据量比较稳定,且读取时通常需要全量读取做join之类的ETL计算,因此通常使用非分区表性能更好。 分区表的分区键不允许更新,否则会产生重复数据。 例外场景:超大维度表和超小事实表 特殊情况如存在持续大量新增数据的维度表(表数据量在200G以上或日增长量超过60M)或数据量非常小的事实表(表数据量小于10G且未来三至五年增长后也不会超过10G)需要针对具体场景来进行例外处理: 持续大量新增数据的维度表 方法一:预留桶数,如使用非分区表则需通过预估较长一段时间内的数据增量来预先增加桶数,缺点是随着数据的增长,文件依然会持续膨胀; 方法二:大粒度分区(推荐),如果使用分区表则需要根据数据增长情况来计算,例如使用年分区,这种方式相对麻烦些但是多年后表无需重新导入。 方法三:数据老化,按照业务逻辑分析大的维度表是否可以通过数据老化清理无效的维度数据从而降低数据规模。 数据量非常小的事实表 这种可以在预估很长一段时间的数据增长量的前提下使用非分区表预留稍宽裕一些的桶数来提升读写性能。
  • 使用DataArts创建Hudi表 DataArts支持通过Spark JDBC方式和Spark API方式操作Hudi表: Spark JDBC方式使用公用资源,不用单独起Spark作业,但是不能指定执行SQL所需要的资源以及配置参数,因此建议用来做建表操作或小数据量的查询操作。 Spark API方式执行的SQL独立起Spark作业,有一定的耗时,但是可以通过配置运行程序参数来指定作业所需要的资源等参数,建议批量导入等 作业使用API方式来指定资源运行,防止占用jdbc资源长时间阻塞其他任务。 DataArts使用Spark API方式操作Hudi表,必须要添加参数--conf spark.support.hudi=true,并且通过执行调度来运行作业。
共100000条