BIO、NIO、AIO、Netty从简单理解到使用
Java编程中BIO、NIO、AIO是三种不同的I/O(输入/输出)模型,它们代表了不同的I/O处理方式。
Netty就是基于Java的NIO(New Input/Output)类库编写的一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。
先来了解一下基本的三种基本的io模型:
BIO(Blocking I/O,阻塞I/O)
定义:BIO是Java最传统的I/O模型,基于流的同步阻塞I/O操作。每个连接都会占用一个线程,当进行I/O操作时,线程会被阻塞,直到操作完成。
特点:
同步阻塞:每个I/O操作都会阻塞当前线程,直到操作完成。
线程占用:每个连接需要一个独立的线程,线程资源消耗较大。
实现简单:代码实现相对简单,易于理解和编写。
作用:适用于连接数较少且固定的架构,如传统的C/S架构。由于其实现简单、编程直观,因此在一些简单的网络编程场景中仍然被使用。
创建客户端和服务端演示数据接收与传输。
//服务端
public static void main(String[] args) {try (ServerSocket serverSocket = new ServerSocket(9999)) {while (true) {Socket socket = serverSocket.accept(); // 持续监听新连接new Thread(() -> { // 为每个客户端创建独立线程try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {String line;while ((line = reader.readLine()) != null) {System.out.println("客户端[" + socket.getPort() + "] 消息: " + line);}} catch (IOException e) {e.printStackTrace();}}).start();}} catch (IOException e) {e.printStackTrace();}}//客户端
public static void main(String[] args) {System.out.println("客户端启动...");try {//创建套接字Socket socket = new Socket("127.0.0.1", 9999);//获取输出流发送消息PrintStream ps = new PrintStream(socket.getOutputStream());Scanner sc = new Scanner(System.in);while (true){System.out.println("请输入信息:");ps.println(sc.nextLine());ps.flush();}} catch (IOException e) {throw new RuntimeException(e);}}
NIO(Non-blocking I/O,非阻塞I/O)
定义:NIO是Java 1.4引入的新I/O API,基于通道(Channel)和缓冲区(Buffer)的非阻塞I/O操作。
特点:
非阻塞:I/O操作不会阻塞线程,线程可以在等待数据时执行其他任务。
多路复用:通过Selector可以管理多个Channel,提高了资源利用率。
高性能:适用于高并发场景,减少线程开销和上下文切换。
核心组件:
缓冲区(Buffer):用于存储数据的固定大小的内存区域,提供了多种类型的缓冲区,如ByteBuffer、CharBuffer等。
通道(Channel):用于数据读写的通道,支持非阻塞模式,与缓冲区配合使用。
选择器(Selector):允许单个线程同时处理多个通道的I/O事件。
作用:适用于连接数较多且连接较短的架构,如高并发的服务器端应用。NIO提供了更高效、更灵活的I/O操作方式,显著提高了系统的并发性能和吞吐量。
//服务端public static void main(String[] args) throws Exception {//创建连接通道,ServerSocketChannel 绑定端口,监听新的客户端连接请求。它本身不处理任何数据传输。ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 设置通道为非阻塞模式serverSocketChannel.configureBlocking(false);//绑定端口serverSocketChannel.bind(new InetSocketAddress(9999));//创建 Selector 并注册 ACCEPT 事件Selector selector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("NIO 服务端启动...");//阻塞等待事件发生while (selector.select()>0){//获取到所有事件Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();//遍历所有事件while (iterator.hasNext()){SelectionKey key = iterator.next();//检查是否有新的连接请求if(key.isAcceptable()){//为每一个创建新的通道SocketChannel clientChannel = serverSocketChannel.accept();clientChannel.configureBlocking(false);clientChannel.register(selector,SelectionKey.OP_READ);}else if(key.isReadable()){//处理读数据SocketChannel channel = (SocketChannel)key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);int bytesRead = 0;while ((bytesRead = channel.read(byteBuffer)) > 0){byteBuffer.flip();String message = new String(byteBuffer.array(),0,bytesRead);System.out.println("接收客户端信息:"+message);byteBuffer.clear();//回写数据给客户端ByteBuffer response = ByteBuffer.wrap(("ECHO: " + message).getBytes());channel.write(response);}}iterator.remove();}}}//客户端
public static void main(String[] args) throws Exception {// 1. 创建 SocketChannel 并连接服务器SocketChannel socketChannel = SocketChannel.open();socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));socketChannel.configureBlocking(false); // 非阻塞模式System.out.println("NIO 客户端已连接");//接收线程new Thread(() -> {ByteBuffer buffer = ByteBuffer.allocate(1024);while (true) {try {int bytesRead = socketChannel.read(buffer);if (bytesRead > 0) {buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);System.out.println("收到服务端响应: " + new String(data));buffer.clear();}} catch (IOException e) {System.out.println("连接已断开");break;}}}).start();//发送消息ByteBuffer byteBuffer = ByteBuffer.allocate(1024);Scanner sc = new Scanner(System.in);while (true){System.out.println("请输入信息:");String msg = sc.nextLine();byteBuffer.put(("AA:"+msg).getBytes(StandardCharsets.UTF_8));byteBuffer.flip();socketChannel.write(byteBuffer);byteBuffer.clear();}}
AIO(Asynchronous I/O,异步I/O)
定义:AIO是Java 7引入的异步I/O API,基于异步通道(AsynchronousChannel)和异步回调机制。
特点:
异步非阻塞:I/O操作是异步的,通过回调处理结果,不阻塞线程。
回调机制:通过回调函数处理I/O操作结果,提高了程序的灵活性。
高性能:适用于高并发、高吞吐量的场景。
工作方式:
程序发起一个异步I/O请求,并提供一个回调函数。
程序无需等待I/O操作完成,而是立即返回,继续执行其他任务。
当I/O操作完成后,系统会调用之前提供的回调函数,传递结果或状态信息。
作用:适用于连接数较多且连接时间较长的架构,如高并发的服务器端应用。AIO提供了真正的异步I/O操作方式,进一步提高了系统的并发性能和吞吐量。
Netty
先了解一下netty出现的原因,是干嘛用的?
- Netty出现的原因:
Java NIO的复杂性:
Java NIO虽然提供了非阻塞IO的能力,但其API设计较为底层,使用起来比较复杂。开发者需要处理大量的细节,如选择器的管理、缓冲区的操作等,这增加了开发的难度和出错的风险。
性能瓶颈:
在高并发场景下,直接使用Java NIO进行网络编程可能会遇到性能瓶颈。例如,选择器的实现和多线程管理的复杂性可能导致性能下降。
缺乏高级功能:
Java NIO仅提供了基础的非阻塞IO机制,缺乏一些高级功能,如协议编解码、连接管理等。这些功能在开发网络应用时非常重要,但实现起来却相对复杂。
- Netty的具体用途是什么?
简化网络编程:
Netty封装了Java NIO的复杂性,提供了一套简洁易用的API。开发者可以使用这些API快速构建网络应用,而无需关注底层的细节。
提高性能:
Netty采用了异步非阻塞IO模型,并支持零拷贝等技术,可以在保证高性能的同时,减少CPU和内存资源的消耗。这使得Netty在高并发场景下表现尤为出色。
支持多种协议:
Netty内置了对多种协议的支持,如TCP、UDP、HTTP、WebSocket等。开发者可以轻松地使用这些协议构建网络应用,而无需自己实现协议编解码等复杂功能。
灵活的扩展性:
Netty提供了丰富的扩展点,如ChannelHandler、Codec等。开发者可以通过实现这些接口来扩展Netty的功能,以满足特定的业务需求。
广泛的应用场景:
Netty经过广泛的使用和验证,具有高稳定性和可靠性,适用于各种网络应用场景,如分布式系统、微服务架构中的通信组件、实时通讯系统、游戏服务器等。
它提供了丰富的错误处理和恢复机制,能够有效地处理网络通信中的各种异常情况。
netty核心优势:
异步事件驱动、零拷贝、内存池、高度可定制。
- 核心组件
先大概了解一下 Reactor 模型(单线程、多线程、主从多线程)。
因为Reactor 模式是 Netty 高性能和高并发能力的核心设计基础。Netty 的线程模型、事件驱动机制和异步非阻塞 I/O 都深度依赖 Reactor 模式。
Reactor 模式是一种 事件驱动的设计模式,用于处理高并发的 I/O 请求。其核心思想是 用一个或多个线程监听事件(如连接、读写请求),并将事件分发给对应的处理器异步处理,避免线程阻塞和资源浪费。
Reactor模型的核心组件
事件源(Event Source):指任何可以产生I/O事件的对象,例如网络连接、文件、设备等。
事件循环(Event Loop):Reactor模型的核心,负责监控所有事件源的状态,并在有事件发生时将其分发给相应的处理程序(即回调函数)。
事件处理器(Event Handler):处理特定事件的代码模块,通常实现为回调函数或方法。针对特定的事件源,每一个事件源通常都有一个相应的处理器,用于处理该事件源的I/O事件。
多路复用器(Demultiplexer):用于监视多个事件源并将发生的事件通知给Reactor。常见的实现包括Java的Selector、Linux的epoll等。
Reactor模型的实现方式
单Reactor单线程模型:所有操作(连接、读写)由一个线程完成。设计简单,但在高并发场景下容易成为性能瓶颈。
单Reactor多线程模型:Reactor线程负责监听和分发事件,而事件的处理则交给线程池中的工作线程完成。这种方式能够充分利用多核CPU的处理能力,但在高并发场景下,Reactor线程可能成为性能瓶颈。
主从Reactor多线程模型(Netty 默认模型-高并发):也称为多Reactor多线程模型。主Reactor线程负责监听和分发连接事件,当有新的连接到来时,将其分发给从Reactor线程处理。从Reactor线程负责监听和分发读写事件,并交给线程池中的工作线程处理。这种方式能够进一步提高系统的并发处理能力和可扩展性。
写个netty服务端示例看一下:
// 1. 创建主 Reactor(处理连接)管理一组 EventLoop,每个线程绑定一个 EventLoop(事件循环线程)
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 主线程组(通常 1 个线程)
// 2. 创建子 Reactor(处理 I/O)
EventLoopGroup workerGroup = new NioEventLoopGroup(); // 子线程组(默认 CPU 核数 × 2)//Reactor 模式配置入口 绑定主/子线程组、设置 Channel 类型
ServerBootstrap server = new ServerBootstrap();
server.group(bossGroup, workerGroup) // 绑定主从线程组.channel(NioServerSocketChannel.class) // 设置 Channel 类型(NIO)代表一个 Socket 连接或监听端口.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new ServerHandler()); // 添加业务处理器,这里需要自己实现}});// 3. 绑定端口并启动服务
ChannelFuture future = server.bind(8080).sync();
//等待服务器通道关闭
future.channel().closeFuture().sync();
//关闭通道
finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}//业务处理器
public class ServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("客户端连接成功...");}}
- 组件说明:
Channel:
在Netty中,Channel是一个核心概念,Channel提供了数据的读取和写入操作,以及与远程端点进行通信的能力。
通过Channel可以获取到很多信息,比如:本地地址、远程地址、Channel的EventLoop、Channel的Pipeline等。
Channel 生命周期:
channelRegistered (初始化操作)→ channelActive (连接)→ channelRead(数据接收) → channelInactive(断开)→ channelUnregistered(注销)
Selector:
Selector是Java NIO(New Input/Output)中的一个核心组件,用于监控多个Channel(通道)的状态,例如连接、读、写等事件。在netty中Selector被封装在NioEventLoop中,当Channel注册到Selector并指定感兴趣的事件类型(如连接、读、写等)后,会返回一个SelectionKey,用于表示Selector与Channel之间的关联关系。Selector会不断地轮询其注册的Channel,如果有事件发生,Selector会将相应的SelectionKey放入就绪事件集合中。事件循环线程会从就绪事件集合中取出SelectionKey,并根据事件类型调用相应的ChannelHandler进行处理。处理完成后,事件循环线程会将Channel放回到Selector中,继续等待下一次事件的发生。
EventLoopGroup:
管理一组 EventLoop,通常分为 bossGroup(处理连接)和 workerGroup(处理 I/O)。
配置线程数:new NioEventLoopGroup(4) 表示 4 个线程。
ServerBootstrap:
用于启动服务器端的引导类,配置服务器参数和处理器链配置、启动服务器、关闭服务器。
- 配置服务器参数:
线程模型:ServerBootstrap允许您配置两个主要的线程组:bossGroup和workerGroup。
bossGroup用于处理客户端的连接请求,而workerGroup用于处理已连接的客户端的I/O操作。
通道类型:通过channel方法,您可以指定服务器使用的通道类型。对于NIO传输,通常使用NioServerSocketChannel。
通道选项:使用option方法可以设置服务器通道的选项,如SO_BACKLOG(TCP连接请求的最大队列长度)和SO_REUSEADDR(允许地址重用)。
子通道选项:childOption方法用于设置已连接客户端的通道选项,如SO_KEEPALIVE(保持连接活动状态)。
Option:可以应用于Channel或Bootstrap上。
ChannelOption:专门用于配置Channel的参数。
- 处理器链配置:
父处理器:通过handler方法,您可以设置处理服务器通道I/O事件的处理器。这通常用于处理连接请求。
子处理器:childHandler方法用于设置处理已连接客户端I/O事件的处理器。这是开发者编写业务逻辑处理代码的地方,通常通过添加一系列的ChannelHandler来实现。
ChannelHandler
ChannelHandler是ChannelPipeline中的基本处理单元,负责处理或拦截入站和出站事件。每个ChannelHandler都有一个关联的ChannelHandlerContext,通过它可以方便地与其他组件进行交互。ChannelPipeline则是ChannelHandler的容器,负责ChannelHandler的管理和事件拦截。
pipeline、ChannelPipeline
Pipeline是ChannelPipeline的简称。ChannelPipeline用于处理网络事件和数据的流动。负责将一系列的处理逻辑(称为ChannelHandler)串联起来,形成一个处理链,对网络事件进行拦截和处理。
事件处理:ChannelPipeline负责处理入站(Inbound)和出站(Outbound)事件,如数据读取、数据写入、连接建立、连接断开等。
拦截器链:ChannelPipeline内部维护了一个拦截器链(或称为处理器链),每个拦截器(即ChannelHandler)都可以对事件进行处理或拦截。
动态性:ChannelPipeline允许在运行时动态地添加、删除或替换拦截器,从而灵活地扩展和定制网络处理逻辑。
-
启动服务器:
配置完成后,通过调用bind方法并传入服务器的端口号,ServerBootstrap将启动服务器并绑定到指定的端口。
bind方法返回一个ChannelFuture对象,您可以使用sync方法等待服务器启动完成。
ChannelFuture是Netty框架中特有的接口,继承自Java的Future接口。在Netty中,所有的I/O操作都是异步的,ChannelFuture用于在操作完成时通知应用程序,以便应用程序可以执行某些操作或检索操作的结果。 -
关闭:
当服务器需要关闭时,可以调用ChannelFuture对象的channel().closeFuture().sync()方法,等待服务器通道关闭。
最后,调用bossGroup和workerGroup的shutdownGracefully方法,以优雅地断开连接并关闭线程组。
ChannelHandlerContext:
ChannelHandlerContext封装了Channel和ChannelPipeline,使得ChannelHandler可以方便地访问和操作ChannelPipeline和Channel。
ChannelHandlerContext提供了许多方法,用于操作和传播事件,如写入数据、刷新数据、触发读事件等。
ChannelHandlerContext允许ChannelHandler将事件传递给ChannelPipeline中的下一个处理器。例如,当一个入站事件(如数据读取)发生时,ChannelHandlerContext可以调用fireChannelRead方法,将事件传递给下一个入站处理器。
相关文章:
BIO、NIO、AIO、Netty从简单理解到使用
Java编程中BIO、NIO、AIO是三种不同的I/O(输入/输出)模型,它们代表了不同的I/O处理方式。 Netty就是基于Java的NIO(New Input/Output)类库编写的一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可…...

计算机毕业设计SpringBoot+Vue.js工厂车间管理系统源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
一、图形图像的基本概念
文章目录 一、分辨率概念二、图形图像的区别三、位图和矢量图的区别 一、分辨率概念 图形显示计数中的分辨率概念有三种,即屏幕分辨率、显示分辨率和显卡分辨率。它们既有区别又有着密切的联系,对图形显示的处理有极大的影响。 1.屏幕分辨率 显示器分辨…...
前端跨域问题初探:理解跨域及其解决方案概览
在当今的Web开发中,跨域问题是一个常见且棘手的挑战 随着前端技术的不断进步,越来越多的应用需要从不同的域名、协议或端口获取资源 然而,浏览器的同源策略(Same-Origin Policy)限制了这种跨域请求,以确保…...
SQL分组问题
下列为电商公司用户访问时间数据 统计某个用户连续的访问记录,如果时间间隔小于60s,就分为一组 id ts 1001 17523641234 1001 17523641256 1002 17523641278 1001 17523641334 1002 17523641434 1001 17523641534 1001 17523641544 1002 17523…...
Oracle 数据库基础入门(二):深入理解表的约束
在 Oracle 数据库的学习进程中,表的约束是构建健壮、准确且高效数据库的关键要素。约束如同数据库的 “规则守护者”,它通过对数据的限制,确保了数据的完整性和一致性,就如同交通规则保障道路上车辆行驶的有序性一样。对于 Java 全…...

DeepSeek掘金——DeepSeek-R1驱动的房地产AI代理
DeepSeek掘金——DeepSeek-R1驱动的房地产AI代理 本文探讨如何使用 Smolagents 和 DeepSeek-R1 构建房地产代理,并利用工具进行网页抓取和数据导出。 AI 代理对于自动化复杂的推理任务至关重要。Smolagents 是由 Hugging Face 开发的轻量级 AI 代理框架,允许将大型语言模型 …...

WebP2P技术在嵌入式设备中的应用:EasyRTC音视频通话SDK如何实现高效通信?
在数字化时代,实时通信技术(RTC)与人工智能(AI)的融合正在重塑各个行业的交互方式。从在线教育到远程医疗,从社交娱乐到企业协作,RTC的应用场景不断拓展。然而,传统的RTC解决方案往往…...
【零基础到精通Java合集】第三集:流程控制与数组
针对**“流程控制与数组”**的15分钟课程内容设计,聚焦代码逻辑设计与数据结构基础: 课程标题:流程控制与数组(15分钟) 目标:掌握分支/循环语法与数组操作,能编写条件判断与数据遍历程序 一、课程内容与时间分配 0-2分钟 课程目标与逻辑导图 明确学习目标:分支结构、…...

VsCode + EIDE + OpenOCD + STM32(野火DAP) 开发环境配置
VsCode EIDE OpenOCD STM32(野火DAP) 开发环境配置 接受了新时代编辑器的我,实在受不了Keil的上古编辑页面,周树人说过:由奢入俭难,下面我们一起折腾一下开源软件Vscode, 用以开发51和STM32,有错误之处&…...
【vue-echarts】——01.认识echarts
文章目录 前言一、echarts二、使用步骤1.vue cli创建项目并安装第三方模块echarts2.显示图表总结前言 定制的数据可视化图表。ECharts最初由百度团队开源,并于2018年初捐赠给Apache基金会,成为ASF孵化级项目。2021年1月26日晚,Apache基金会官方宣布ECharts项目正式毕业。 一…...
【http://noi.openjudge.cn/】4.3算法之图论——1538:Gopher II
[【http://noi.openjudge.cn/】4.3算法之图论——1538:Gopher II] 题目 查看提交统计提问 总时间限制: 2000ms 内存限制: 65536kB 描述 The gopher family, having averted the canine threat, must face a new predator. The are n gophers and m gopher holes, each at di…...
Linux常见操作命令
Linux系统拥有丰富的命令行工具,通过这些命令可以高效地完成各种系统管理和日常操作任务。以下是一些常见的Linux操作命令: 文件和目录操作: - 创建目录:使用 mkdir 命令,例如 mkdir test 可以创建名为 test 的目录。如…...

Linux下测试Wifi性能——2.Linux下wifi指令
一、前言 相关知识大家看前一章节 Linux下测试Wifi性能——1.Wifi相关知识-CSDN博客 二、指令 1.查找可用网卡 iw dev 其中 接口名称(Interface) p2p0 和 wlan0 都是无线接口(网卡)的名称。 wlan0 是常见的无线局域网接口名…...

(十 九)趣学设计模式 之 中介者模式!
目录 一、 啥是中介者模式?二、 为什么要用中介者模式?三、 中介者模式的实现方式四、 中介者模式的优缺点五、 中介者模式的应用场景六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,…...
Leetcode 54: 螺旋矩阵
Leetcode 54: 螺旋矩阵 是一道经典的矩阵遍历模拟题目,要求我们以螺旋顺序遍历一个二维数组。这个问题在面试中非常经典,考察模拟、数组操作以及逻辑清晰度。掌握本题的高效解法可以迅速给面试官留下好印象。 适合面试的解法:边界法ÿ…...
abseil-cpp:环境搭建
参考: https://abseil.io/docs/cpp/quickstart-cmake abseil-cpp.git/dd4c89b abseil-cpp.git/20240722.1 1. clone代码仓库、编译 git clone https://github.com/abseil/abseil-cpp.git /app/abseil-cpp/ #/app/abseil-cpp/.git/config git checkout 20240722.1git rev-pa…...

Centos7部署k8s(单master节点安装)
单master节点部署k8s集群(Centos) 一、安装前准备 1、修改主机名 按照资源准备修改即可 # master01 hostnamectl set-hostname master01 ; bash # node1 hostnamectl set-hostname node1 ; bash # node2 hostnamectl set-hostname node2 ; bash2、修改hosts文件 以下命令所…...
RPA 职业前景:个人职场发展的 “新机遇”
1. RPA职业定义与范畴 1.1 RPA核心概念 机器人流程自动化(RPA)是一种通过软件机器人模拟人类操作,自动执行重复性、规则性任务的技术。RPA的核心在于其能够高效、准确地处理大量数据和流程,减少人工干预,从而提高工作…...
详解DeepSeek模型底层原理及和ChatGPT区别点
一、DeepSeek大模型原理 架构基础 DeepSeek基于Transformer架构,Transformer架构主要由编码器和解码器组成,在自然语言处理任务中,通常使用的是Transformer的解码器部分。它的核心是自注意力机制(Self - Attention),这个机制允许模型在处理输入序列时,关注序列中不同位…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...