缓冲区的奥秘:解析数据交错的魔法
目录
一、理解缓存区的好处
(一)直观性的理解
(二)缓存区的好处
二、经典案例分析体会
(一)文件读写流(File I/O Buffering)
BufferedOutputStream 和 BufferedWriter 可以加快写入的速度
BufferedInputStream 和 BufferedReader 可以加快读取字符的速度
(二)日志缓冲(Logging Buffering)
三、案例回顾和优化方向分析
四、Kafka缓存区优化思考
(一)Kafka 的生产者,有可能会丢数据吗?
(二)Kafka 生产者会影响业务的高可用吗?
五、总结
参考文章
干货分享,感谢您的阅读!
在计算机科学的广袤世界里,有一项看似简单却又深奥无比的技术,那就是缓冲。缓冲,像是隐藏在代码背后的魔法,它默默地改变着数据的流动,使得看似杂乱无章的操作变得井然有序。然而,它的本质并非只是简单的数据暂存,而是一种艺术,一门科学。
一、理解缓存区的好处
(一)直观性的理解
在Java虚拟机(JVM)中,堆内存扮演了一个重要的角色,用于存储动态分配的对象。当代码执行时,不断地在堆空间中创建新的对象,这些对象会暂时存放在堆中,直到不再需要时才被垃圾回收器回收。这个过程就像是在一个巨大的缓存中存储着各种数据。
垃圾回收器进程则负责在后台默默地进行垃圾回收,清理不再被引用的对象,释放内存空间。这就像是在缓存中进行定期的清理和整理,以保持缓存的有效性和性能。
所以,JVM的堆空间可以被视为一个巨大的缓存,它存储着临时的对象数据,并且由垃圾回收器进程来管理和维护。这个例子很好地展示了缓存的概念,即通过暂存数据来提高系统的效率和性能,同时保持数据的一致性和可用性。
生活化一些的,想象每年过大年你和大家庭的亲人们正在一起包饺子,每个人都有不同的任务。有的人负责擀面皮,有的人负责包馅料,还有的人负责煮饺子。但是,大家的速度并不总是一致的,有时候有人擀好了面皮,但包馅的还没准备好,有时候包馅的准备好了,但煮饺子的还在忙其他的事情。
这时,你们决定在中间放一个大盆子,就像是一个缓冲区一样。每当有人完成了自己的任务,就把成果放进盆子里,而需要下一个任务的人则从盆子里取出材料进行下一步操作。这样一来,即使大家的速度不一致,也不会影响整个过程的进行,每个人都可以按照自己的节奏进行操作,保持了整个包饺子过程的顺畅进行。
(二)缓存区的好处
无论是在生活中还是在程序设计中,缓冲区都扮演着类似的角色,平衡了不同速度之间的数据流动,保证了整个过程的顺畅进行。总结下缓冲区的好处:
好处 | 描述 |
---|---|
平衡数据流速度差异 | 缓冲区可以暂时存储数据,平衡生产者和消费者之间的速度差异,防止数据丢失或处理延迟。 |
降低系统开销 | 通过批量处理数据,减少频繁的数据交互和I/O操作,降低系统的开销,提高系统效率。 |
提高系统性能 | 缓冲区优化数据处理方式,减少等待时间,提高系统的响应速度,从而提高系统性能。 |
保护数据一致性 | 缓冲区暂存数据,直到数据传输或处理完成,保护数据的一致性,避免数据丢失或损坏。 |
优化用户体验 | 在音视频播放或网络通信等应用场景中,提前缓冲数据可以实现流畅的用户体验,提高用户满意度。 |
二、经典案例分析体会
我们将介绍几个经典的缓冲区应用案例,并分析它们的优势和适用场景:
案例 | 前提描述 | 描述 |
---|---|---|
文件读写流(File I/O Buffering) | 当需要进行大量文件读写操作时,可以使用缓冲区来提高性能。 | 在文件读写操作中使用缓冲区来提高性能。将文件内容暂存到内存缓冲区中,减少对磁盘的频繁访问。写入数据时,也可以暂存到缓冲区,减少磁盘I/O操作次数。 |
网络数据传输缓冲(Network Data Transfer Buffering) | 在进行网络数据传输时,为了提高效率和稳定性,可以使用缓冲区来缓存发送和接收的数据。 | 在网络通信中使用缓冲区来缓存发送和接收的数据,提高网络数据传输的效率和稳定性。发送端和接收端都可以利用缓冲区来优化数据传输。 |
日志缓冲(Logging Buffering) | 当系统需要进行日志记录,并且对系统性能有一定要求时,可以使用日志缓冲区来优化日志写入操作。 | 在软件系统中使用日志缓冲区来减少对系统性能的影响。将待写入的日志信息暂存到缓冲区中,定期批量写入日志文件,减少磁盘I/O操作,提高系统性能。 |
内存缓存(Memory Caching) | 当系统需要频繁访问某些数据,并且对数据访问速度有较高要求时,可以使用内存缓存来提高数据访问速度。 | 使用内存缓存来暂存频繁访问的数据,提高数据访问速度和效率。比如,Web服务器可以将经常访问的网页内容暂存到内存中,减少磁盘访问,提高网页访问速度。 |
选取其中的两个可以展开进行分析体会。
(一)文件读写流(File I/O Buffering)
缓冲在 Java 语言中被广泛应用,在 IDEA 中搜索*buffer,可以看到长长的类列表,其中最典型的就是文件读取和写入字符流。
Java 的 I/O 流设计,采用的是装饰器模式,当需要给类添加新的功能时,就可以将被装饰者通过参数传递到装饰者,封装成新的功能方法。
Java的I/O库中提供了许多装饰器类,如BufferedInputStream和BufferedOutputStream,它们通过装饰器模式来给输入流和输出流添加额外的功能,比如缓冲功能。
一般情况下,在读取和写入流的 API 中,BufferedInputStream 和 BufferedReader 可以加快读取字符的速度,BufferedOutputStream 和 BufferedWriter 可以加快写入的速度。
BufferedOutputStream 和 BufferedWriter 可以加快写入的速度
以BufferedWriter为例分析,当需要写入字符时,使用BufferedWriter
相对于直接使用FileWriter
可以提供更高的写入速度,因为BufferedWriter
内部使用了缓冲区,能够一次写入多个字符,减少了频繁的系统调用和磁盘访问次数。我们可以通过对比使用BufferedWriter
和直接使用FileWriter
的写入速度:
package org.zyf.javabasic.io;import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;/*** @program: zyfboot-javabasic* @description: 使用BufferedWriter相对于直接使用FileWriter可以提供更高的写入速度* @author: zhangyanfeng* @create: 2024-05-26 17:28**/
public class BufferedWriterIOExample {private static final String FILE_PATH = "example.txt";private static final String CONTENT = "This is a test content. ";public static void main(String[] args) {long startTime, endTime;// 测试直接使用FileWriter写入字符startTime = System.currentTimeMillis();try (FileWriter fileWriter = new FileWriter(FILE_PATH)) {for (int i = 0; i < 100000; i++) {fileWriter.write(CONTENT);}} catch (IOException e) {e.printStackTrace();}endTime = System.currentTimeMillis();System.out.println("直接使用FileWriter写入字符耗时:" + (endTime - startTime) + " 毫秒");// 测试使用BufferedWriter写入字符startTime = System.currentTimeMillis();try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(FILE_PATH))) {for (int i = 0; i < 1000000; i++) {bufferedWriter.write(CONTENT);}} catch (IOException e) {e.printStackTrace();}endTime = System.currentTimeMillis();System.out.println("使用BufferedWriter写入字符耗时:" + (endTime - startTime) + " 毫秒");}
}
通过运行测试
可以观察到使用BufferedWriter
的写入速度明显要快,在BufferedWriter
的源码中,可以看到它内部维护了一个字符数组作为缓冲区,数据会先被写入到这个缓冲区中,然后再一次性地将缓冲区中的数据写入到底层的Writer
中。简化版本BufferedWriter
:
import java.io.*;public class BufferedWriter extends Writer {// 缓冲区大小,默认为 8192private static final int DEFAULT_BUFFER_SIZE = 8192;// 缓冲区字符数组private char[] buffer;// 缓冲区中的数据索引private int index;// 底层的 Writer 对象private Writer out;// 构造方法public BufferedWriter(Writer out) {this(out, DEFAULT_BUFFER_SIZE);}// 带缓冲区大小的构造方法public BufferedWriter(Writer out, int bufferSize) {this.out = out;buffer = new char[bufferSize];index = 0;}// 写入一个字符到缓冲区@Overridepublic void write(int c) throws IOException {if (index >= buffer.length) {flushBuffer(); // 如果缓冲区已满,先将缓冲区中的数据写入到底层 Writer 中}buffer[index++] = (char) c;}// 写入字符数组到缓冲区@Overridepublic void write(char[] cbuf, int off, int len) throws IOException {for (int i = off; i < off + len; i++) {write(cbuf[i]); // 循环调用写入一个字符到缓冲区的方法}}// 刷新缓冲区,将缓冲区中的数据写入到底层 Writer 中@Overridepublic void flush() throws IOException {flushBuffer();out.flush();}// 关闭 BufferedWriter,先刷新缓冲区,再关闭底层的 Writer@Overridepublic void close() throws IOException {flush();out.close();}// 刷新缓冲区private void flushBuffer() throws IOException {if (index > 0) {out.write(buffer, 0, index); // 将缓冲区中的数据写入到底层 Writer 中index = 0; // 重置索引}}
}
通过这段代码,我们可以直接看到BufferedWriter
内部使用了缓冲区,数据会先暂时存储在缓冲区中,等到需要刷新缓冲区或关闭BufferedWriter
时,才会将缓冲区中的数据一次性写入到底层的Writer
中。
BufferedInputStream 和 BufferedReader 可以加快读取字符的速度
同样以BufferedReader为例,
当需要读取字符时,使用BufferedReader
相对于直接使用FileReader
可以提供更高的读取速度,因为BufferedReader
内部使用了缓冲区,能够一次读取多个字符,减少了频繁的系统调用和磁盘访问次数。我们通过对比使用BufferedReader
和直接使用FileReader
的读取速度:
package org.zyf.javabasic.io;import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;/*** @program: zyfboot-javabasic* @description: 使用BufferedReader相对于直接使用FileReader可以提供更高的读取速度* @author: zhangyanfeng* @create: 2024-05-26 17:40**/
public class BufferedReaderIOExample {private static final String FILE_PATH = "example.txt";public static void main(String[] args) {long startTime, endTime;// 测试直接使用FileReader读取字符startTime = System.currentTimeMillis();try (FileReader fileReader = new FileReader(FILE_PATH)) {int data;while ((data = fileReader.read()) != -1) {// 模拟处理读取的字符// System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}endTime = System.currentTimeMillis();System.out.println("直接使用FileReader读取字符耗时:" + (endTime - startTime) + " 毫秒");// 测试使用BufferedReader读取字符startTime = System.currentTimeMillis();try (BufferedReader bufferedReader = new BufferedReader(new FileReader(FILE_PATH))) {String line;while ((line = bufferedReader.readLine()) != null) {// 模拟处理读取的字符// System.out.println(line);}} catch (IOException e) {e.printStackTrace();}endTime = System.currentTimeMillis();System.out.println("使用BufferedReader读取字符耗时:" + (endTime - startTime) + " 毫秒");}
}
通过运行测试
可以观察到使用BufferedReader
的读取速度会明显快于直接使用FileReader
,这是因为BufferedReader
内部使用了缓冲区,能够一次读取多个字符,减少了频繁的系统调用和磁盘访问次数,从而提高了读取的效率,其源码上的处理这里就不在展示了。
(二)日志缓冲(Logging Buffering)
在Java开发中,日志记录是一个至关重要的方面。 无论是开发过程中的调试和追踪问题,还是生产环境中的监控和排错,日志都是程序员们必不可少的工具之一。然而,在高并发和大规模的应用中,日志记录往往会带来一些挑战。 随着应用程序的规模和用户量的增长,日志消息的数量也会急剧增加,可能会导致大量的磁盘 I/O 操作和系统开销,从而影响应用程序的性能和稳定性。
为了解决这些挑战,我们需要一种高效且可靠的日志记录框架。 这就是Logback发挥作用的地方。作为SLF4J的一种实现,Logback不仅提供了简洁易用的API,还具有出色的性能和可靠性。
其中一个Logback的特点就是异步日志记录。 异步日志记录机制使得Logback可以将日志消息先放入缓冲队列中,而不是立即写入到日志文件中,从而减少了对磁盘的频繁访问,提高了日志记录的效率。以下图实现为了:
Logback的异步日志输出流程中应用程序生成日志消息,并调用Logback的日志记录接口进行记录。Logback将生成的日志消息放入一个ArrayBlockingQueue队列中,这是一个线程安全的有界队列。这个队列充当了生产者-消费者模式中的缓冲区,用于临时存储待写入的日志消息。
也就是说,Logback启动一个后台Worker线程,该线程负责从队列中获取日志消息,并将其写入到磁盘中。后台Worker线程不断地从队列中取出日志消息,然后将这些消息写入到指定的日志文件中。在写入磁盘时,Logback可以通过一些优化手段,比如批量写入和异步IO,来提高写入性能。
一旦后台Worker线程将队列中的日志消息全部写入磁盘后,整个日志记录流程就完成了。总的来说,异步日志输出之后,日志信息将暂存在 ArrayBlockingQueue 列表中,后台会有一个 Worker 线程不断地获取缓冲区内容,然后写入磁盘中。
上图中提及的三个关键参数说明如下:
-
queueSize(队列大小):这个参数定义了异步日志队列的最大容量,即可以存放的日志消息数量上限。默认值为256。如果队列大小设置得太小,在高并发情况下,日志消息产生速度超过了写入速度,可能会导致队列溢出,从而丢失一部分日志消息。因此,应根据系统的实际情况和性能需求合理设置队列大小。但要注意,如果将队列大小设置得太大,在突发断电等异常情况下,会导致大量的日志消息被丢失。
-
maxFlushTime(最大刷新时间):这个参数定义了在关闭日志上下文后,继续执行写任务的时间。Logback会在关闭日志上下文时调用Thread的join方法,等待后台Worker线程执行完剩余的写任务。默认情况下,maxFlushTime未设置,即等待所有写任务执行完毕才关闭日志上下文。如果系统中有一些耗时较长的写任务,可能会导致日志上下文无法及时关闭,影响系统的正常关闭和资源释放。因此,可以通过设置maxFlushTime来限制等待的最大时间,保证日志上下文能够及时关闭。
-
discardingThreshold(丢弃阈值):这个参数定义了当队列快要达到最大容量时,是否丢弃一些级别较低的日志消息。默认值为队列长度的80%。在高负载情况下,如果不及时处理日志消息,队列可能会溢出,从而导致丢失重要的日志信息。通过设置discardingThreshold,可以在队列快要达到上限时,丢弃一些级别较低的日志消息,保证队列不会溢出。如果你担心可能会丢失业务关键的日志,可以将这个值设置为0,表示不丢弃任何日志消息,所有日志都会被记录。
这些关键参数在配置异步日志记录时非常重要。
三、案例回顾和优化方向分析
针对文件读写流和Logback的两个例子,我们可以看到:
- 文件读写流:当使用文件写入流(如BufferedOutputStream)时,写入的数据首先被放入缓冲区中,而不是直接写入到文件中。这意味着在写入操作完成之前,数据实际上并没有真正地写入到文件中,而是先存储在缓冲区中。为了确保数据被及时写入文件,我们需要手动调用flush()方法来刷新缓冲区,将数据立即写入文件中。这样可以避免因为程序崩溃而导致的数据丢失问题。
- Logback:Logback的异步日志记录机制使用了缓冲区,将日志消息暂存于缓冲队列中,然后由后台Worker线程负责将日志消息写入磁盘中。通过配置参数来控制缓冲队列的大小、最大刷新时间等,以及是否在队列快满时丢弃日志消息。通过合理配置这些参数,可以平衡性能和可靠性之间的关系,确保日志记录的效率和稳定性。
在处理缓冲区设计的常规操作时,需要注意及时刷新缓冲区,以确保数据被正确地写入到目标资源中,同时要考虑到异步操作可能引入的时序问题,保证程序的正确性和稳定性。
根据不同的资源和应用场景,选择适当的缓存优化设计是非常常见的做法。
-
同步操作:适用于对数据完整性要求较高,可以容忍一定程度的性能损失的场景。同步操作会阻塞当前线程,直到操作完成,确保数据的及时写入或处理。这种方式通常适用于对数据一致性要求较高、对性能要求相对较低的场景。
-
异步操作:适用于对性能要求较高,可以容忍一定程度的数据丢失或时序不一致的场景。异步操作将数据暂存于缓冲区中,并由后台线程异步处理,从而提高了系统的响应性能和并发能力。这种方式通常适用于高并发、大规模的应用场景,可以显著提升系统的吞吐量和性能。
有时候,甚至可以结合同步和异步操作,针对不同的场景采用不同的缓存优化方案,以达到最佳的性能和可靠性。日常的开发中我们需要不断的思考引入缓存来解决我们的一些业务诉求,同时需要思考对应的优化手段。
四、Kafka缓存区优化思考
在 Kafka 中,消息是通过分区存储的,并且每个分区都有一个存储日志文件(log file)来持久化消息。这些日志文件是以分段(segment)的方式组织的,每个分段包含一定数量的消息。而消息的写入和读取都是通过分段来进行的。
Kafka 同样利用了缓存区的思想来优化消息的写入和读取过程,具体我们通过分析两个基本问题来说明。
(一)Kafka 的生产者,有可能会丢数据吗?
Kafka 生产者会将发送到同一个分区的多条消息封装在一个缓冲区(batch)中。这个缓冲区有两种触发条件:一是缓冲区满了,即达到了指定的大小(batch.size);二是消息在缓冲区中等待的时间超过了指定的超时时间(linger.ms)。一旦满足了其中一个条件,缓冲区中的消息就会被发送到 Kafka Broker 上。
在默认情况下,Kafka 的缓冲区大小为 16KB。如果生产者的业务突然断电或发生故障,尚未发送到 Broker 的 16KB 数据将会丢失,因为它们没有机会被发送出去。这种情况下,消息丢失是有可能发生的。
为了避免这种情况的发生,我们有两种解决办法都是可行的:
-
缓冲区大小设置较小:将缓冲区大小设置得非常小,以确保在生产者发生故障时,待发送的数据量较小,从而减少了可能丢失的数据量。但是,将缓冲区大小设置得太小可能会导致性能下降,因为每条消息都需要单独发送,增加了网络开销和系统负载。
-
消息发送日志记录:在消息发送前记录一条日志,标记消息发送的开始,然后在消息成功发送后通过回调再记录一条日志,标记消息发送的结束。通过扫描生成的日志,可以判断哪些消息丢失了。这种方法可以有效地追踪和识别丢失的消息,但需要额外的日志记录和扫描操作,可能会增加系统的复杂性和开销。
对于如何处理生产者发生故障时可能丢失的数据,需要根据具体的业务需求和性能要求来选择合适的解决方案。在权衡性能和可靠性的基础上,可以选择合适的缓冲区大小,并结合消息发送日志记录等技术手段来确保消息的可靠传输和处理。
(二)Kafka 生产者会影响业务的高可用吗?
Kafka 生产者的设计确实可能会影响业务的高可用性,特别是与生产者的缓冲区大小和超时参数相关的配置。
-
缓冲区大小限制:生产者的缓冲区是有限的,如果消息产生得过快或者生产者与 Broker 节点之间存在网络问题,缓冲区可能会一直处于满载状态。在这种情况下,有新的消息到达时,可能会导致阻塞。
-
超时参数设置:通过配置生产者的超时参数和重试次数,可以控制生产者在缓冲区满载时的行为。一般来说,将超时参数设置得较小可以让新的消息不会一直阻塞在业务方。然而,有些情况下,如果将超时参数设置得过大,可能会导致生产者线程被阻塞,无法继续处理新的请求,从而影响了业务的高可用性。
为了确保 Kafka 生产者与业务的高可用性,需要合理配置生产者的缓冲区大小、超时参数以及重试策略,以及针对可能的异常情况进行监控和调优。同时,也需要在系统设计时考虑消息传输的可靠性和容错性,以应对可能发生的各种问题,从而保障业务的稳定运行。
五、总结
缓存作为计算机系统中提升性能的重要工具,其核心作用在于通过减少系统调用和批量处理数据来提高资源利用率和数据处理速度。本文通过对多个典型应用场景的分析,如文件I/O、日志系统以及Kafka消息队列,展示了缓存技术在实际应用中的广泛性和灵活性。无论是通过缓冲区减少磁盘I/O操作,还是在高并发环境中通过批量处理数据提升系统吞吐量,缓存机制都展示出了显著的性能优化效果。
然而,缓存的引入也伴随着挑战,特别是在高并发环境下,缓存区的设计需要考虑数据一致性、缓存丢失以及缓存区满载等问题。针对这些挑战,合适的缓存策略(如定时刷新、缓存淘汰策略)和合理的缓存配置显得尤为重要。此外,缓存设计的复杂性在分布式系统中尤为突出,如分布式缓存的一致性管理、数据分片与复用等,这些问题的解决将进一步推动缓存技术的发展。
未来,随着分布式系统、物联网、大数据处理等领域的不断发展,缓存技术将在数据存储和传输中扮演更加重要的角色。开发者需要在不同的场景中平衡性能、数据安全性和系统资源的利用,设计出更加高效且稳健的缓存机制。
参考文章
《Java 性能优化与面试 21 讲》,李国
https://www.cnblogs.com/zhzhlong/p/11420084.html
【深入浅出C#】章节 7: 文件和输入输出操作:文件读写和流操作-腾讯云开发者社区-腾讯云
Azure HPC 缓存使用情况模型 | Microsoft Learn
专为流式数据设计的另一种缓存:流式缓存技术解读_语言 & 开发_Andrei Paduroiu_InfoQ精选文章
https://zhuanlan.zhihu.com/p/641984395
https://zhuanlan.zhihu.com/p/475320277
IO流中的设计模式_io流用到的设计模式-CSDN博客
https://www.cnblogs.com/LoveShare/p/17029000.html
概念,原理,到例子,全解析logback ,学会日志系统-腾讯云开发者社区-腾讯云
logback配置详解 & 原理介绍_logback 配置原理-CSDN博客
logback之 AsyncAppender 的原理、源码及避坑建议-阿里云开发者社区
快速了解常用日志技术(JCL、Slf4j、JUL、Log4j、Logback、Log4j2)-阿里云开发者社区
相关文章:
缓冲区的奥秘:解析数据交错的魔法
目录 一、理解缓存区的好处 (一)直观性的理解 (二)缓存区的好处 二、经典案例分析体会 (一)文件读写流(File I/O Buffering) BufferedOutputStream 和 BufferedWriter 可以加快…...
【MySQL — 数据库基础】MySQL的安装与配置 & 数据库简单介绍
数据库基础 本节目标 掌握关系型数据库,数据库的作用掌握在Windows和Linux系统下安装MySQL数据库了解客户端工具的基本使用和SQL分类了解MySQL架构和存储引擎 1. 数据库的安装与配置 1.1 确认MYSQL版本 处理无法在 cmd 中使用 mysql 命令的情况&a…...
如何使用Python解析从淘宝API接口获取到的JSON数据?
基本的 JSON 解析 当从淘宝 API 接口获取到数据后(假设数据存储在变量response_data中),首先要判断数据类型是否为 JSON。如果是,就可以使用 Python 内置的json模块进行解析。示例代码如下: import json # 假设respon…...
Day1 生信新手笔记
生信新手笔记 生信学习第一天笔记打卡。 转录组学中: 上游分析-基于linux,包括质控、过滤、比对、定量; 下游分析-基于R语言,包括差异分析、富集分析、可视化。 1. 级别标题 一个井号加空格 就是一级标题,两个井号加…...
内网穿透步骤
步骤 第一次需要验证token window和linux的方法不同。 然后 启动 cpolar 服务: 在命令窗口中输入 cpolar.exe htttp 8080,启动内网穿透服务。确保命令窗口保持开启状态,以维持穿透效果。 cpolar.exe hhttp 8080 成功后 注意事项 命令窗口…...
docker启动容器,语句名词解释
#启动容器代码docker run -it -d --name dev_aios -v D:\project\aialign:/www/ -v D:\project\data\dev\aios:/myfile/data/dev/aios -w /www/stand-alone-aios/aios -p 9002:9000 --ulimit core0 aialign/python-base:1.0 bash名词解释 docker run: 这是 Docker 的命令&#…...
微服务之短信验证服务配置完后junit单元测试短信发送失败
总之岁月漫长,然而值得等待。 主要是版本冲突问题,具体报错与解决方法如下: 报错前: 启动失败 短信服务测试报错: 解决后: 启动成功 短信服务测试发送成功: 在使用 SpringBoot 开发时&am…...
QSqlTableModel的使用
实例功能 这边使用一个实例显示数据库 demodb 中 employee 数据表的内容,实现编辑、插入、删除的操作,实现数据的排序和记录过滤,还实现 BLOB 类型字段 Photo 中存储照片的显示、导入等操作,运行界面如下图: 在上图中…...
构建高可用系统设计OpenStack、Docker、Mesos和Kubernetes(简称K8s)
如果构建高可用、高并发、高效运维的大型系统 大型系统架构设计包括业务层设计、服务层设计、基础架层设计、存储层设计、网络层协同设计来完成。 一、业务层 根据主要业务范畴的分类和特征提取,抽象出独立的业务系统,分别统计系统的用户角色群体、访…...
CondaValueError: Malformed version string ‘~‘: invalid character(s).
问题描述:在window下使用conda安装任何包都会报错。报错信息是CondaValueError: Malformed version string ~: invalid character(s). 解决办法:把.condarc文件的源地址删除(八成是源地址访问不了了),只保存默认的&am…...
uniapp图片上传预览uni.chooseImage、uni.previewImage
文章目录 1.上传图片2.预览图片 1.上传图片 uni.chooseImage(OBJECT) 从本地相册选择图片或使用相机拍照。 App端如需要更丰富的相机拍照API(如直接调用前置摄像头),参考plus.camera 微信小程序从基础库 2.21.0 开始, wx.choos…...
代码随想录算法训练营第三十二天 | 509. 斐波那契数 | 70. 爬楼梯 | 746. 使用最小花费爬楼梯
Day 32 总结 自己实现中遇到哪些困难今日收获,记录一下自己的学习时间 12:30 - 21:30 理论基础 代码随想录 动态规划 问题有很多的重叠子问题需要解决,状态涉及推导 DP 5部曲 DP数组含义 状态转移公式 dp数组初始化 数组遍历顺序 举例推导 视频&a…...
Flink常见面试题
1、Flink 的四大特征(基石) 2、Flink 中都有哪些 Source,哪些 Sink,哪些算子(方法) 预定义Source 基于本地集合的source(Collection-based-source) 基于文件的source(…...
SpringCloud之Config:从基础到高级应用
目录 一、SpringCloud Config 简介1、SpringCloud Config 概述(1)核心概念(2)SpringCloud Config 的特点(3)应用场景(4)工作原理(5)优势(6&#x…...
redis 底层数据结构
概述 Redis 6 和 Redis 7 之间对比: Redis6 和 Redis7 最大的区别就在于 Redis7 已经用 listpack 替代了 ziplist. 以下是基于 Redis 7基础分析。 RedisObject Redis是⼀个<k,v>型的数据库,其中key通常都是string类型的字符串对象,⽽…...
机器学习之RLHF(人类反馈强化学习)
RLHF(Reinforcement Learning with Human Feedback,基于人类反馈的强化学习) 是一种结合人类反馈和强化学习(RL)技术的算法,旨在通过人类的评价和偏好优化智能体的行为,使其更符合人类期望。这种方法近年来在大规模语言模型(如 OpenAI 的 GPT 系列)训练中取得了显著成…...
openwrt利用nftables在校园网环境下开启nat6 (ipv6 nat)
年初写过一篇openwrt在校园网环境下开启ipv6 nat的文章,利用ip6tables控制ipv6的流量。然而从OpenWrt22版本开始,系统内置的防火墙变为nftables,因此配置方法有所改变。本文主要参考了OpenWRT使用nftables实现IPv6 NAT 这篇文章。 友情提示 …...
Vue3+node.js实现注册
文章目录 前端代码实现后端代码实现 效果图 前端代码实现 <template><div class"register-container"><el-card class"register-card"><template #header><div class"card-header"><span>注册</span&…...
LabVIEW将TXT文本转换为CSV格式(多行多列)
在LabVIEW中,将TXT格式的文本文件内容转换为Excel格式(即CSV文件)是一项常见的数据处理任务,适用于将以制表符、空格或其他分隔符分隔的数据格式化为可用于电子表格分析的形式。以下是将TXT文件转换为Excel(CSV&#x…...
SpringBoot源码-Spring Boot启动时控制台为何会打印logo以及自定义banner.txt文件控制台打印
1.当我们启动一个SpringBoot项目的时候,入口程序就是main方法,而在main方法中就执行了一个run方法。 SpringBootApplication public class StartApp {public static void main(String[] args) {// testSpringApplication.run(StartApp.class);} }publi…...
【笔记】软技能
硬技能:操控世界的能力,处理对象为【物】。软技能:影响他人的能力,处理对象为【人】。软技能包括一个人的情商、个性、社交礼仪、沟通、语言、个人习惯,还有解决问题的能力、领导能力、时间管理能力等一切非技术能力。…...
试题转excel;试题整理工具;试卷转excel;word转excel
一、问题描述 我父亲是一名教师,偶尔会需要将试卷转excel,方便管理处理一些特别重要的题目 于是,就抽空写一个专门将试题转excel的工具,便于各位教师从业者和教育行业的朋友更好的整理试题,减少一点重复枯燥的工作 …...
【热门主题】000072 分布式数据库:开启数据管理新纪元
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...
常见靶场的搭建
漏洞靶场 渗透测试(漏洞挖掘)切忌纸上谈兵,学习渗透测试(漏洞挖掘)知识的过程中,我们通常需要一个包含漏洞的测试环境来进行训练。而在非授权情况下,对于网站进行渗透测试攻击,是触及…...
C语言——链表
1 链表基础 1 什么是链表 !!!链表相当于多个结构体变量链接在一起!!! //链表节点结构 struct Node //数据域和指针域 {int data; //数据域//struct Student data;数据尽量不写在链表结构体里面…...
【经典】星空主题的注册界面HTML,CSS,JS
目录 界面展示 完整代码 说明: 这是一个简单的星空主题的注册界面,使用了 HTML 和 CSS 来实现一个背景为星空效果的注册页面。 界面展示 完整代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8&…...
94.【C语言】解析预处理(2)
目录 1.带有副作用的宏参数 代码 一个判断最大值的宏代码 运行结果 分析 "副作用"的解释 2.宏替换规则 解释 3.宏和函数的对比 附一张对比表 承接93.【C语言】解析预处理(1)文章 1.带有副作用的宏参数 代码 一个判断最大值的宏代码 #define MAX(a, b) (…...
(数据结构与算法)如何提高学习算法的效率?面试算法重点有哪些?面试需要哪些能力?
面试官眼中的求职者 通过对你算法的考察!!!! 缩进太多!!一般不要超过三层!!!缩进越少,bug越少;逻辑比较复杂,把这些包装成为函数&…...
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58 STM32F407芯片的OPTION Byte全面解析 STM32F407芯片是STMicroelectronics推出的一款功能强大的微控制器,广泛应用于工业控制、通信和消费电子等领域。其中,OPTION Byte࿰…...
MySQL主从复制
华子目录 实验环境准备修改配置文件 实验主开启bin-log日志创建用于主从复制的用户master配置salve配置 测试 添加一台新的slave,如何实现数据的全部同步呢什么环境下主比较多,什么环境下从比较多?延迟复制测试 并行复制gtid模式未启用gtid时…...
贝叶斯统计:高斯分布均值μ的后验分布推导
使用贝叶斯统计方法 均值 ( μ \mu μ ) 的后验分布解析 在贝叶斯统计中,后验分布表示在观察到数据后,对参数的更新后的信念。本篇文章将结合高斯分布的假设,详细解析均值 ( μ \mu μ ) 的后验分布推导过程,并对 ( μ \mu μ…...
linux常用指令都是工作中遇到的
前端打war包 jar -cvf dist.war *创建 WAR 文件的命令 jar -cvf dist.war * 用于将当前目录下的所有文件和文件夹打包成一个名为 dist.war 的 WAR 文件。以下是该命令的详细解释: jar: Java Archive 工具,用于创建 JAR、WAR 或 EAR 文件。 -c: 创建新的…...
亚马逊自研大语言模型 Olympus 即将亮相,或将在 LLM 竞赛中掀起新波澜
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
droppath
DropPath 是一种用于正则化深度学习模型的技术,它在训练过程中随机丢弃路径(或者说随机让某些部分的输出变为零),从而增强模型的鲁棒性和泛化能力。 代码解释: import torch import torch.nn as nn # 定义 DropPath…...
通信与网络安全之IPSEC
IPSec(IP Security)是IETF制定的为保证在Internet上传送数据的安全保密性能的三层隧道加密协议。IPSec在网络层对IP报文提供安全服务。IPSec协议本身定义了如何在IP数据包中增加字段来保证IP包的完整性、 私有性和真实性,以及如何加密数据包。…...
Linux内核编译流程(Ubuntu24.04+Linux Kernel 6.8.12)
万恶的拯救者,使用Ubuntu没有声音,必须要自己修改一下Linux内核中的相关驱动逻辑才可以,所以被迫学习怎么修改内核&编译内核,记录如下 准备工作 下载Linux源码:在Linux发布页下载并使用gpg签名验证 即:…...
什么是GAN?
一、基本概念 生成对抗网络(Generative Adversarial Network,GAN)是一种由两个神经网络共同组成深度学习模型:生成器(Generator)和判别器(Discriminator)。这两个网络通过对抗的方式…...
torch_geometric使用手册-Creating Graph Datasets(专题四)
虽然 PyG 已经提供了很多有用的数据集,但你可能希望创建自己的数据集,使用自己收集的数据或非公开的数据。 自己实现数据集是非常简单的,你可能想查看源代码,了解各种数据集是如何实现的。然而,这里简要介绍一下如何设置你自己的数据集。 我们提供了两个抽象类用于数据集…...
编程语言之Python
Python是一种高级编程语言,自其诞生以来,便因其简洁明了的语法、强大的功能和广泛的应用领域而备受青睐。以下是对Python的详细介绍,包括其历史、特点、应用领域,以及通过代码示例展示其语法、库、函数等关键概念。同时࿰…...
【Go】-调度器简介
目录 数据结构 G M P 调度器启动 创建 Goroutine 初始化结构体 运行队列 调度信息 调度循环 小结 数据结构 Go的运行时调度器的三个重要组成部分 — 线程 M、Goroutine G 和处理器 P: 图 6-29 Go 语言调度器 G — 表示 Goroutine,它是一个待…...
在Ubuntu 22.04上设置Python 3的Jupyter Notebook
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 Jupyter Notebook 是一个作为 Web 应用程序的交互式计算命令 shell。该工具可与多种语言一起使用,包括 Python、Julia…...
通讯专题4.1——CAN通信之计算机网络与现场总线
从通讯专题4开始,来学习CAN总线的内容。 为了更好的学习CAN,先从计算机网络与现场总线开始了解。 1 计算机网络体系的结构 在我们生活当中,有许多的网络,如交通网(铁路、公路等)、通信网(电信、…...
将jar包导入maven
1.将jar包放repository 2.执行命令:mvn install:install-file -DgroupIdcom.oracle -DartifactIdojdbc7 -Dversion12.1.0.2 -Dpackagingjar -DfileD:\dev\utils\idea\repository\ojdbc7.jar -Dfile: 指定要安装的JAR文件的路径。 -DgroupId: 指定项目的groupId。 -…...
Mysql实现定时自动备份(Windows环境)
一.新建数据库备份目录 二.新建批处理文件 创建批处理文件mysql_backup.bat echo off set BACKUP_DIRD:\backup set MYSQL_USERroot set MYSQL_PASS123456 set MYSQL_HOSTlocalhost set DATABASE_NAMEphoenix set DATE%date:~0,4%-%date:~5,2%-%date:~8,2%_%time:~0,2%-%time…...
kafka数据在服务端时怎么写入的
学习背景 接着上篇,我们来聊聊kafka数据在服务端怎么写入的 服务端写入 在介绍服务端的写流程之前,我们先要理解服务端的几个角色之间的关系。 假设我们有一个由3个broker组成的kafka集群,我们在这个集群上创建一个topic叫做shitu-topic&…...
2024算法基础公选课练习七(BFS1)
一、前言 还是偏基础的bfs,但是有几个题不是很好写 二、题目总览 三、具体题目 3.1 问题 A: 数据结构-队列-奇怪的电梯 我的代码 可以看成求一维平面的bfs最短路 #include <bits/stdc.h> using i64 long long; using pii std::pair<int,int>; co…...
算法刷题Day1
BM47 寻找第k大 第一天就随便记录吧,万事开头难,我好不容易开的头,就别难为自己,去追求高质量了。嘿嘿嘿 题目 传送门 解题思路一:维护一个大小为k的最小堆。最后返回堆顶元素。 代码: # # 代码中的类名…...
你还没有将 Siri 接入GPT对话功能吗?
由于各种原因,国内ios用户目前无缘自带 AI 功能,但是这并不代表国内 ios 无法接入 AI 功能,接下来手把手带你为iPhone siri 接入 gpt 对话功能。 siri 接入 chatGPT 暂时还无法下载 ChatGPT app,或者没有账号的读者可以直接跳到…...
LabVIEW 标准状态机设计模式
LabVIEW 标准状态机设计模式 LabVIEW 软件框架介绍LabVIEW编程模式及其应用分析状态机模式的类型分析标准状态机设计模式及状态机应用学习顺序结构它的一个缺点是什么? 状态机结构 LabVIEW 软件框架介绍 源于虚拟仪器技术的LabVIEW程序设计语言,从被创建…...
Scala学习记录,统计成绩
统计成绩练习 1.计算每个同学的总分和平均分 2.统计每个科目的平均分 3.列出总分前三名和单科前三名,并保存结果到文件中 解题思路如下: 1.读入txt文件,按行读入 2.处理数据 (1)计算每个同学的总分平均分 import s…...