Flink SQL 窗口聚合详解

1.滚动窗⼝(TUMBLE)

**滚动窗⼝定义:**滚动窗⼝将每个元素指定给指定窗⼝⼤⼩的窗⼝,滚动窗⼝具有固定⼤⼩,且不重叠。

例如,指定⼀个⼤⼩为 5 分钟的滚动窗⼝,Flink 将每隔 5 分钟开启⼀个新的窗⼝,其中每⼀条数都会划分到唯⼀⼀个 5 分钟的窗⼝中。

在这里插入图片描述

**应⽤场景:**按照⼀分钟对数据进⾏聚合,计算⼀分钟内 PV,UV 数据。

**实际案例:**分维度分钟级别统计在线⽤户数、总销售额。

滚动窗⼝在 1.13 版本之前和 1.13 及版本之后有两种 Flink SQL 实现⽅式

Group Window Aggregation(1.13 之前)和 Windowing TVF(1.13 及之后)

Group Window Aggregation ⽅案(⽀持 Batch\Streaming 任务):

-- 数据源表
CREATE TABLE source_table (
 -- 维度数据
 dim STRING,
 -- ⽤户 id
 user_id BIGINT,
 -- ⽤户
 price BIGINT,
 -- 事件时间戳
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 -- watermark 设置
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '10',
 'fields.dim.length' = '1',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000',
 'fields.price.min' = '1',
 'fields.price.max' = '100000'
)

-- 数据汇表
CREATE TABLE sink_table (
 dim STRING,
 pv BIGINT,
 sum_price BIGINT,
 max_price BIGINT,
 min_price BIGINT,
 uv BIGINT,
 window_start bigint
) WITH (
 'connector' = 'print'
)

-- 数据处理逻辑
insert into sink_table
select
 dim,
 count(*) as pv,
 sum(price) as sum_price,
 max(price) as max_price,
 min(price) as min_price,
 -- 计算 uv 数
 count(distinct user_id) as uv,
 UNIX_TIMESTAMP(CAST(tumble_start(row_time, interval '1' minute) AS STRING)) * 10
from source_table
group by
 dim,
 tumble(row_time, interval '1' minute)

Group Window Aggregation 滚动窗⼝的 SQL 语法,把 tumble window 的声明写在了 group by ⼦句中,即 tumble(row_time, interval ‘1’ minute) ,第⼀个参数为事件时间的时间戳,第⼆个参数为滚动窗⼝⼤⼩。

Window TVF ⽅案(1.13 只⽀持 Streaming 任务):

-- 数据源表
CREATE TABLE source_table (
 -- 维度数据
 dim STRING,
 -- ⽤户 id
 user_id BIGINT,
 -- ⽤户
 price BIGINT,
 -- 事件时间戳
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 -- watermark 设置
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '10',
 'fields.dim.length' = '1',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000',
 'fields.price.min' = '1',
 'fields.price.max' = '100000'
)

-- 数据汇表
CREATE TABLE sink_table (
 dim STRING,
 pv BIGINT,
 sum_price BIGINT,
 max_price BIGINT,
 min_price BIGINT,
 uv BIGINT,
 window_start bigint
) WITH (
 'connector' = 'print'
)

-- 数据处理逻辑
insert into sink_table
SELECT
 dim,
 UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 as window_start,
 count(*) as pv,
 sum(price) as sum_price,
 max(price) as max_price,
 min(price) as min_price,
 count(distinct user_id) as uv
FROM TABLE(TUMBLE(
 TABLE source_table
 , DESCRIPTOR(row_time)
 , INTERVAL '60' SECOND))
GROUP BY window_start, 
 window_end,
 dim

Windowing TVF 滚动窗⼝的写法把 tumble window 的声明写在了数据源的 Table ⼦句中,包含三部分参数:

TABLE(
TUMBLE(TABLE source_table, DESCRIPTOR(row_time), INTERVAL '60' SECOND)
) 

第⼀个参数 TABLE source_table 声明数据源表;

第⼆个参数 DESCRIPTOR(row_time) 声明数据源的时间戳字段;

第三个参数 INTERVAL ‘60’ SECOND 声明滚动窗⼝⼤⼩为 1 min。

实时场景 SQL 语义: 假设 Orders 为 kafka,target_table 也为 Kafka,这个 SQL ⽣成的实时任务,在执⾏时,会⽣成三个算⼦。

数据源算⼦(From Order):

连接到 Kafka topic,数据源算⼦⼀直运⾏,实时的从 Order Kafka 中⼀条⼀条的读取数据,然后⼀条⼀条发送给下游的 窗⼝聚合算⼦

窗⼝聚合算⼦(TUMBLE 算⼦):

接收到上游算⼦发的⼀条⼀条的数据,然后将每⼀条数据按照时间戳划分到对应的窗⼝中(根据事件时间、处理时间的不同语义进⾏划分),上述案例为事件时间,事件时间中,滚动窗⼝算⼦接收到上游的 Watermark ⼤于窗⼝的结束时间时,则说明当前这⼀分钟的滚动窗⼝已经结束了,将窗⼝计算完的结果发往下游算⼦(⼀条⼀条发给下游 数据汇算⼦ )

数据汇算⼦(INSERT INTO target_table):

接收到上游发的⼀条⼀条的数据,写⼊到 target_table Kafka 中

注意: 事件时间中滚动窗⼝的窗⼝计算触发是由 Watermark 推动的。

2.滑动窗⼝(HOP)

**滑动窗⼝定义:**滑动窗⼝是将元素指定给固定⻓度的窗⼝,与滚动窗⼝功能⼀样,也有窗⼝⼤⼩的概念,不⼀样的地⽅在于,滑动窗⼝有另⼀个参数控制窗⼝计算的频率(滑动窗⼝滑动的步⻓),如果滑动的步⻓⼩于窗⼝⼤⼩,则滑动窗⼝之间每个窗⼝是可以重叠,在这种情况下,⼀条数据就会分配到多个窗⼝当中。

**举例:**有 10 分钟⼤⼩的窗⼝,滑动步⻓为 5 分钟,每 5 分钟会划分⼀次窗⼝,这个窗⼝包含的数据是过去 10 分钟内的数据。

在这里插入图片描述

**应⽤场景:**计算同时在线的数据,要求结果的输出频率是 1 分钟⼀次,每次计算的数据是过去 5 分钟的数据(有的场景下⽤户可能在线,但是可能会 2 分钟不活跃,但是这也要算在同时在线数据中,所以取最近 5 分钟的数据就能计算进去了)

**实际案例:**分维度分钟级别同时在线⽤户数,1 分钟输出⼀次,计算最近 5 分钟的数据,Group Window Aggregation、Windowing TVF 两种⽅案

Group Window Aggregation ⽅案(⽀持 Batch\Streaming 任务):

CREATE TABLE source_table (
 -- 维度数据
 dim STRING,
 -- ⽤户 id
 user_id BIGINT,
 -- ⽤户
 price BIGINT,
 -- 事件时间戳
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 -- watermark 设置
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '10',
 'fields.dim.length' = '1',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000',
 'fields.price.min' = '1',
 'fields.price.max' = '100000'
);

-- 数据汇表
CREATE TABLE sink_table (
 dim STRING,
 uv BIGINT,
 window_start bigint
) WITH (
 'connector' = 'print'
);

-- 数据处理逻辑
insert into sink_table
SELECT dim,
UNIX_TIMESTAMP(
	CAST(
		hop_start(row_time, interval '1' minute, interval '5' minute) 
		AS STRING)
	) * 10,
count(distinct user_id) as uv
FROM source_table
GROUP BY dim
 , hop(row_time, interval '1' minute, interval '5' minute)

Group Window Aggregation 滚动窗⼝的写法把 hop window 的声明写在了 group by ⼦句中,即

hop(row_time, interval '1' minute, interval '5' minute) 

第⼀个参数为事件时间的时间戳字段;

第⼆个参数为滑动窗⼝的滑动步⻓;

第三个参数为滑动窗⼝⼤⼩。

Windowing TVF ⽅案(1.13 只⽀持 Streaming 任务):

-- 数据源表
CREATE TABLE source_table (
 -- 维度数据
 dim STRING,
 -- ⽤户 id
 user_id BIGINT,
 -- ⽤户
 price BIGINT,
 -- 事件时间戳
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 -- watermark 设置
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '10',
 'fields.dim.length' = '1',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000',
 'fields.price.min' = '1',
 'fields.price.max' = '100000'
);

-- 数据汇表
CREATE TABLE sink_table (
 dim STRING,
 uv BIGINT,
 window_start bigint
) WITH (
 'connector' = 'print'
);

-- 数据处理逻辑
insert into sink_table
SELECT
 dim,
 UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 as window_start, 
 count(distinct user_id) as bucket_uv
FROM TABLE(HOP(
 TABLE source_table
 , DESCRIPTOR(row_time)
 , INTERVAL '1' MINUTES, INTERVAL '5' MINUTES))
GROUP BY window_start, 
 window_end,
 dim

Windowing TVF 滑动窗⼝的写法把 hop window 的声明写在了数据源的 Table ⼦句中,即

TABLE(HOP(TABLE source_table, DESCRIPTOR(row_time), INTERVAL '1' MINUTES, INTERVAL '5' MINUTES))

第⼀个参数 TABLE source_table 声明数据源表;

第⼆个参数 DESCRIPTOR(row_time) 声明数据源的时间戳;

第三个参数 INTERVAL ‘1’ MINUTES 声明滚动窗⼝滑动步⻓⼤⼩为 1 min。

第四个参数 INTERVAL ‘5’ MINUTES 声明滚动窗⼝⼤⼩为 5 min。

3.Session 窗⼝

**Session 窗⼝定义:**Session 时间窗⼝和滚动、滑动窗⼝不⼀样,其没有固定的持续时间,如果在定义的间隔期(Session Gap)内没有新的数据出现,则 Session 就会窗⼝关闭。

在这里插入图片描述

**实际案例:**计算每个⽤户在活跃期间(⼀个 Session)总共购买的商品数量,如果⽤户 5 分钟没有活动,则视为 Session 断开

⽬前 1.13 版本中 Flink SQL 不⽀持 Session 窗⼝的 Window TVF,只介绍 Group Window Aggregation ⽅案。

Group Window Aggregation ⽅案(⽀持 Batch\Streaming 任务):

-- 数据源表,⽤户购买⾏为记录表
CREATE TABLE source_table (
 -- 维度数据
 dim STRING,
 -- ⽤户 id
 user_id BIGINT,
 -- ⽤户
 price BIGINT,
 -- 事件时间戳
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 -- watermark 设置
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '10',
 'fields.dim.length' = '1',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000',
 'fields.price.min' = '1',
 'fields.price.max' = '100000'
);

-- 数据汇表
CREATE TABLE sink_table (
 dim STRING,
 pv BIGINT, -- 购买商品数量
 window_start bigint
) WITH (
 'connector' = 'print'
);

-- 数据处理逻辑
insert into sink_table
SELECT
 dim,
 UNIX_TIMESTAMP(CAST(session_start(row_time, interval '5' minute) AS STRING)) * 10,
 count(1) as pv
FROM source_table
GROUP BY dim
 , session(row_time, interval '5' minute)

**注意:**上述 SQL 任务是在整个 Session 窗⼝结束之后才会把数据输出,Session 窗⼝⽀持 处理时间 和 事件时间,但是处理时间只⽀持在 Streaming 任务中运⾏,Batch 任务不⽀持。

Group Window Aggregation 中 Session 窗⼝的写法把 session window 的声明写在了 group by ⼦句中

session(row_time, interval '5' minute)

第⼀个参数为事件时间的时间戳;

第⼆个参数为 Session gap 间隔。

4.渐进式窗⼝(CUMULATE)

**渐进式窗⼝定义(1.13 只⽀持 Streaming 任务):**渐进式窗⼝可以认为是⾸先开⼀个最⼤窗⼝⼤⼩的滚动窗⼝,然后根据⽤户设置的触发的时间间隔将这个滚动窗⼝拆分为多个窗⼝,这些窗⼝具有相同的窗⼝起点和不同的窗⼝终点。

**示例:**从每⽇零点到当前这⼀分钟绘制累积 UV,其中 10:00 时的 UV 表示从 00:00 到 10:00 的 UV 总数。

在这里插入图片描述

**应⽤场景:**周期内累计 PV,UV 指标(如每天累计到当前这⼀分钟的 PV,UV),这类指标是⼀段周期内的累计状态。

**实际案例:**每天的截⽌当前分钟的累计 money(sum(money)),去重 id 数(count(distinct id)),每天代表渐进式窗⼝⼤⼩为 1 天,分钟代表渐进式窗⼝移动步⻓为分钟级别。

明细输⼊数据:

在这里插入图片描述

预期经过渐进式窗⼝计算的输出数据:

在这里插入图片描述

**特点:**每⼀分钟的输出结果都是当天零点累计到当前的结果,渐进式窗⼝只有 Windowing TVF ⽅案⽀持。

Windowing TVF ⽅案(1.13 只⽀持 Streaming 任务)

-- 数据源表
CREATE TABLE source_table (
 -- ⽤户 id
 user_id BIGINT,
 -- ⽤户
 money BIGINT,
 -- 事件时间戳
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 -- watermark 设置
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '10',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000',
 'fields.money.min' = '1',
 'fields.money.max' = '100000'
);

-- 数据汇表
CREATE TABLE sink_table (
 window_end bigint,
 window_start bigint,
 sum_money BIGINT,
 count_distinct_id bigint
) WITH (
 'connector' = 'print'
);

-- 数据处理逻辑
insert into sink_table
SELECT
 UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end, 
 window_start, 
 sum(money) as sum_money,
 count(distinct user_id) as count_distinct_id
FROM TABLE(CUMULATE(
 TABLE source_table
 , DESCRIPTOR(row_time)
 , INTERVAL '60' SECOND
 , INTERVAL '1' DAY))
GROUP BY
 window_start, 
 window_end

Windowing TVF 滚动窗⼝的写法把 cumulate window 的声明写在了数据源的 Table ⼦句中

TABLE(
	CUMULATE(
		TABLE source_table,
    DESCRIPTOR(row_time),
    INTERVAL '60' SECOND, INTERVAL '1' DAY)
) 

第⼀个参数 TABLE source_table 声明数据源表;

第⼆个参数 DESCRIPTOR(row_time) 声明数据源的时间戳;

第三个参数 INTERVAL ‘60’ SECOND 声明渐进式窗⼝触发的渐进步⻓为 1 min。

第四个参数 INTERVAL ‘1’ DAY 声明整个渐进式窗⼝的⼤⼩为 1 天,到了第⼆天新开⼀个窗⼝重新累计。

5.Window TVF ⽀持 Grouping Sets、Rollup、Cube

**应⽤场景:**多个维度组合(cube)计算,把每个维度写⼀遍 union all 起来麻烦⽽且会导致⼀个数据源读取多遍。

⽤ Grouping Sets 将维度组合写在⼀条 SQL 中,⽅便且执⾏效率⾼,⽬前 Grouping Sets 只在 Window TVF 中⽀持,不⽀持 Group Window Aggregation。

**示例:**计算每⽇零点累计到当前这⼀分钟的,分汇总、age、sex、age+sex 维度的⽤户数。

-- ⽤户访问明细表
CREATE TABLE source_table (
 age STRING,
 sex STRING,
 user_id BIGINT,
 row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)),
 WATERMARK FOR row_time AS row_time - INTERVAL '5' SECOND
) WITH (
 'connector' = 'datagen',
 'rows-per-second' = '1',
 'fields.age.length' = '1',
 'fields.sex.length' = '1',
 'fields.user_id.min' = '1',
 'fields.user_id.max' = '100000'
);

CREATE TABLE sink_table (
 age STRING,
 sex STRING,
 uv BIGINT,
 window_end bigint
) WITH (
 'connector' = 'print'
);

insert into sink_table
SELECT
 UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end,
 if (age is null, 'ALL', age) as age,
 if (sex is null, 'ALL', sex) as sex,
 count(distinct user_id) as bucket_uv
FROM TABLE(CUMULATE(
 TABLE source_table
 , DESCRIPTOR(row_time)
 , INTERVAL '5' SECOND
 , INTERVAL '1' DAY))
GROUP BY
 window_start, 
 window_end,
 -- grouping sets 写法
 GROUPING SETS (
 ()
 , (age)
 , (sex)
 , (age, sex)
 )

Flink SQL 中 Grouping Sets 的语法和 Hive SQL 的语法有不同,使⽤ Hive SQL 实现上述 SQL 的语义,实现如下:

insert into sink_table
SELECT
 UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end, 
 if (age is null, 'ALL', age) as age,
 if (sex is null, 'ALL', sex) as sex,
 count(distinct user_id) as bucket_uv
FROM source_table
GROUP BY
 age
 , sex
-- hive sql grouping sets 写法
GROUPING SETS (
 ()
 , (age)
 , (sex)
 , (age, sex)
)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在知识付费系统小程序开发中实现社区互动和用户参与

在知识付费系统小程序的开发中,实现社区互动和用户参与可以通过以下步骤实现: 1. 建立用户身份验证和管理系统 // 后端示例代码(Node.js) // 用户注册 app.post(/register, (req, res) > {const { username, email, passwor…

如何在电脑上制作可视化待办任务清单?

在现代高效工作的节奏下,上班族们需要管理大量的待办任务和工作事项。可视化的待办任务清单能够使我们清晰地了解自己的任务进度和工作优先级。每天打开电脑,我们可以直观地看到还有哪些任务需要完成,避免遗漏和混乱。而如何将这些任务清单可…

数据结构之堆的实现(图解➕源代码)

一、堆的定义 首先明确堆是一种特殊的完全二叉树,分为大根堆和小根堆,接下来我们就分别介绍一下这两种不同的堆。 1.1 大根堆(简称:大堆) 在大堆里面:父节点的值 ≥ 孩子节点的值 我们的兄弟节点没有限制&…

Nacos2.2.3版本运行startup.cmd出现闪退,无错误信息解决方法

Nacos2.2.3版本运行startup.cmd出现闪退,无错误信息解决方法 一、问题描述二、解决方法 一、问题描述 当我下载好nacos2.2.3版解压之后,直接双击startup.cmd出现闪退,而且 没有错误提示信息。后来经过一番搜索尝试,终于解决了自己…

Spring 中 @Qualifier 注解还能这么用?

今天想和小伙伴们聊一聊 Qualifier 注解的完整用法,同时也顺便分析一下它的实现原理。 说到 Qualifier,有的小伙伴可能会觉得诧异,这也只得写一篇文章?确实,但凡有点开发经验,多多少少可能都遇到过 Qualif…

《算法通关村—轻松搞定合并二叉树》

《算法通关村—轻松搞定合并二叉树》 描述 leetcode 617 给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵…

酒水展示预约小程序的效果如何

酒的需求度非常高,各种品牌、海量经销商组成了庞大市场,而在实际经营中,酒水品牌、经销商、门店经营者等环节往往也面临着品牌传播拓客引流难、产品展示预约订购难、营销难、销售渠道单一等痛点。 那么商家们应该怎样解决呢? 可以…

Vue3多页面开发实践

前言: 项目需求,把项目中的一个路由页面单摘出来作为一个新的项目。项目部署到服务器上后,通过一个链接的形式可以直接访问到新项目的页面。 解决方式: 使用Vue多页面方式打包项目 实现步骤: 1、在项目的src目录下&am…

MySQL(8):聚合函数

聚合函数介绍 聚合函数: 对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。 聚合函数类型:AVG(),SUM(),MAX(),MIN(),COUNT() AVG / SUM 只适用于数值类型的字段(或变量) SELECT AVG(…

【IK分词器安装】

安装IK分词器: 下载链接(如果es版本不同可以修改下版本号):https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip 通常下载是比较慢的:有需要可以从…

golang工程——opentelemetry简介、架构、概念、追踪原理

opentelemetry 简介 OpenTelemetry,简称OTel,是一个与供应商无关的开源可观测性框架,用于检测、生成、收集和导出 遥测数据,如轨迹、度量、日志。OTel的目标是提供一套标准化的供应商无关SDK、API和工具,用于接 收、…

Mean-Shift聚类方法

刘玉琪 跟随 出版于 台湾人工智能学院 一、说明 上一篇介绍了基于密度的分群方法——DBSCAN,本篇会介绍另一个分群方法——Mean Shift,与DBSCAN一样不需要预先知道欲分群的数量,而对于分群的形状也没有限制。 然而,这个方法是基…

网络层:控制平面

路由选择算法 路由选择算法就是为了在端到端的数据传输中,选择路径上路由器的最好的路径。通常,一条好的路径指具有最低开销的路径。最低开销路径是指源和目的地之间具有最低开销的一条路。 根据集中式还是分散式来划分 集中式路由选择算法&#xff1a…

基础Redis-Java客户端操作介绍

Java客户端操作介绍 2.基础-Redis的Java客户端a.介绍b.Jedisc.Jedis连接池d.SpringDataRedise.SpringDataRedis的序列化方式f.StringRedisTemplate 2.基础-Redis的Java客户端 a.介绍 Jedis 以Redis命令作为方法名称,学习成本低,简单实用。但是Jedis实例…

性能工作站,双十一大促,超值推荐:蝰蛇峡谷 NUC12SNKi7迷你主机,优惠抢购!

近年来,ITX主机和小型化系统变得越来越受欢迎。英特尔的NUC受到许多玩家们的关注。作为mini主机的代表NUC小巧设计和灵活性使它成为很多玩家和科技爱好者的选择。它的高性能和可玩性使得它在迷你型准系统市场上备受推崇。双11来临之际,我们分析下哪款高性…

【React】【react-globe.gl】3D Objects效果

目录 想要实现的效果实现过程踩坑安装依赖引入页面 想要实现的效果 示例地址 实现过程 踩坑 示例是通过script引入的依赖,但本人需要在react项目中实现该效果。按照react-globe.gl官方方法引入总是报错 Cant import the named export AmbientLight from non EcmaS…

前端的几种网络请求方式

网络请求 node编写接口 这里用到的几个包的作用 express:基于 Node.js 平台,快速、开放、极简的 Web 开发框架,官网:https://www.expressjs.com.cn/cors:用来解决跨域问题body-parser:可以通过 req.body…

Leetcode48旋转图像

思路:找规律 方法一、一般辅助数组解法 行列转换,第一行变到第三列,第二行变到第二列,第三行变到第一列 matrix[row][col] matrix[col][n-row-1] 然后复制回原数组 class Solution {public void rotate(int[][] matrix) {in…

Spring cloud负载均衡 @LoadBalanced注解原理

接上一篇文章,案例代码也在上一篇文章的基础上。 在上一篇文章的案例中,我们创建了作为Eureka server的Eureka注册中心服务、作为Eureka client的userservice、orderservice。 orderservice引入RestTemplate,加入了LoadBalanced注解&#x…

线性【SVM】数学原理和算法实现

一. 数学原理 SVM是一类有监督的分类算法,它的大致思想是:假设样本空间上有两类点,如下图所示,我们希望找到一个划分超平面,将这两类样本分开,我们希望这个间隔能够最大化来使得模型泛化能力最强。 如上图所…