【系统设计】提升Kafka系统性能:Spring Boot实现Lag感知的生产者与消费者

在分布式系统中,消息队列扮演着至关重要的角色,而Kafka凭借其高吞吐量和低延迟的特性,成为了流数据处理的首选。然而,随着应用规模的扩大,如何有效管理Kafka的offset与lag,确保系统的高可用性和性能稳定,成为了一个亟待解决的问题。本文将深入探讨如何实现一个基于Key的Lag感知生产者与消费者,通过动态监控与调节,实现智能的负载均衡,从而在部分服务器性能下降时,依然能够保证整体系统的高效


Kafka Offset与Lag的概念解析

在Kafka中,OffsetLag是两个关键的指标,用于监控和管理消费者的消费进度。

Offset(偏移量)

每个Kafka分区中的消息都有一个唯一的offset,用于标识该消息在分区中的位置。消费者在消费消息时,会记录其最新消费的offset,以便在出现故障或重启时能够从上次消费的位置继续。

Lag(延迟)

Lag表示消费者与生产者之间的延迟,即生产者生成的最新消息的offset与消费者已消费的offset之间的差值。Lag越大,意味着消费者处理消息的速度跟不上生产者的速度,可能导致系统的延迟增加甚至出现消息堆积。

Offset与Lag的计算方式

  • Offset计算:每个消费者组在每个分区上都会维护一个offset,表示该消费者组在该分区上已经消费到的位置。
  • Lag计算:Lag = 生产者最新的offset - 消费者当前的offset

通过定期监控每个分区的Lag值,可以及时发现消费滞后的问题,并采取相应的措施,如扩展消费者实例或调整生产者的负载策略。

消费者的工作机制及负载均衡实现

消费者的工作机制

Kafka消费者通过订阅一个或多个主题(Topic)来消费消息。消费者组(Consumer Group)允许多个消费者实例共同消费一个主题的消息,每个分区只能被一个消费者实例消费,从而实现负载均衡。

主要步骤:

  1. 订阅主题:消费者订阅一个或多个主题。
  2. 分配分区:Kafka会将主题的分区分配给消费者组中的各个消费者实例,确保每个分区只被一个消费者消费。
  3. 消费消息:消费者按照分配的分区顺序消费消息,并定期提交offset。
  4. 负载均衡:当消费者数量变化(增加或减少)时,Kafka会自动重新分配分区,确保负载均衡。

负载均衡的实现

在传统的负载均衡中,分区的分配是静态的,无法根据实时的Lag情况进行动态调整。为了实现基于Lag的动态负载均衡,可以采取以下策略:

  1. 监控Lag:定期监控每个分区的Lag值,识别出Lag较高的分区。
  2. 动态调整分区分配
    • 当某个分区的Lag超过预设阈值时,消费者主动退出对该分区的订阅。
    • 触发消费者组的再平衡机制,使其他消费者接手高Lag分区的消费任务。
  3. 重新分配消费者:通过消费者组的再平衡机制,使其他消费者实例接手高Lag分区的负载,实现负载均衡。

这种动态调整机制能够有效应对部分服务器性能下降的情况,提升整体系统的稳定性和性能。

基于Spring Boot的实现源码

下面将通过一个Spring Boot项目,详细展示如何实现基于Key的Lag感知生产者与消费者,以及动态负载均衡的具体实现。

项目结构

kafka-lag-aware
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com.example.kafkalagaware
│   │   │       ├── KafkaLagAwareApplication.java
│   │   │       ├── config
│   │   │       │   ├── KafkaConsumerConfig.java
│   │   │       │   └── KafkaProducerConfig.java
│   │   │       ├── consumer
│   │   │       │   └── LagAwareConsumer.java
│   │   │       ├── partitioner
│   │   │       │   └── LagAwarePartitioner.java
│   │   │       └── producer
│   │   │           └── LagAwareProducer.java
│   │   └── resources
│   │       └── application.yml
└── pom.xml

依赖配置

pom.xml中添加必要的依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>kafka-lag-aware</artifactId><version>1.0.0</version><packaging>jar</packaging><name>kafka-lag-aware</name><description>Kafka Lag Aware Producer and Consumer with Dynamic Load Balancing</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</version><relativePath/> <!-- lookup parent from repository --></parent><dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- Spring for Apache Kafka --><dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency><!-- Lombok for boilerplate code reduction --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Additional dependencies if needed --></dependencies><build><plugins><!-- Spring Boot Maven Plugin --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- Lombok Plugin --><plugin><groupId>org.projectlombok</groupId><artifactId>lombok-maven-plugin</artifactId><version>1.18.24.0</version><executions><execution><phase>compile</phase><goals><goal>delombok</goal></goals></execution></executions></plugin></plugins></build></project>

配置文件 application.yml

spring:kafka:bootstrap-servers: localhost:9092consumer:group-id: lag-aware-groupkey-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializerenable-auto-commit: falseauto-offset-reset: earliestproducer:key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializerpartitioner: com.example.kafkalagaware.partitioner.LagAwarePartitionerproperties:bootstrap.servers: localhost:9092listener:type: batchtopic: my-topiclag:threshold: 100

Kafka配置类

a. KafkaProducerConfig.java

确保在生产者配置中正确设置自定义分区器。

package com.example.kafkalagaware.config;import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.*;import java.util.HashMap;
import java.util.Map;@Configuration
public class KafkaProducerConfig {@Value("${spring.kafka.bootstrap-servers}")private String bootstrapServers;@Beanpublic ProducerFactory<String, String> producerFactory(){Map<String, Object> props = new HashMap<>();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);// 设置自定义分区器props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, "com.example.kafkalagaware.partitioner.LagAwarePartitioner");// Additional producer configurations if neededreturn new DefaultKafkaProducerFactory<>(props);}@Beanpublic KafkaTemplate<String, String> kafkaTemplate(){return new KafkaTemplate<>(producerFactory());}
}
b. KafkaConsumerConfig.java
package com.example.kafkalagaware.config;import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.*;
import org.springframework.kafka.listener.*;import java.util.HashMap;
import java.util.Map;@Configuration
public class KafkaConsumerConfig {@Value("${spring.kafka.bootstrap-servers}")private String bootstrapServers;@Value("${spring.kafka.consumer.group-id}")private String groupId;@Beanpublic ConsumerFactory<String, String> consumerFactory(){Map<String, Object> props = new HashMap<>();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");// Additional consumer configurations if neededreturn new DefaultKafkaConsumerFactory<>(props);}@Beanpublic ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(){ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();factory.setConsumerFactory(consumerFactory());factory.setConcurrency(3); // Number of consumer threadsfactory.setBatchListener(true);return factory;}
}

实现基于Key的Lag感知生产者

LagAwareProducer 负责发送消息。由于我们已经在自定义分区器中处理了分区选择逻辑,因此 LagAwareProducer 只需负责发送消息即可,无需手动选择分区。

package com.example.kafkalagaware.producer;import org.springframework.beans.factory.annotation.*;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;@Component
public class LagAwareProducer {@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;@Value("${spring.kafka.topic}")private String topic;/*** 发送消息,依赖自定义分区器决定目标分区*/public void sendMessage(String key, String value) {kafkaTemplate.send(topic, key, value).addCallback(success -> System.out.println("Message sent to partition " + success.getRecordMetadata().partition()),failure -> System.err.println("Failed to send message: " + failure.getMessage()));}
}

实现Lag感知的消费者

LagAwareConsumer 负责消费消息,并监控自身的 Lag 值。当 Lag 超过阈值时,消费者主动退出对该分区的订阅,触发消费者组的再平衡机制,使其他消费者接管该分区。

package com.example.kafkalagaware.consumer;import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.common.TopicPartition;
import org.springframework.beans.factory.annotation.*;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.*;
import java.util.concurrent.ConcurrentHashMap;@Component
public class LagAwareConsumer {@Value("${spring.kafka.lag.threshold:100}")private long lagThreshold;@Autowiredprivate ConsumerFactory<String, String> consumerFactory;private final Set<TopicPartition> pausedPartitions = ConcurrentHashMap.newKeySet();@KafkaListener(topics = "${spring.kafka.topic}", containerFactory = "kafkaListenerContainerFactory")public void listen(List<ConsumerRecord<String, String>> records, Acknowledgment acknowledgment, Consumer<?, ?> consumer) {for (ConsumerRecord<String, String> record : records) {// 处理消息System.out.printf("Consumed message: key=%s, value=%s, partition=%d, offset=%d%n",record.key(), record.value(), record.partition(), record.offset());// 检查Laglong lag = getLag(record.topic(), record.partition(), consumer);if (lag > lagThreshold) {TopicPartition partition = new TopicPartition(record.topic(), record.partition());if (!pausedPartitions.contains(partition)) {consumer.pause(Collections.singleton(partition));pausedPartitions.add(partition);System.out.println("Paused partition: " + partition.partition());// 主动取消订阅该分区,触发再平衡unsubscribeFromPartition(consumer, partition);}}}acknowledgment.acknowledge();}/*** 获取分区的Lag值*/private long getLag(String topic, int partition, Consumer<?, ?> consumer) {TopicPartition topicPartition = new TopicPartition(topic, partition);long latestOffset = consumer.endOffsets(Collections.singleton(topicPartition)).get(topicPartition);long currentOffset = consumer.position(topicPartition);return latestOffset - currentOffset;}/*** 主动取消订阅高Lag的分区,触发消费者组的再平衡*/private void unsubscribeFromPartition(Consumer<?, ?> consumer, TopicPartition partition) {try {// 获取当前分配的分区Set<TopicPartition> currentPartitions = consumer.assignment();// 移除高Lag分区Set<TopicPartition> updatedPartitions = new HashSet<>(currentPartitions);updatedPartitions.remove(partition);// 重新分配分区consumer.assign(updatedPartitions);System.out.println("Unsubscribed from partition: " + partition.partition());} catch (Exception e) {e.printStackTrace();}}/*** 定期检查暂停的分区是否可以恢复消费*/@Scheduled(fixedDelay = 10000)public void checkPausedPartitions() {// 此处需要实现逻辑检查Lag是否恢复// 如果Lag已经降低,可以移除pausedPartitions中的分区,并重新订阅// 具体实现请根据实际需求编写}
}

实现自定义分区器

LagAwarePartitioner 实现自定义分区选择逻辑,根据每个分区的 Lag 值,选择 Lag 最小的分区来发送消息,确保负载均衡。

package com.example.kafkalagaware.partitioner;import org.apache.kafka.clients.admin.*;
import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.PartitionInfo;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.utils.Utils;import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;public class LagAwarePartitioner implements Partitioner {private AdminClient adminClient;private String consumerGroupId = "lag-aware-group"; // 消费者组ID@Overridepublic void configure(Map<String, ?> configs) {Properties props = new Properties();props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, configs.get("bootstrap.servers"));this.adminClient = AdminClient.create(props);}@Overridepublic int partition(String topic, Object keyObj, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {String key = (String) keyObj;List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);List<Integer> partitionNumbers = partitions.stream().map(PartitionInfo::partition).collect(Collectors.toList());try {// 获取每个分区的Lag值Map<TopicPartition, Long> lagMap = getLagMap(topic, partitionNumbers);int totalPartitions = partitions.size();// 根据Key的哈希值选择默认分区int hash = Math.abs(key.hashCode());int defaultPartition = hash % totalPartitions;TopicPartition defaultTp = new TopicPartition(topic, defaultPartition);long defaultLag = lagMap.getOrDefault(defaultTp, 0L);if (defaultLag >= 100) { // 预设的Lag阈值// 如果默认分区Lag过高,则选择Lag最小的分区Optional<TopicPartition> optionalPartition = lagMap.entrySet().stream().filter(entry -> entry.getValue() < 100).min(Comparator.comparingLong(Map.Entry::getValue)).map(Map.Entry::getKey);if (optionalPartition.isPresent()) {return optionalPartition.get().partition();}}// 默认分区Lag正常,发送到默认分区return defaultPartition;} catch (Exception e) {e.printStackTrace();// 回退到默认的轮询策略return defaultPartition(keyBytes, partitions, cluster);}}private int defaultPartition(byte[] keyBytes, List<PartitionInfo> partitions, Cluster cluster) {if (keyBytes == null) {// 如果没有key,则随机选择分区return new Random().nextInt(partitions.size());} else {// 使用默认的hash策略return Utils.toPositive(Utils.murmur2(keyBytes)) % partitions.size();}}private Map<TopicPartition, Long> getLagMap(String topic, List<Integer> partitions) throws ExecutionException, InterruptedException {Map<TopicPartition, Long> lagMap = new HashMap<>();List<TopicPartition> topicPartitions = partitions.stream().map(p -> new TopicPartition(topic, p)).collect(Collectors.toList());// 获取最新的offsetListOffsetsResult latestResult = adminClient.listOffsets(topicPartitions.stream().collect(Collectors.toMap(tp -> tp, tp -> OffsetSpec.latest())));Map<TopicPartition, ListOffsetsResult.ListOffsetsResultInfo> latestOffsets = latestResult.all().get();// 获取消费者组的当前offsetListConsumerGroupOffsetsResult consumerOffsetsResult = adminClient.listConsumerGroupOffsets(consumerGroupId);Map<TopicPartition, OffsetAndMetadata> consumerOffsets = consumerOffsetsResult.partitionsToOffsetAndMetadata().get();for (TopicPartition tp : topicPartitions) {long latestOffset = latestOffsets.get(tp).offset();long consumerOffset = consumerOffsets.getOrDefault(tp, new OffsetAndMetadata(0L)).offset();long lag = latestOffset - consumerOffset;lagMap.put(tp, lag);}return lagMap;}@Overridepublic void close() {if (adminClient != null) {adminClient.close();}}@Overridepublic void onNewBatch(String topic, Cluster cluster, int prevPartition) {// 可选实现}
}

注意事项

  • 性能开销:自定义分区器中调用AdminClient获取Lag信息会带来额外的网络和计算开销,特别是在高频率发送消息的场景下。因此,建议对Lag信息进行缓存,并设置合理的更新频率。
  • 消息顺序性:使用Key进行分区选择时,确保具有相同Key的消息发送到同一分区,以保持顺序性。在本实现中,当默认分区Lag过高时,可能会将相同Key的消息发送到不同分区,从而打乱顺序。根据需求,可能需要调整策略以平衡负载均衡与顺序性。
  • 故障处理:在自定义分区器中,需要妥善处理AdminClient的异常情况,确保在无法获取Lag信息时,系统能够退化到默认的分区策略,避免消息发送失败。

主应用类

KafkaLagAwareApplication 作为Spring Boot的入口,初始化Producer和消费者。

package com.example.kafkalagaware;import com.example.kafkalagaware.producer.LagAwareProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication
@EnableScheduling
public class KafkaLagAwareApplication implements CommandLineRunner {@Autowiredprivate LagAwareProducer producer;public static void main(String[] args) {SpringApplication.run(KafkaLagAwareApplication.class, args);}@Overridepublic void run(String... args) throws Exception {// 模拟生产消息for (int i = 0; i < 1000; i++) {String key = "key-" + (i % 50); // 使用有限的Key,增加分区的重复使用String value = "value-" + i;producer.sendMessage(key, value);Thread.sleep(10); // 控制生产速率}}
}

总结

本文详细介绍了如何在Kafka中实现一个基于Key的Lag感知生产者与消费者,通过监控各分区的Lag值,动态调整消息的生产与消费策略,达到智能的负载均衡效果。具体实现中:

  1. 生产者:通过自定义分区器 LagAwarePartitioner,在发送消息时根据 Key 的哈希值和分区的 Lag 值选择目标分区。当默认分区的 Lag 超过预设阈值时,自动选择 Lag 最小的分区发送消息。
  2. 消费者:在消费过程中持续监控自身的 Lag 值,当 Lag 超过预设阈值时,主动退出对该分区的订阅,触发消费者组的再平衡机制,使其他消费者接管该分区。
  3. 动态负载均衡:通过生产者和消费者的协同工作,确保高 Lag 分区能够被性能较好的消费者接管,提升整体系统的稳定性和性能。

应用场景:这种机制特别适用于服务器性能不均衡的情况下,能够显著提升整体系统的稳定性和性能,避免因部分节点性能问题导致整个系统的瓶颈。

通过Spring Boot与Spring Kafka的结合,简化了配置与开发流程,使得实现复杂的Kafka消费者逻辑变得更加高效和便捷。未来,可以进一步优化Lag检测与负载转移的策略,例如引入更多的监控指标,结合自动伸缩机制,实现更加智能化的系统自我调节能力。同时,结合容器化和微服务架构,能够在更大规模的分布式环境中,充分发挥基于Key的Lag感知机制的优势,保障数据流处理的高效与可靠。

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

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

相关文章

通宵修bug

前两个月的某天凌晨&#xff0c;我司全新的一个营销工具&#xff0c;在全国如期上线。然而整个发布过程并非一帆风顺&#xff0c;在线上环境全量发布后&#xff0c;有同事观测到他所负责模块的监控曲线有异常&#xff01;监控曲线在发布的时刻近乎于直线下跌。 经过初步排查&am…

Rust-宏编程

巴山楚水凄凉地&#xff0c;二十三年弃置身。 怀旧空吟闻笛赋&#xff0c;到乡翻似烂柯人。 沉舟侧畔千帆过&#xff0c;病树前头万木春。 今日听君歌一曲&#xff0c;暂凭杯酒长精神。 ——《酬乐天扬州初逢席上见赠》唐刘禹锡 【哲理】翻覆的船只旁仍有千千万万的帆船经过&a…

leetcode912.排序数组的题解

题目描述&#xff1a; 题目要求在不使用任何内置函数的情况下解决问题&#xff0c;时间复杂度为 O(nlog(n))。 笔者使用了快速排序&#xff0c;但是直接使用最原始的快速排序&#xff0c;有些特殊的测试用例会超时。 1&#xff09;如果数组本身基本有序&#xff0c;则使用原始…

TikTok品牌出海:从“流量为王”到“价值为王”

随着市场竞争的加剧&#xff0c;品牌逐渐意识到&#xff0c;仅仅依靠流量已不足以在海外市场立足&#xff0c;必须实现从“流量为王”到“价值为王”的转变。本文Nox聚星将和大家探讨品牌如何与TikTok达人合作&#xff0c;在海外市场中建立长期稳定的品牌形象。 一、品牌出海的…

纯血鸿蒙系统 HarmonyOS NEXT自动化测试实践

1、测试框架选择 hdc&#xff1a;类似 android 系统的 adb 命令&#xff0c;提供设备信息查询&#xff0c;包管理&#xff0c;调试相关的命令ohos.UiTest&#xff1a;鸿蒙 sdk 的一部分&#xff0c;类似 android sdk 里的uiautomator&#xff0c;基于 Accessibility 服务&…

Kafka 可观测性最佳实践

Kafka 概述 Kafka 是由 LinkedIn 开发一个分布式的基于发布订阅模式的消息队列&#xff0c;是一个实时数据处理系统&#xff0c;可以横向扩展。与 RabbitMQ、RockerMQ 等中间件一样拥有几大特点&#xff1a; 异步处理服务解耦流量削峰 监控 Kafka 是非常重要的&#xff0c;因…

《XGBoost算法的原理推导》12-13树的叶子节点权重w和映射关系q 公式解析

本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 我们重新定义一颗树&#xff0c;包括两个部分&#xff1a; 叶子结点的权重向量 w w w&#xff1b;实例 -> 叶子结点的映射关系 q q q&#xff08;本质是树的…

电商API:开启电商新时代的关键钥匙

一、电商API&#xff1a;定义与发展 电商API&#xff0c;即应用程序编程接口&#xff0c;是连接不同软件系统的桥梁&#xff0c;在电商领域中发挥着至关重要的作用。电商API的发展历程可以追溯到20世纪90年代&#xff0c;当时电子商务刚刚兴起&#xff0c;企业开始意识到通过A…

多client向同一个pushgateway推送指标被覆盖问题

问题: 多个client向同一个pushgateway推送指标&#xff0c;每个client推送的指标名称相同但是lable不同。如下&#xff1a; # TYPE ObjectCount gauge ObjectCount{server_id"server1"} 4 ObjectCount{server_id"server2"} 4 ObjectCount{server_id"…

C++__XCode工程中Debug版本库向Release版本库的切换

Debug和Release版本分别设置编译后&#xff0c;就分别得到了对应的lib库&#xff0c;如下图&#xff1a; 再生成Release后如下图&#xff1a;

梧桐数据库中处理连续日期序列的解决方案

在数据库管理中&#xff0c;处理时间序列数据是一项常见的任务&#xff0c;尤其是在需要识别连续日期序列的场景中。例如&#xff0c;在一个生产环境中&#xff0c;我们可能需要跟踪产品的输出类型&#xff0c;并记录这些输出是否连续。本文将介绍如何在梧桐数据库中实现这一功…

增删改增删改

savePostMapping("/save") public ResponseResult save(RequestBody ChannelDto channelDto){ // 参数判断 if(channelDto null || StringUtils.isBlank(channelDto.getName())){ return ResponseResult.error(AppHttpCodeEnum.PARA…

消费疲软下,家居品牌如何利用营销实现新的突围与增长?

在消费疲软的大环境下&#xff0c;家居品牌面临着前所未有的挑战与机遇。尤其以耐消品为主的家居行业&#xff0c;也受到一定程度影响——有效需求不足导致产能过剩&#xff0c;营销乏力&#xff0c;市场竞争开始变得激烈&#xff0c;不少家居品牌正在面临业绩压力。家居品牌如…

Apache Shiro -配置先后的影响

在Apache Shiro框架中&#xff0c;shiroFilterChainDefinition&#xff08;或filterChainDefinitions&#xff09;的配置顺序确实有影响。以下是具体的影响和原因&#xff1a; URL匹配规则&#xff1a;Shiro在验证URL时&#xff0c;会按照filterChainDefinitions中配置的顺序进…

How to use ffmpeg to convert video format from .webm to .mp4

The .mp4 container format doesn’t support the VP8 codec, which is commonly used in .webm files. MP4 containers typically use the H.264 codec for video and AAC for audio. You’ll need to re-encode the video using the H.264 codec and re-encode the audio us…

ORACLE _11G_R2_ASM 常用命令

--------查看磁盘组&#xff0c;(空间情况) select name,state,free_mb,total_mb,usable_file_mb from v$asm_diskgroup; --------查看磁盘情况 select GROUP_NUMBER,free_mb,total_mb,disk_number,MOUNT_STATUS,mode_status, HEADER_STATUS,name,PATH from v$asm_disk order …

连985都没有面试机会 二本就更没戏了:瞎说,这就是三年高考的意义

最近有二本同学在直播里说&#xff1a;“看到很多面经说&#xff0c;连985同学都没有面试机会&#xff0c;而且是零offer。那我们二本就更没戏了。” 其实这种言论是在瞎扯。 我们一直在强调校招是分层的。 现在学生太多了&#xff0c;而且招聘对学历是有要求的。比如大厂的…

微信小程序运营日记(第四天)

2024年11月6日-星期三-2024年45周 {微信小程序的时间板块进行一个增加&#xff0c;增加&#xff1a;2024年第45周|共53周&#xff0c;星期三&#xff0c;今年时间剩余&#xff0c;本周时间剩余} 开源竞争&#xff1a; 开源竞争&#xff08;当你无法掌握一个技术就开源这个技术…

greendao使用封装

1. 确保正确配置 greenDAO 首先,确保您在项目的 build.gradle 文件中添加了 greenDAO 的依赖: dependencies {implementation org.greenrobot:greendao:3.3.0 // 根据需要选择合适的版本annotationProcessor org.greenrobot:greendao-compiler:3.3.0 // 仅在 Java 中使用 }…

linux tar 打包为多个文件

将目录打包成多个大小为 80MB 的文件&#xff0c;可以使用以下命令&#xff1a; tar -cf - my_folder | split -b 80m - my_folder.tar.解释&#xff1a; tar -cf - my_folder 将 my_folder 目录打包成一个 tar 文件并通过管道 (|) 输出到标准输出。 split -b 80m - my_fold…