实训笔记7.19

news2024/11/25 20:48:49

实训笔记7.19

  • 7.19
    • 一、座右铭
    • 二、Hadoop的HDFS分布式文件存储系统的相关原理性内容
      • 2.1 HDFS上传数据的流程
      • 2.2 HDFS下载数据的流程
      • 2.3 HDFS中NameNode和SecondaryNameNode工作机制(涉及到HDFS的元数据管理操作)
      • 2.4 HDFS中NameNode和DataNode的工作机制(涉及到HDFS的集群管理操作)
    • 三、Hadoop的新的从节点服役和旧的从节点退役(HDFS-DataNode、YARN-NodeManager)--HDFS、YARN的运行中的操作
    • 四、Hadoop的MapReduce分布式计算框架
      • 4.1 基本概念
        • 4.1.1 MapReduce的分布式计算思想
        • 4.1.2 MapReduce运行过程中相关的一些进程
        • 4.1.3 MapReduce编程规范
      • 4.2 MapReduce的工作流程原理(简单版本)
      • 4.3 MapReduce的中序列化机制问题
      • 4.4 MR程序运行的核心阶段的细节性知识
        • 4.4.1 MR程序在运行过程中,涉及到的阶段和作用:
        • 4.4.2 MR程序运行的的第一个阶段:InputFormat阶段
    • 五、MR程序运行的问题总结
    • 六、代码示例

7.19

一、座右铭

我的故事你说,我的文字我落,我值几两你定,我去何方我挑。

二、Hadoop的HDFS分布式文件存储系统的相关原理性内容

2.1 HDFS上传数据的流程

2.2 HDFS下载数据的流程

2.1~2.2:客户端Client 主节点NameNode 从节点DataNode

2.3 HDFS中NameNode和SecondaryNameNode工作机制(涉及到HDFS的元数据管理操作)

  1. 一个概念和两个文件:元数据、edits编辑日志文件、fsimage镜像文件(元数据的持久点检查文件)
  2. SNN的检查点机制:每间隔一段时间或者记录数到达一定的数量,HDFS就会把edits文件和fsimage文件合并
  3. NameNode如果元数据丢失的恢复机制
    1. 把SNN的拷贝过来的edits文件和fismage文件复制到NN的所在目录下(可能会造成元数据的丢失)
    2. 设置NameNode的多目录存储(可以百分百恢复元数据,但是多目录只能在同一个节点上配置)
    3. 使用HA高可用安装模式
  4. HDFS的集群安全模式的问题
    1. HDFS启动之后到能正常对外提供访问的这一段时间成为集群的安全模式
    2. 元数据加载成功,同时整个HDFS集群99.9%的block数据块满足最小备份数的时候

2.4 HDFS中NameNode和DataNode的工作机制(涉及到HDFS的集群管理操作)

  1. DataNode存储的block数据块除了包含数据本身以外,还包含数据块的校验和(保证block块的完整性的)。。。
  2. NameNode和DataNode的心跳机制 每隔3秒
  3. NameNode认为DataNode死亡的掉线时限时长:2*掉线的检测时间(5分钟)+10*心跳时间

三、Hadoop的新的从节点服役和旧的从节点退役(HDFS-DataNode、YARN-NodeManager)–HDFS、YARN的运行中的操作

  1. 新节点的服役:dfs.hosts

  2. 旧节点的退役:dfs.hosts.exclude|

退役的时候,HDFS会把退役节点上的block块迁移到没有退役的节点上

四、Hadoop的MapReduce分布式计算框架

4.1 基本概念

4.1.1 MapReduce的分布式计算思想

  1. Mapper阶段
    1. mapper阶段是用来分数据的
    2. Mapper阶段处理数据之前,数据文件会按照指定的规则划分为不同的切片(数据块),然后Mapper阶段启动多个MapTask去处理每一个切片的数据 MapTask的数量是自动确定的,是和切片的数量一一对应的
  2. Reducer阶段
    1. Reducer阶段是用来合数据的
    2. Reducer阶段是Mapper阶段之后执行的,处理的数据是Mapper处理完成的数据,Reducer会启动多个ReduceTask,每一个ReduceTask负责处理Mapper阶段输出的一部分数据 ReduceTask的数量不是自动确定的,而是我们手动指定,一般ReduceTask的数量在手动指定的时候需要和分区数保持一致

4.1.2 MapReduce运行过程中相关的一些进程

  1. MRAPPMaster
  2. MapTask
  3. ReduceTask

4.1.3 MapReduce编程规范

  1. 编写Mapper阶段的计算逻辑:MapTask的计算逻辑
  2. 编写Reduce阶段的计算逻辑:ReduceTask的计算逻辑
  3. 编写Driver驱动程序:整合MR程序,输入路径、Mapper阶段、Reducer阶段、输出路径

4.2 MapReduce的工作流程原理(简单版本)

在这里插入图片描述

4.3 MapReduce的中序列化机制问题

  1. MR程序的Map阶段和Reduce阶段都是要求输入的数据和输出的数据必须得是key-value键值对类型的数据,而且key-value必须得是序列化类型的数据
    1. 序列化:将Java中的某种数据类型转成二进制数据
    2. 反序列化:将二进制数据转换成某种数据类型
  2. MR程序之所以要求输入和输出的数据是K-V类型的,是因为MR程序是一个分布式计算程序,MR程序可以在多个节点上同时运行的,而且多个计算程序计算出来的结果可能跨节点,跨网络进行数据传输的。如果数据要跨节点跨网络传输,要求数据必须是二进制数据。
  3. Hadoop在进行Key-Value的序列化的时候,没有采用Java的序列化机制(Serializable、Externalizable),因为Java的序列化机制非常的笨重的,因此Hadoop基于Java的序列化机制方式提供了一种全新的专门适用于MR程序的轻量级的序列化机制。
  4. Hadoop中提供了两个接口:Writable、WritableComparable,Hadoop提供的两个序列化机制
    1. Writable
      1. 只有序列化和反序列化的效果,如果我们自定义的一个数据类型(Java类)要想当MR程序的K-V使用的话,Java必须实现Writable接口,重写两个方法,通过这两个方法规定序列化和反序列化的内容
      2. Writable的使用方式类似于Java中Externalizable序列化机制
    2. WritableComparable
      1. 接口除了具备序列化和反序列化的能力以外,还具备一个比较大小关系的方法
      2. 如果自定义的数据类型(Java类),想当MR程序中的key值来使用,必须实现此接口,让自定义数据类型既可以进行序列化反序列化还可以进行大小的比较判断 如果自定义的数据类型只想当作MR程序中的value来使用,只需要实现Writable接口即可,不需要比较大小。
  5. Hadoop常见的序列化类型(Hadoop把Java中包装类和String类型已经给我们封装好了对应的Hadoop序列化类型)—实现了WritableComparable接口
类型方法名
booleanBooleanWritable
byteByteWritable
intIntWritable
floatFloatWritable
longLongWritable
doubleDoubleWritable
stringText
mapMapWritable
arrayArrayWritable
  • 【注意】 1、如果以后MR程序运行没有报错,但是输出目录没有任何的内容,一般可能是因为输入和输出的key-value的自定义类型没有实现序列化 2、如果自定义的JavaBean充当Reducer阶段输出key-value时,最好把toString方法给重写了,否则Reducer最后输出的结果是JavaBean的地址值

4.4 MR程序运行的核心阶段的细节性知识

4.4.1 MR程序在运行过程中,涉及到的阶段和作用:

  1. InputFormat阶段:两个作用
    1. 负责对输入的数据进行切片,切片的数据和Mapper阶段的MapTask的数量是相对应的
    2. 负责MapTask读取切片数据时,如果将切片的数据转换成为Key-value类型的数据,包括key-value的数据类型的定义
  2. Mapper阶段——作用处理每一个切片数据的计算逻辑
  3. Partitioner阶段——map阶段处理完成的数据输出到缓冲区溢写磁盘的时候必须进行分区
  4. Combiner阶段:可以存在可以不存在——相当于是一个Reducer,只不过这个reducer是针对于当前的MapTask有效
  5. Reducer阶段———作用就是用来聚合所有MapTask的数据,聚合起来之后计算逻辑的编写
  6. OutputFormat阶段———作用就是Reducer阶段输出的数据如何以key-value的形式输出到最终的目的地

4.4.2 MR程序运行的的第一个阶段:InputFormat阶段

  1. InputFormat是一个抽象类,提供了两个抽象方法

    1. getSplits:这个方法是用来进行输入数据文件的切片计算的
    2. createRecordReader:这个方法是MapTask读取切片数据时,是按照行读取还是按照其他规则读取,包括读取时key-value分别代表什么含义,什么类型
  2. 常用的InputFormat的实现类:

    1. FileInputFormat(是InputFormat的默认实现类)FileInputFormat是专门用来读取文件数据时使用的输入格式化类,但是FileInputFormat也是一个抽象类

    2. FileInputFormat抽象类有五个常用的非抽象子类

      1. TextInputFormat(是FileInputFormat默认实现类)

        1. 如何切片

          1. 两个核心参数:MinSplitSize=1LMaxSplitSize=Long.MAX_VALUE

            confguration("mapreduce.input.fileinputformat.split.minsize",xxxL)

            configuration("mapreduce.input.fileinputformat.split.maxsize",xxxL)

          2. 每一个输入文件单独进行切片

          3. 每一个文件先获取它的blockSize,然后计算文件的切片大小splitSize=Math.max(minSize, Math.min(maxSize, blockSize))

          4. 先判断文件是否能被切片,如果文件是一个压缩包(.gz、.zip),单独成为一个切片,如果文件能被切片,判断文件的长度是否大于splitSize的1.1倍,如果不大于 文件单独成为一个切片,如果大于1.1倍,按照splitsize切一片,然后将剩余的大小和splitsize继续比较

          5. 示例

            1. 第一种情况: a.tar.gz 300M blocksize 128M 有一个数据切片300M
            2. 第二种情况:blocksize均为128M a.txt 200M 两个切片:一个切片128M 第二个切片72M b.txt 130M 一个切片:130M
          6. 【注意】

            TextInputFormat是按照SplitSize进行切片的,默认情况下SplitSize=文件的BlockSize

            如果你要让SplitSize大于blockSize,那么我们需要在MR程序调整minsize的大小即可

            如果你要让SplitSize小于BlockSize 那么需要MR程序调整maxSize的大小即可

        2. 如何读取数据成为key-value

      2. KeyValueTextInputFormat

      3. NLineInputFormat

      4. CombineInputFormat

      5. SequenceFileInputFormat

  3. 如何自定义InputFormat实现类

五、MR程序运行的问题总结

  1. MR程序运行需要在控制台输出日志,MR程序控制台输出的日志能清洗看到MR程序切片数量以及MapTask的数量和ReduceTask的数量 但是默认情况下控制台是无法输出日志的,如果要输出日志信息,我们需要对代码进行修改

    1. 需要在项目的resources目录引入log4j.properties文件 日志信息输出文件,文件当中定义了我们如何输出日志信息

    2. 引入一个日志框架的依赖,如果没有这个依赖,那么日志文件不会生效输出 pom.xml

      <dependency>      
          <groupId>org.slf4j</groupId>     
          <artifactId>slf4j-log4j12</artifactId>      <version>1.7.21</version>    
      </dependency>
      

六、代码示例

package com.sxuek.flow;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Objects;

/**
 * JavaBean:是Java中一种很干净的类,类中只具备私有化的属性、构造器、getter setter方法  hashCode equals方法 toString方法
 * 实体类:实体类又是一种特殊的JavaBean,当JavaBean是和数据库中数据表对应的类的时候,JavaBean称之为实体类
 *
 * JavaBean可以自己手动生成也可以使用lombok的技术基于注解快速的创建JavaBean这个类
 *    Lombok使用要慎重,Lombok对代码的侵占性是非常大的
 *
 * 如果自定义的JavaBean要当MR程序的输入和输出的KV值,最好让JavaBean存在一个无参构造器(MR程序底层反射构建这个类的对象)
 * 如果自定义的JavaBean要充当Reducer阶段的KEY和Value,那也就意味着JavaBean的结果要写到最终的结果文件当中,JavaBean的数据往结果文件写的格式是按照
 * JavaBean的toString方法去写的。
 */
public class FlowBean implements Writable {
//public class FlowBean {
    private Long upFlow;//上行流量
    private Long downFlow; //下行流量
    private Long sumFlow; //总流量

    public FlowBean() {

    }

    public FlowBean(Long upFlow, Long downFlow, Long sumFlow) {
        this.upFlow = upFlow;
        this.downFlow = downFlow;
        this.sumFlow = sumFlow;
    }

    public Long getUpFlow() {
        return upFlow;
    }

    public void setUpFlow(Long upFlow) {
        this.upFlow = upFlow;
    }

    public Long getDownFlow() {
        return downFlow;
    }

    public void setDownFlow(Long downFlow) {
        this.downFlow = downFlow;
    }

    public Long getSumFlow() {
        return sumFlow;
    }

    public void setSumFlow(Long sumFlow) {
        this.sumFlow = sumFlow;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        FlowBean flowBean = (FlowBean) o;
        return Objects.equals(upFlow, flowBean.upFlow) && Objects.equals(downFlow, flowBean.downFlow) && Objects.equals(sumFlow, flowBean.sumFlow);
    }

    @Override
    public int hashCode() {
        return Objects.hash(upFlow, downFlow, sumFlow);
    }

    @Override
    public String toString() {
        return upFlow+"\t"+downFlow+"\t"+sumFlow;
    }

    /**
     * 序列化写的方法
     * @param out <code>DataOuput</code> to serialize this object into.
     * @throws IOException
     */
    @Override
    public void write(DataOutput out) throws IOException {
        out.writeLong(upFlow);
        out.writeLong(downFlow);
        out.writeLong(sumFlow);
    }

    /**
     * 反序列化读取数据的方法
     * @param in <code>DataInput</code> to deseriablize this object from.
     * @throws IOException
     */
    @Override
    public void readFields(DataInput in) throws IOException {
        upFlow = in.readLong();
        downFlow = in.readLong();
        sumFlow = in.readLong();
    }
}

package com.sxuek.flow;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * 现在有一个文件 phone_data.txt,文件中记录着手机号消耗的流量信息
 * 文件中每一行数据代表一条手机的流量消耗,每一条数据是以\t制表符分割的多个字段组成的
 * 使用MR程序统计每一个手机号消耗的总的上行流量、总的下行流量、总流量
 */
public class FlowDriver {
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException, URISyntaxException {
        Configuration configuration = new Configuration();
        configuration.set("fs.defaultFS","hdfs://192.168.68.101:9000");
//        configuration.set("mapreduce.input.fileinputformat.split.minsize",150*1024*1024+"");
        //maxsize  100M  minsize  1L  blocksize 128M
        configuration.set("mapreduce.input.fileinputformat.split.maxsize",100*1024*1024+"");

        Job job = Job.getInstance(configuration);

        /**
         * MR程序封装的时候,按道理需要指定InputFormat类,只有指定了这个实现类,才能实现切片和kv数据的读取
         * 但是MR程序有个机制,如果没有指定InputFormat的实现类,默认就会实现FileInputFormat的一个实现子类TextInputFormat当作默认的切片机制
         * 和KV数据读取的InputFormat类
         */
//        job.setInputFormatClass(TextInputFormat.class);
        //封装输入的文件路径 输入路径可以是一个 也可以是多个 输入路径可以是文件也可以是文件夹
        /**
         * 默认切片机制 每一个文件单独切片  n个文件 最小有n个文件
         * splitSize 100M
         * 文件能否被切割、文件的大小是否大于splitsize的1.1倍
         * 300M   100M  100M  100M
         * 120M   100M   20M
         */
        FileInputFormat.setInputPaths(job,new Path("/test1"));

        //封装Mapper阶段
        job.setMapperClass(FlowMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(FlowBean.class);

        //封装Reducer阶段
        job.setReducerClass(FlowReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FlowBean.class);
        job.setNumReduceTasks(1);

        //封装输出结果路径
        //MR程序要求输出路径不能提前存在 如果提前存在会报错
        Path path = new Path("/output");
        //是用来解决输出目录如果存在MR程序报错问题的
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.68.101:9000"), configuration, "root");
        if (fs.exists(path)){
            fs.delete(path,true);
        }
        FileOutputFormat.setOutputPath(job,path);

        //最后提交程序运行即可
        boolean b = job.waitForCompletion(true);
        System.exit(b?0:1);
    }
}

package com.sxuek.flow;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * 读取切片数据,一行数据读取一次 而且读取的key value  LongWritable  Text
 * 输出的key value 是Text  FlowBean
 *
 */
public class FlowMapper extends Mapper<LongWritable, Text,Text,FlowBean> {
    @Override
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, FlowBean>.Context context) throws IOException, InterruptedException {
        String line = value.toString();
        String[] array = line.split("\t");
        String phoneNumber = array[1];
        Long upFlow = Long.parseLong(array[array.length - 3]);
        Long downFlow = Long.parseLong(array[array.length - 2]);
        FlowBean flowBean = new FlowBean(upFlow,downFlow,upFlow+downFlow);
        //需要将这一条数据以手机号为key  以flowbean为value输出给reduce
        context.write(new Text(phoneNumber),flowBean);
    }
}

package com.sxuek.flow;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class FlowReducer extends Reducer<Text,FlowBean,Text,FlowBean> {
    @Override
    protected void reduce(Text key, Iterable<FlowBean> values, Reducer<Text, FlowBean, Text, FlowBean>.Context context) throws IOException, InterruptedException {
        //计算手机号消耗的总的上行 下行 总流量  values中每一条流量的上 下 总累加起来即可
        long upFlowSum = 0L;
        long downFlowSum = 0L;
        long sumFlowSum = 0L;
        for (FlowBean value : values) {
            upFlowSum += value.getUpFlow();
            downFlowSum += value.getDownFlow();
            sumFlowSum += value.getSumFlow();
        }
        //需要以手机号为key  以flowbean为value将结果输出,flowbean需要将我们计算出来总流量信息封装起来
        FlowBean flowBean = new FlowBean(upFlowSum,downFlowSum,sumFlowSum);
        context.write(key,flowBean);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/771588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】仿函数(less)

C中的仿函数 class Solution { public:struct cmp{bool operator()(const pair<string,int>&kv1,const pair<string,int>&kv2){if(kv1.second<kv2.second) return true;if(kv1.secondkv2.second&&kv1.first>kv2.first) return true;return …

JavaWeb01-Servlet-thymeleaf-mvd-dispatcher-controller

Servlet: servlet的基本作用 第一个servlet程序&#xff1a; //演示servlet的生命周期 public class Demo02Servlet extends HttpServlet {Overridepublic void init() throws ServletException {System.out.println("正在初始化。。。");}Overrideprotected void …

实例019 以图形按钮显示的界面

实例说明 菜单和工具栏虽然能方便用户操作程序的相应功能&#xff0c;但各有缺点。如果采用按钮式功能菜单&#xff0c;不但美观大方&#xff0c;而且操作灵活。当单击按钮时&#xff0c;用户区将显示相应的操作按钮组。下面介绍图形界面式菜单的设计方法。运行本例&#xff0…

【个人笔记】linux命令之cd

cd命令 cd&#xff08;英文全拼&#xff1a;change directory&#xff09;命令用于改变当前工作目录的命令&#xff0c;切换到指定的路径。 若目录名称省略&#xff0c;则变换至使用者的 home 目录 (也就是刚 login 时所在的目录)。 另外&#xff0c;~ 也表示为 home 目录 的…

恢复配置并减少网络停机时间

随着众多公司努力在商业世界中崭露头角&#xff0c;拥有可靠的 IT 基础架构比以往任何时候都更加重要。组织需要维护一个稳定的网络环境&#xff0c;避免不合时宜的网络中断以及网络连接中断、声誉受损、应用程序不可用和数据丢失。 Network Configuration Manager 提供了一种…

Debian 12上如何关闭nobody共享文件夹,一个能让INSCODE AI 创作助手不知所措的小问题

这个问题之前在Debian 10和11上都没有遇到过&#xff0c;换上Debian 12后Samba的设置就出现了状况&#xff0c;装上Samba后什么都没有设置就在局域网可以看到&#xff1a; 根据之前的经验在/etc/samba/smb.conf里查了很久也没有看出所以然来&#xff0c;后来又问了INSCODE AI…

ubuntu打开usb摄像头

文章目录 前言一、识别 usb 摄像头二、安装应用程序显示摄像头捕捉到的视频1、使用应用程序茄子&#xff08;cheese&#xff09;2、运行 cheese 捕捉视频 总结 前言 记录一下解决在 Linux 下打开 usb 摄像头界面黑屏的问题。 一、识别 usb 摄像头 1、保持在 ubuntu 界面&…

软件测试用例的八大步骤你都知道吗?

目录 第一步、UI体验测试 第二步、功能完整性测试 第三步、业务流程测试 第四步、容错机制测试 第五步、常规性测试 第六步、性能测试 第七步、交互体验测试 第八步、兼容性测试 总结&#xff1a; 第一步、UI体验测试 1.风格、样式、颜色是否协调 2. 界面布局是否整齐、…

【网站搭建】3 更换博客主题—butterfly

可以到官网选择想要更换的主题Themes | Hexo 我选用的是butterflyzhangzeli/hexo-theme-butterfly: A Hexo Theme: Butterfly (github.com) 在Hexo根目录打开终端执行拉去操作 下载配套文件 npm install hexo-renderer-pug hexo-renderer-stylus 打开_config.yml文件&#xf…

二维费用背包(既有最大体积限制,又多加了一个最大重量限制)

1:分析状态转移方程式 2:ACcode: #include<bits/stdc.h> using namespace std; const int N1e310; int f[N][N],v[N],w[N],m[N]; void solve() {int a,b,c;cin>>a>>b>>c;for(int i1; i<a; i) cin>>v[i]>>m[i]>>w[i];//酷似01背…

数仓虚拟化技术:PieCloudDB 通过中国信通院 2023 「可信数据库」性能评测的强力支撑...

“可信数据库”是国内首个数据库的评测体系&#xff0c;被业界广泛认可为产品能力重要的衡量标准之一。PieCloudDB 在该评测中展现出卓越的数据处理速度、稳定性和可扩展性&#xff0c;为用户提供了强大的数据分析和查询能力。 6 月 15 ~ 16 日&#xff0c;中国信通院 2023 上…

vue3笔记-脚手架篇

第一章 基础篇 第二章 脚手架篇 vue2与vue3的一些区别 响应式系统&#xff1a; Vue 2 使用 Object.defineProperty 进行响应式数据的劫持和监听&#xff0c;它对数据监听是一项项的进行监听&#xff0c;因此&#xff0c;当新增属性发生变化时&#xff0c;它无法监测到&…

0719_rasa网站的一些介绍

it’s not a bot, it’s your brand rasa is the leading open generative conversational ai platform for creating and managing ai assistants at scale. learn more talk with sales top enterprises trust rasa american express adobe dell accenture report ho…

使用Canal同步mysql数据到es

一、简介 Canal主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费。 当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x 二、工作原理 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志( binary log, 其中记…

一篇文章带你用Jenkins和Kubernetes搭建DevOps平台

JenkinsKubernetes实现DevOps DevOps 介绍Jenkins环境准备准备JDK下载jdk安装jdk配置jdk环境变量 准备maven下载maven解压maven配置maven配置maven环境变量 安装Docker安装git 安装Jenkins初始化jenkins准备代码仓库和docker镜像仓库准备Kubernetes准备java项目搭建DevOps创建代…

ENSP实验一:防火墙基础配置

1、搭建拓扑图 配置client&#xff08;内网&#xff09;、FTP Server&#xff08;外网&#xff09;的IP地址 客户端设置&#xff1a; 服务端设置&#xff1a; 2、配置防火墙命名 进入防火墙&#xff0c;输入密码&#xff1a;默认为admin123 <USG6000V1>system-view /…

埃科光电在科创板上市:同创伟业、毅达资本为股东,实控人为董宁

7月19日&#xff0c;合肥埃科光电科技股份有限公司&#xff08;下称“埃科光电”&#xff0c;SH:688610&#xff09;在上海证券交易所科创板上市。本次上市&#xff0c;埃科光电的发行价为73.33元/股&#xff0c;发行数量为1700万股&#xff0c;募资总额约为12.47亿元&#xff…

Flutter 单线程模型保证UI运行流畅

Flutter 框架出色的渲染和交互能力。支撑起这些复杂的能力背后&#xff0c;实际上是基于单线程模型的 Dart。那么&#xff0c;与原生 Android 和 iOS 的多线程机制相比&#xff0c;单线程的 Dart 如何从语言设计层面和代码运行机制上保证 Flutter UI 的流畅性呢&#xff1f; 因…

❤️创意网页:HTML5 Canvas技术实现绚丽多彩的烟花特效教程

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

HhybridApp开发模式,你了解多少?

Hhybrid App顾名思义就是原生 App 与 Web App 的结合。它的壳是原生 App&#xff0c;但是里面放的是网页。 可以理解成&#xff0c;混合 App 里面隐藏了一个浏览器&#xff0c;用户看到的实际上是这个隐藏浏览器渲染出来的网页。 随着 Web 技术和移动设备的快速发展&#xff0…