<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[Yohohaha的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/Yohohaha</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; Yohohaha]]></copyright><item><title><![CDATA[flink学习（七）——DataStream API介绍]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/112480679</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/112480679</guid><author>Yohohaha</author><pubDate>Wed, 13 Jan 2021 16:36:27 +0800</pubDate><description><![CDATA[前面我们尝试用flink写了一个WordCount程序，并且介绍了flink提供的api层级，接下来我们正式来学习flink的DataStream API。

为什么先学习DataStream API，而不是ProcessFunction API，这是因为ProcessFunction API是通过DataStream API调用的，它作为DataStream API的补充，可以实现DataStream API所不能实现的一些高级功能。

DataStream程序结构剖析
我们回到WordCount的那个例]]></description><category></category></item><item><title><![CDATA[flink学习（六）——flink api层次]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/111462427</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/111462427</guid><author>Yohohaha</author><pubDate>Mon, 21 Dec 2020 22:45:46 +0800</pubDate><description><![CDATA[在前文我们写了一个WordCount程序体验了一下flink程序的编写。在本篇中我们详细学习下flink api的分类及其应用场景。
Flink’s API
flink提供了4个层次的api抽象：


在最下层，就是有状态流式编程，它提供了状态编程和时间编程（时间编程后面会学到）的基础能力。它通过Process Function嵌入到DataStream API中。它It is embedded into the DataStream API via the Process Function. It all]]></description><category></category></item><item><title><![CDATA[flink学习（五）——浅尝WordCount]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/111407612</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/111407612</guid><author>Yohohaha</author><pubDate>Sat, 19 Dec 2020 20:26:28 +0800</pubDate><description><![CDATA[前面学了那么多，我们还没有上手写过代码，现在我们来学习如何用flink实现流式的WordCount程序。
准备工作

java开发环境，推荐Intellij IDEA。
netcat程序。

如果是windows系统，可以到https://eternallybored.org/misc/netcat/网站下载netcat，并解压配好环境变量即可；
如果是centos系统，直接yum install -y nc即可；


pom文件配置    &lt;!-- Apache Flink dependencies]]></description><category></category></item><item><title><![CDATA[flink学习（四）——flink任务执行原理详解]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/111400250</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/111400250</guid><author>Yohohaha</author><pubDate>Sat, 19 Dec 2020 15:08:59 +0800</pubDate><description><![CDATA[在前文中我们学习了flink的整体架构和任务提交执行的流程。现在我们来学习flink在内部具体如何执行任务。
任务执行图
在flink中有四层执行图，StreamGraph -&gt; JobGraph -&gt; ExecutionGraph -&gt; 物理执行图，如图所示：


StreamGraph：是根据用户通过 Stream API 编写的代码生成的最初的图，用来表示程序的拓扑结构。每个转换操作会生成一个StreamNode，两个StreamNodes之间由StreamEdge连接在一起，Str]]></description><category></category></item><item><title><![CDATA[flink学习（三）——flink整体架构]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/111398232</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/111398232</guid><author>Yohohaha</author><pubDate>Sat, 19 Dec 2020 00:15:07 +0800</pubDate><description><![CDATA[flink作为一个分布式计算引擎，它可以在所有主流集群资源管理器中，如Hadoop YARN，Apache Mesos和Kubernetes，也可以运行在独立集群中。当然，它还提供了本地运行模式，可以供我们开发测试。
架构组成
flink集群中最重要的两个进程组件是：JobManager 和 TaskManager。
这是典型的主从架构：一个集群中只能有一个JobManager（HA部署的除外，它会有一个leader jobmager和一个standby jobmanager），但是可以有多个TaskMan]]></description><category></category></item><item><title><![CDATA[flink学习（二）——flink怎么进行流计算]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/110511034</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/110511034</guid><author>Yohohaha</author><pubDate>Fri, 04 Dec 2020 16:09:20 +0800</pubDate><description><![CDATA[Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams.

上述那句话是flink官网对flink的描述。
我们可以总结出两点计算特征：

分布式
有状态计算

分布式很好理解。在大数据时代，作为数据处理引擎，分布式是必须的能力。

...]]></description><category></category></item><item><title><![CDATA[flink学习（加餐）——flink-mysql-cdc设置从指定position消费]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/110525584</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/110525584</guid><author>Yohohaha</author><pubDate>Fri, 04 Dec 2020 11:25:09 +0800</pubDate><description><![CDATA[目前发布的flink-connector-mysql-cdc（version：1.1.0）不支持从指定的mysql bin-log文件的某个position开始消费。不过也不是没有办法，我们可以增加一些额外配置使其支持。

参考自Support read from specific MySQL Binlog position

它的原理是通过设置OFFSET_STATE_VALUE属性，解析出bin-log文件和对应的position，在启动的时候即可指定position消费。OFFSET_STATE_VA]]></description><category></category></item><item><title><![CDATA[flink学习（一）——什么是流处理]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/110510604</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/110510604</guid><author>Yohohaha</author><pubDate>Thu, 03 Dec 2020 02:27:24 +0800</pubDate><description><![CDATA[流处理引入
为了理解流处理，我们先来看看批处理。批处理是把我们感兴趣的数据一起搜集下来加以处理，产生结果。比如说双十一当天有多少个用户购买了商品，每个用户分别买了多少件，分别是哪些品类的商品。过去需要第二天或者几个小时后才能出统计结果，我们才能知道双十一当天或者截止到某个小时有多少人买了东西等，这些是批处理的结果。批处理的结果生成相距用户实际行为的发生间隔了很长一段时间，往往是一天或者几小时。在现在的互联网竞争下，有时候这些数据统计延迟是无法接受的，我们需要更快地知道当前最新的数据状态，这就需要流处理（也可]]></description><category></category></item><item><title><![CDATA[flink学习（加餐）——job任务状态变化]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/110509744</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/110509744</guid><author>Yohohaha</author><pubDate>Thu, 03 Dec 2020 01:56:36 +0800</pubDate><description><![CDATA[我们来看一下flink官网的图：

光看图就头晕了，我们可以来整理一下。
首先flink job任务状态总共有：

Created
Running
Finished
Failed
Canceled
Failing
Canceling
Restarting
Suspended

根据个人理解，我们可以把这些状态分为四大类：

起始态
中间态
最终态
过渡态

起始态表示任务启动时的状态，中间态表示任务运行时的状态，最终态表示任务最后的状态，过渡态表示任务在上述这些状态转化时中间过渡的状态。
这样我们就把九个状]]></description><category></category></item><item><title><![CDATA[进程与线程（一）]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/109375840</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/109375840</guid><author>Yohohaha</author><pubDate>Fri, 30 Oct 2020 00:09:03 +0800</pubDate><description><![CDATA[我们打开一个应用程序，就是操作系统就会启动一个进程。不同的应用程序之间数据是隔离的，比如qq无法访问到浏览器的数据（保存到文件的除外），也即进程之间运行数据是隔离的。
线程是进程内部的执行单元，操作系统执行程序的最小单元。进程之间数据是隔离的，但是同一个进程内的不同线程之间资源是共享的。

...]]></description><category></category></item><item><title><![CDATA[学点算法（十一）——将二叉树转为数组]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/108722964</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/108722964</guid><author>Yohohaha</author><pubDate>Tue, 22 Sep 2020 02:53:21 +0800</pubDate><description><![CDATA[今天我们来学习如何将二叉树转为数组（填坑学点算法（九）——二叉树中序遍历算法（递归实现））。
首先，我们看下面这棵二叉树，我们从根节点出发，左右孩子依次排列在根节点后面，放入数组中，然后继续以同样的方法遍历其左右孩子，如果孩子节点的位置已经被叔父节点占据，则继续排在叔父节点后面，如果遇到没有左右孩子的情况，则将没有的节点置为null，将节点排列在数组中，直至遍历结束，位于数组结尾的null(后面没有有效节点值)可去除。

我们来看下这个过程：

首先我们放入1及其左右孩子，得到[1, 2, 3]。
取1的左]]></description><category></category></item><item><title><![CDATA[hadoop partitioner类加载分析]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/108538762</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/108538762</guid><author>Yohohaha</author><pubDate>Fri, 11 Sep 2020 17:40:27 +0800</pubDate><description><![CDATA[在hadoop中，在map方法结束写出数据的时候需要对数据进行分区，具体分区实现由Partitioner类提供，而Partitioner类的加载逻辑如下：
partitions = jobContext.getNumReduceTasks();
if (partitions &gt; 1) {
  // 设置的分区数（即reduce task的个数）大于1，则使用设置的分区类
  partitioner = (org.apache.hadoop.mapreduce.Partitioner&lt;K,V&gt]]></description><category></category></item><item><title><![CDATA[hadoop mapreduce加载ClientProtocol(JobRunner)方法解析]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/108420048</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/108420048</guid><author>Yohohaha</author><pubDate>Sun, 06 Sep 2020 10:48:14 +0800</pubDate><description><![CDATA[hadoop mapreduce加载ClientProtocol(JobRunner)使用了spi机制，具体方法在Cluster#initialize。它会使用frameworkLoader加载ClientProtocolProvider，在hadoop的jar包里配置了两个实现类：

org.apache.hadoop.mapred.YarnClientProtocolProvider，配置文件见~\.m2\repository\org\apache\hadoop\hadoop-mapreduce-cli]]></description><category></category></item><item><title><![CDATA[学点算法（十）——二叉树中序遍历算法（迭代实现）]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/107022374</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/107022374</guid><author>Yohohaha</author><pubDate>Tue, 30 Jun 2020 15:37:09 +0800</pubDate><description><![CDATA[今天我们继续来学习二叉树的中序遍历算法。
在学点算法（九）——二叉树中序遍历算法（递归实现）中我们已经学习了二叉树中序遍历的递归算法，今天我们继续来学习它的迭代算法。
我们先来看整个遍历的过程，如图所示：


...]]></description><category></category></item><item><title><![CDATA[学点算法（九）——二叉树中序遍历算法（递归实现）]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/107004314</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/107004314</guid><author>Yohohaha</author><pubDate>Mon, 29 Jun 2020 16:02:18 +0800</pubDate><description><![CDATA[今天我们来学习二叉树的中序遍历算法。
二叉树有多种遍历方法，前中序遍历和层次遍历。我们今天的主角是中序遍历，它的遍历顺序为：

左子树
根节点
右子树

如下图所示：

我们知道树的定义本身就是递归式的，左子树就是一棵以根节点的左孩子为根节点的树，右子树也同理，所以遍历左子树或者右子树直接是把原来的根节点换成根节点的左孩子或者右孩子即可。这样我们可以很快地写出递归的中序遍历算法。
import java.util.ArrayDeque;
import java.util.ArrayList;
import ]]></description><category></category></item><item><title><![CDATA[学点算法（八）——括号匹配算法]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/106797650</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/106797650</guid><author>Yohohaha</author><pubDate>Mon, 22 Jun 2020 17:14:20 +0800</pubDate><description><![CDATA[今天我们来学习括号匹配算法。
作为程序员应该都知道，我们在码代码的过程中，会用到各类括号，无论是{}还是()还是[]。括号都要求成对出现，要不然就会报语法错误。得益于强大的IDE，我们不需要自己去检测括号，如果多写活着漏写了括号，IDE就会提示我们有语法错误，我们改正一下就可以了。那你是否好奇过IDE的这个检测算法是如何实现的呢？
接下来我们来分析分析。
我们前面提到了可能会有多种括号情况：{}、()、[]等等。我们先只取一种来分析，我们这里取()。
见多识广
先从简单的开始：
0 * (1 + 2) ——]]></description><category></category></item><item><title><![CDATA[学点算法（七）——十进制数转换为二进制数]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/106763274</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/106763274</guid><author>Yohohaha</author><pubDate>Mon, 15 Jun 2020 22:11:38 +0800</pubDate><description><![CDATA[今天我们来学习进制转换算法。
大家学习计算机或者编程，都会知道计算机处理数据都是基于二进制的，而我们在日常生活中都是使用十进制。如果要用计算机存储数据，肯定要将十进制转化为二进制，或者我们要查数据，要将二进制转换为十进制，那么问题来了：现在有一个十进制数，我们如何将其转换为二进制数呢？
比如我们现在有一个数字：1024（预先给定的数字默认用十进制理解）。用十进制表示为：
1024(10)=1×103+0×102+2×101+4×1001024_{(10)} = 1 \times 10^3 + 0 \time]]></description><category></category></item><item><title><![CDATA[学点算法（六）——数组选择排序]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/106709420</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/106709420</guid><author>Yohohaha</author><pubDate>Fri, 12 Jun 2020 18:56:22 +0800</pubDate><description><![CDATA[今天我们来学习数组的插入排序算法。

假设你是一个农场工人，收获了100个萝卜，长短不一，农场主让你从小到大排列好售卖，你应该怎么做？]]></description><category></category></item><item><title><![CDATA[学点算法（五）——使用归并算法求数组的逆序对数]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/106620502</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/106620502</guid><author>Yohohaha</author><pubDate>Mon, 08 Jun 2020 17:11:53 +0800</pubDate><description><![CDATA[今天来学习归并算法的一个应用，求数组中的逆序对数。
首先我们需要知道逆序对是什么东西：在一个数组中，有两个元素，索引小的元素比索引大的元素大，那这两个元素就构成一个逆序对。而一个数组中所有逆序对的个数就叫做逆序对数。
暴力求解法
我们可以很容易地想出暴力求解的方法：遍历数组，依次取数组中的每一个数，然后与索引排在其后的元素比较，如果比它小，则逆序对数+1，遍历完毕，得到的逆序对数则是数组的逆序对数。
代码如下：
/**
 * 暴力求解法求逆序对数
 * @param nums 数组
 * @return 逆]]></description><category></category></item><item><title><![CDATA[学点算法（四）——数组插入排序]]></title><link>https://blog.youkuaiyun.com/Yohohaha/article/details/106589873</link><guid>https://blog.youkuaiyun.com/Yohohaha/article/details/106589873</guid><author>Yohohaha</author><pubDate>Sun, 07 Jun 2020 09:23:13 +0800</pubDate><description><![CDATA[今天来学习数组的插入排序算法。
再将算法之前，我们先来想象这样一个场景：我们要上体育课，体育老师要求同学们从高到矮排好队。当同学们都排好队的时候，小甲同学迟到了。这时候小甲同学随便站个地方可不行，因为这样队伍就不是排好的了，所以要将小甲同学插入到队伍中，使队伍重新又是从高到矮排好的。小甲同学对比自己和同学们的身高，找到自己的位置，排到队伍里，就完成了队伍的排序。
这个将一个无序元素插入到n个元素的有序集合，使新的(n+1)个元素的集合变成重新有序的动作就是插入排序的基本思想。借助这种思想，我们就可以把一个数]]></description><category></category></item></channel></rss>