Flink窗口机制

news2024/11/16 1:43:41

1.窗口的概念

在这里插入图片描述

时间是为窗口服务的。窗口是什么?为什么会有窗口呢?
(1)Flink要处理的数据,一般是从Kafka过来的流式数据,如果只是单纯地统计流的数据量,是没办法统计的。
(2)所以,要人为的 加上了一个时间区间限制(窗口),才可以进行统计。

2.窗口的分类

2.1滚动窗口(tumble)

2.1.1 sql版

窗口大小 = 滑动距离。
它的窗口是紧密排布的,中间没有任何的数据重复和丢失。
在这里插入图片描述

--创建表
CREATE TABLE source_table ( 
 user_id STRING, 
 price BIGINT,
 `timestamp` bigint,
 row_time AS TO_TIMESTAMP(FROM_UNIXTIME(`timestamp`)),
 watermark for row_time as row_time - interval '0' second
) WITH (
  'connector' = 'socket',
  'hostname' = 'node1',        
  'port' = '9999',
  'format' = 'csv'
);

--语法
tumble(row_time,时间间隔),比如,如下的sql
tumble(row_time,interval '5' second),每隔5秒滚动一次。

--业务查询逻辑(传统方式)
select 
user_id,
count(*) as pv,
sum(price) as sum_price,
UNIX_TIMESTAMP(CAST(tumble_start(row_time, interval '5' second) AS STRING)) * 1000  as window_start,
UNIX_TIMESTAMP(CAST(tumble_end(row_time, interval '5' second) AS STRING)) * 1000  as window_end
from source_table
group by
    user_id,
    tumble(row_time, interval '5' second);

--TVF写法
--语法,跟3个参数:
--参数1:表名
--参数2:表中事件时间列
--参数3:窗口大小
from table(tumble(table source,descriptor(row_time),interval '5' second))
--sql为:
SELECT 
    user_id,
    UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 as window_start,
    UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end,
    sum(price) as sum_price
FROM TABLE(TUMBLE(
        TABLE source_table
        , DESCRIPTOR(row_time)
        , INTERVAL '5' SECOND))
GROUP BY window_start, 
      window_end,
      user_id;
--window_start,window_end是新写法的关键字

在这里插入图片描述

在事件时间下,窗口的划分是根据第一条事件时间来划分的,只有等数据来了才会创建窗口。

计算公式 = 事件时间   - (事件时间 % 窗口大小)
刚刚的案例中,第一条数据的事件时间为1,窗口大小为5
1 - (1 % 5) = 0,所以,窗口的起始是从0开始。
由于窗口的大小是5秒,因此,后面的窗口排布就是:
[0,5)
[5,10)
[10,15)

什么时候触发计算呢?
在事件时间下,窗口的触发计算就是窗口结束 - 1(毫秒)。

比如上面的窗口是[0,5),结束的点就是5 * 1000 - 1 = 4999。

所以,我们输入5秒的时候,会触发窗口内的数据计算。

2.1.2 DataStream API版

开发步骤:
//1.创建流式执行环境
//2.数据源
//3.数据处理
	//3.1数据map转换操作,转成Tuple3
	//3.2把Tuple3的数据添加Watermark(monotonousTimestamps)
	前两个目的是为了指定时间列(才能根据这一列进行窗口的划分)
	//3.3把数据根据id进行分组
	//3.4分组之后,设置滚动事件时间窗口,并且制定窗口大小为5秒钟
	//3.5对窗口内的数据进行sum操作
	//3.6把Tuple3转成了Tuple2(取id和sum的值)
//4.数据输出
//5.启动流式任务
package flink.test;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class tests {
    public static void main(String[] args) throws Exception {
        // TODO:  1.创建流式执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        // TODO: 2.数据源
        DataStreamSource<String> source = env.socketTextStream("node1", 9999);

        // TODO: 3.处理数据
        //分配窗口,创建窗口就有水位线,不需要就设置为0,类似于sql版
        /**
         * WatermarkStrategy的策略有四种:
         * forMonotonousTimestamps,单调递增水印
         * forBoundedOutOfOrderness,允许乱序数据(数据迟到)的水印
         * forGenerator,自定义水印
         * noWatermarks,没有水印
         *
         * ---
         * (1)map转换得到 每一行对应的列
         * (2)通过 .assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps() 来创建窗口
         * (3) .withTimestampAssigner() 来指定哪一列来表示时间列(才能根据这一列进行窗口的划分)
         */
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> mapAndWatermarkStream = source.map(new MapFunction<String, Tuple3<String, Integer, Long>>() {
            @Override
            public Tuple3<String, Integer, Long> map(String s) throws Exception {
                String[] lines = s.split(",");
                /**
                 * lines分为3个字段:String id,Integer price,Long ts 所有要类型转换一下
                 */
                return Tuple3.of(lines[0], Integer.valueOf(lines[1]), Long.valueOf(lines[2]));
            }
        }).assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps().withTimestampAssigner(
                new SerializableTimestampAssigner<Tuple3<String, Integer, Long>>() {
                    @Override
                    public long extractTimestamp(Tuple3<String, Integer, Long> element, long l) {
                        //这个方法用于标记 哪一列是表示时间戳
                        return element.f2 * 1000L;
                    }
                }));
        mapAndWatermarkStream.print("原数据:");
        //数据分组 sql group by
        KeyedStream<Tuple3<String, Integer, Long>, String> keybyStream = mapAndWatermarkStream.keyBy(value -> value.f0);
        //划分窗口和统计  指定窗口的大小,再sum  ---》类似与离线 sql  where条件限制范围 time between  20240101 and 20240107(比如说求一周内的某个指标) 和 select中的 sum
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> result = keybyStream.window(TumblingEventTimeWindows.of(Time.seconds(5)))
                .sum(1)
                .returns(Types.TUPLE(Types.STRING, Types.INT));

        // TODO: 4.数据输出
        result.printToErr("聚合后的数据:");
        // TODO: 5.启动流式任务
        env.execute();

    }
}

数据输出和结果输出:
在这里插入图片描述
在这里插入图片描述

2.2滑动窗口(hop)

滑动窗口 :滑动距离 不等于 窗口大小。

(1)如果滑动距离<窗口大小===>数据重复;

(2)如果滑动距离=窗口大小===>滚动窗口(没有任何的数据重复和丢失);

(3)如果滑动距离>窗口大小===>数据丢失(不考虑)!!!
在这里插入图片描述

2.2.1 sql版

--创建表
CREATE TABLE source_table ( 
 user_id STRING, 
 price BIGINT,
 `timestamp` bigint,
 row_time AS TO_TIMESTAMP(FROM_UNIXTIME(`timestamp`)),
 watermark for row_time as row_time - interval '0' second
) WITH (
  'connector' = 'socket',
  'hostname' = 'node1',        
  'port' = '9999',
  'format' = 'csv'
);

--语法
hop(事件时间列,滑动间隔,窗口大小)
hop(row_time,interval '2' second, interval '5' second)

--业务SQL
SELECT user_id,
UNIX_TIMESTAMP(CAST(hop_start(row_time, interval '2' SECOND, interval '5' SECOND) AS STRING)) * 1000 as window_start,
UNIX_TIMESTAMP(CAST(hop_end(row_time, interval '2' SECOND, interval '5' SECOND) AS STRING)) * 1000 as window_end, 
    sum(price) as sum_price
FROM source_table
GROUP BY user_id
    , hop(row_time, interval '2' SECOND, interval '5' SECOND);--每隔两秒滑动一次


--TVF写法
--table:表名
--descriptor:事件时间列
--滑动距离:interval 2 second
--窗口大小:interval 5 second
from table(hop(table 表名,descriptor(事件时间列),滑动间隔,窗口大小))
from table(hop(table source,descriptor(row_time),interval '2' second,interval '5' second))

--sql为:
SELECT 
    user_id,
UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 as window_start,  
UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end, 
    sum(price) as sum_price
FROM TABLE(HOP(
        TABLE source_table
        , DESCRIPTOR(row_time)
        , interval '2' SECOND, interval '6' SECOND))
GROUP BY window_start, 
      window_end,
      user_id;


数据输入和运行结果如下:

在这里插入图片描述

在这里插入图片描述
说明:

(1)事件时间1的到来,会让窗口仅限排布(划分),划分的窗口如下:

[-2,3],[0,5],[2,7],[4,9]

(2)窗口每隔两秒滑动一次,所以会有数据重复计算。

2.2.2 DataStream API版

package flink.test;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class Demo02_SlideWindow {
    public static void main(String[] args) throws Exception {
        //1.创建流式执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        //2.数据源
        DataStreamSource<String> source = env.socketTextStream("node1", 9999);
        //3.数据处理
        //3.1数据map转换操作,转成Tuple3
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> mapStream = source.map(value -> {
            /**
             * 由一行数据中,用逗号进行切分【id,price,ts】
             * String id
             * Integer price
             * Long ts
             */
            String[] lines = value.split(",");
            return Tuple3.of(lines[0], Integer.valueOf(lines[1]), Long.parseLong(lines[2]));
        }).returns(Types.TUPLE(Types.STRING, Types.INT, Types.LONG));
        //3.2把Tuple3的数据添加Watermark(monotonousTimestamps)
        /**
         * WatermarkStrategy生成水印的策略有四种:
         * forMonotonousTimestamps,单调递增水印(用的次多)
         * forBoundedOutOfOrderness,运行数据迟到(乱序)(用的最多)
         * forGeneric,自定义水印(不用)
         * noWatermark,没有水印(不用)
         */
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> watermarks = mapStream.assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps()
                .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, Long>>() {
                    @Override
                    public long extractTimestamp(Tuple3<String, Integer, Long> element, long recordTimestamp) {
                        return element.f2 * 1000L;
                    }
                }));
        //3.3把数据根据id进行分组
        watermarks.print("源数据:");
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> sumStream = watermarks.keyBy(value -> value.f0)
                //3.4分组之后,设置滑动事件时间窗口,并且制定窗口大小为5秒钟,滑动间隔为2秒。
                /**
                 * SlidingEventTimeWindows,滑动事件时间窗口,带2个参数:
                 * 参数1:窗口大小
                 * 参数2:滑动间隔
                 */
                .window(SlidingEventTimeWindows.of(Time.seconds(5), Time.seconds(2)))
                //3.5对窗口内的数据进行sum操作
                .sum(1);
        //3.6把Tuple3转成了Tuple2(取id和sum的值)
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = sumStream.map(value -> Tuple2.of(value.f0, value.f1))
                .returns(Types.TUPLE(Types.STRING,Types.INT));
        //4.数据输出
        result.printToErr("聚合后的数据:");
        //5.启动流式任务
        env.execute();
    }
}


数据输入和结果输出:
在这里插入图片描述
在这里插入图片描述

2.3会话窗口(session)

会话窗口:在一个会话周期内,窗口的数据会累积,超过会话周期就会触发窗口的计算,同时开辟下一个新窗口。
注意:

数据本身的事件时间大于窗口间隔,才会触发当前窗口的计算。
在这里插入图片描述

2.3.1 sql版

--创建表
CREATE TABLE source_table ( 
 user_id STRING, 
 price BIGINT,
 `timestamp` bigint,
 row_time AS TO_TIMESTAMP(FROM_UNIXTIME(`timestamp`)),
 watermark for row_time as row_time - interval '0' second
) WITH (
  'connector' = 'socket',
  'hostname' = 'node1',        
  'port' = '9999',
  'format' = 'csv'
);

--语法
session(事件时间列,窗口间隔)
session(row_time,interval '5' second)

--业务SQL
SELECT 
    user_id,
UNIX_TIMESTAMP(CAST(session_start(row_time, interval '5' SECOND) AS STRING)) * 1000 as window_start,
UNIX_TIMESTAMP(CAST(session_end(row_time, interval '5' SECOND) AS STRING)) * 1000 as window_end, 
    sum(price) as sum_price
FROM source_table
GROUP BY user_id
      , session(row_time, interval '5' SECOND);


!!!会话窗口没有TVF写法。

数据输入和结果输出:
在这里插入图片描述

在这里插入图片描述

2.3.2 DataStream API版

package flink.test;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.EventTimeSessionWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class Demo03_SessionWindow {
    public static void main(String[] args) throws Exception {
        //1.创建流式执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        //2.数据源
        DataStreamSource<String> source = env.socketTextStream("node1", 9999);
        //3.数据处理
        //3.1数据map转换操作,转成Tuple3
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> mapStream = source.map(new MapFunction<String, Tuple3<String, Integer, Long>>() {
            @Override
            public Tuple3<String, Integer, Long> map(String value) throws Exception {
                /**
                 * String id
                 * Integer price
                 * Long ts
                 */
                String[] lines = value.split(",");
                return Tuple3.of(lines[0], Integer.valueOf(lines[1]), Long.parseLong(lines[2]));
            }
        });
        //3.2把Tuple3的数据添加Watermark(monotonousTimestamps)
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> watermarks = mapStream
                .assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps()
                .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, Long>>() {
            @Override
            public long extractTimestamp(Tuple3<String, Integer, Long> element, long recordTimestamp) {
                return element.f2 * 1000L;
            }
        }));
        watermarks.print("源数据:");
        //3.3把数据根据id进行分组
        //3.4分组之后,设置会话事件时间窗口,并且指定窗口间隔为5秒钟。
        //3.5对窗口内的数据进行sum操作
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> sumStream = watermarks.keyBy(value -> value.f0)
                .window(EventTimeSessionWindows.withGap(Time.seconds(5)))
                .sum(1);
        //3.6把Tuple3转成了Tuple2(取id和sum的值)
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = sumStream.map(value -> Tuple2.of(value.f0, value.f1)).returns(Types.TUPLE(Types.STRING, Types.INT));
        //4.数据输出
        result.printToErr("聚合后的结果:");
        //5.启动流式任务
        env.execute();
    }
}

数据输入和结果输出:
在这里插入图片描述

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

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

相关文章

2024蓝桥杯每日一题(组合计数)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;计算系数 试题二&#xff1a;求组合数1 试题三&#xff1a;求组合数2 试题四&#xff1a;杨辉三角形 试题一&#xff1a;计算系数 【题目描述】 给定一个多项式 (axby)k&#xff0c;请…

Google Earth Engine 洪水制图 - 使用 Sentinel-1 SAR GRD

Sentinel-1 提供从具有双极化功能的 C 波段合成孔径雷达 (SAR) 设备获得的信息。该数据包括地面范围检测 (GRD) 场景,这些场景已通过 Sentinel-1 工具箱进行处理,以创建经过校准和正射校正的产品。该集合每天都会更新,新获得的资产会在可用后两天内添加。 该集合包含所有 G…

【研发管理】产品经理知识体系-产品创新管理

导读&#xff1a; 产品创新管理对企业的发展具有深远的影响&#xff0c;它不仅是企业保持竞争优势的关键&#xff0c;也是推动企业持续稳定发展的重要动力。因此&#xff0c;企业应高度重视产品创新管理&#xff0c;并采取有效的策略和方法来推动产品创新活动的开展。对于产品经…

.NET 邮件发送 SMTP邮件发送

SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;是用于电子邮件传输的规则集&#xff0c;可以从邮件客户端向接收电子邮件服务器发送、中继或转发邮件。发件人可使用SMTP 服务器来执行发送电子邮件的过程。SMTP服务器则是按照这些规则中转电子邮件的服务器。 IMAP…

Java web应用性能分析之【MySQL安装注意事项】

本文主要是针对以前LAMP&#xff0c;以及默认用apt安装的mysql。数据文件、日志文件都在一起&#xff1b;innodb_buffer_pool默认用128M。如果你排查问题&#xff0c;最后发现是因为mysql的安装配置不对&#xff0c;是否一口老血要喷出来。同时给MySQL数据库安装做参考。 关于M…

Docker - HelloWorld

原文地址&#xff0c;使用效果更佳&#xff01; Docker - HelloWorld | CoderMast编程桅杆https://www.codermast.com/dev-tools/docker/docker-helloworld.html 开始之前 在学习本小节之前&#xff0c;你必须确保你正确安装了 Docker&#xff0c;正确安装 Docker 是后续学习的…

【树莓派学习】hello,world!

系统安装及环境配置详见【树莓派学习】系统烧录及VNC连接、文件传输-CSDN博客 树莓派内置python3&#xff0c;可以直接利用python输出。

linux中如何挂载yum云仓库进行软件的安装

1.首先在根目录下建立文件&#xff0c;用来挂载镜像文件 [rootclient ~]# mkdir /rhel9 2.挂载镜像文件&#xff1a; [rootclient ~]# mount /dev/cdrom /rhel9 3.切换到 /etc/yum.repos.d 下的目录并查看 &#xff0c;创建 rhel9.repo文件&#xff0c;并编辑云仓库域名&am…

基于机器学习的车辆状态异常检测

基于马氏距离的车辆状态异常检测&#xff08;单一传感器&#xff09; 基于多元自动编码器的车辆状态异常检测 基于单传感器平滑马氏距离的车辆状态异常检测 工学博士&#xff0c;担任《Mechanical System and Signal Processing》等期刊审稿专家&#xff0c;擅长领域&#xff1…

HCIP-Datacom-ARST必选题库_10_IPv4【1道题】

一、单选 1.IPV4报文发送方式包括哪三种? 任意播组播单播广播 2.如图所示是一个IP报文头部,则以下说法正确的是? 协议号51,代表该IPHeader后的报文为AH头部 该报文一定是只有AH装的IPsecVPN报文 协议号51,代表该IPHeader后的报文为ESP头部 该报文为Ipsec VPN报文,并且该报文…

【NRND】SCT2401 4.5V-40V输入,600mA同步降压DCDC变换器,建议使用LGS5148替代

DCDC丝印2401替代原因&#xff1a; 国产器件未提供中文说明书&#xff0c;截止到2024年4月20日。 批量价格约9毛&#xff0c;比LGS5148贵50%&#xff0c;且输入电压没有LGS5148高&#xff0c;而LGS5148还提供了中文说明书。 2者引脚定义相同。 LGS5148详情请点此处打开CSDN连接…

知道做到 一篇总结学习方法的笔记

元数据 [!abstract] 知道做到&#xff1a;跃迁式学习 书名&#xff1a; 知道做到&#xff1a;跃迁式学习作者&#xff1a; 彼得•霍林斯简介&#xff1a; 学习是改善你的生活环境、成为你想成为的人的关键。科学的方法能加速学习进程&#xff0c;让你事半功倍。技能、信息和能力…

linux下摄像头设置固定的设备名

目录 2.热插拔udev机制 3.设置udev的规则 1.查看usb ID 2. 查看usb设备的信息 3.编译规则 4.拓展 1.问题的出现 通过我之前的文章配置完摄像头的开机自启动之后我们会发现有的时候会出现启动不了的情况&#xff0c;通过实验我发现是摄像头的设备名发生了改变&#xff0c;…

如何打开局域网共享?

局域网共享是一种方便实现文件共享、打印共享和资源访问的技术。通过局域网共享&#xff0c;不同设备之间可以方便地共享文件和资源&#xff0c;提高工作效率和便利性。在网络环境中&#xff0c;使用天联组网工具可以更加快速地实现局域网共享&#xff0c;解决不同地区间的远程…

数据仓库作业五:第8章 关联规则挖掘

目录 第8章 关联规则挖掘作业题 第8章 关联规则挖掘 作业题 1、设4-项集 X { a , b , c , d } X\{a,b,c,d\} X{a,b,c,d}&#xff0c;试求出由 X X X 导出的所有关联规则。 解&#xff1a; 首先生成项集的所有非空真子集。这包括&#xff1a; { a } , { b } , { c } , {…

Java测试编程题

题目1 1.创建5个线程对象 线程名设置为&#xff08;Thread01&#xff0c;Thread02&#xff0c;Thread03&#xff0c;Thread04&#xff0c;Thread05&#xff09;使用 代码实现5个线程有序的循环打印&#xff0c;效果如下&#xff1a; Thread01正在打印1 Thread02正在打印2 Threa…

【做一名健康的CSDNer】

程序员由于工作性质&#xff0c;常常需要长时间面对电脑&#xff0c;这可能对身心健康带来挑战。以下是一些实用的建议&#xff0c;帮助程序员保持身心健康&#xff1a; 规律生活&#xff1a;建立健康的生活习惯&#xff0c;包括规律的作息时间和固定的饮食时间&#xff0c;保证…

2024 年选择安全运营中心 (SOC) 工具指南

安全运营中心 (SOC) 是对抗网络威胁的前线。他们使用各种安全控制措施来监控、检测和快速响应任何网络威胁。这些控制措施对于确保信息系统全天候安全至关重要。 大型组织中的现代 SOC 与各种安全供应商合作&#xff0c;处理 75 到 100 种不同的工具。让我们探讨一下您可能遇到…

操作教程丨MaxKB+Ollama:快速构建基于大语言模型的本地知识库问答系统

2024年4月12日&#xff0c;1Panel开源项目组正式对外介绍了其官方出品的开源子项目——MaxKB&#xff08;github.com/1Panel-dev/MaxKB&#xff09;。MaxKB是一款基于LLM&#xff08;Large Language Model&#xff09;大语言模型的知识库问答系统。MaxKB的产品命名内涵为“Max …

二维图像的双线性插值

1. 原理 见下图,假设原图为单通道的灰度图,想求图像中某点Q(x,y)的灰度值。 2. 代码实现 #include <iostream> #include <stdio.h> #include <stdint.h> #include <string> #include<opencv2/opencv.hpp> #include<opencv2/core.hpp>…