Java学习笔记(二十四)

1 策略模式

1.1 策略模式概述

策略模式(Strategy Pattern) 是一种行为设计模式,定义了一系列算法,并将它们封装成独立的类,使它们可以互相替换而不会影响使用它们的客户端代码。
策略模式的核心思想是将行为与环境解耦,使得行为可以灵活替换。适用于需要在运行时根据条件选择不同算法或行为的情况。


1.2 策略模式的关键组成

  1. 上下文(Context)

    • 维护对策略对象的引用。
    • 调用策略对象定义的接口以执行具体的行为。
  2. 抽象策略(Strategy)

    • 定义所有支持算法的公共接口。
  3. 具体策略(ConcreteStrategy)

    • 实现具体的算法或行为。

1.3 策略模式的优点

  • 遵循 开闭原则(Open-Closed Principle):可以在不修改上下文类的情况下引入新的策略。
  • 消除大量条件语句(如 if-elseswitch-case)。
  • 策略的实现代码可以独立于使用它的客户端代码,使代码更容易理解和维护。

1.4 策略模式的代码示例

以一个简单的支付系统为例。不同的支付方式(如支付宝、微信支付、信用卡支付)是不同的策略。

1.4.1 Python 实现
from abc import ABC, abstractmethod

# 抽象策略类
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: float):
        pass

# 具体策略:支付宝支付
class Alipay(PaymentStrategy):
    def pay(self, amount: float):
        print(f"Using Alipay to pay {amount} dollars.")

# 具体策略:微信支付
class WeChatPay(PaymentStrategy):
    def pay(self, amount: float):
        print(f"Using WeChat Pay to pay {amount} dollars.")

# 具体策略:信用卡支付
class CreditCardPay(PaymentStrategy):
    def pay(self, amount: float):
        print(f"Using Credit Card to pay {amount} dollars.")

# 上下文类
class PaymentContext:
    def __init__(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def set_strategy(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def pay(self, amount: float):
        self._strategy.pay(amount)

# 客户端代码
if __name__ == "__main__":
    # 初始化支付方式
    alipay = Alipay()
    wechat_pay = WeChatPay()
    credit_card_pay = CreditCardPay()

    # 使用上下文类
    context = PaymentContext(alipay)
    context.pay(100)  # 使用支付宝支付

    context.set_strategy(wechat_pay)
    context.pay(200)  # 使用微信支付

    context.set_strategy(credit_card_pay)
    context.pay(300)  # 使用信用卡支付

1.4.2 Java 实现
// 抽象策略
interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略:支付宝支付
class Alipay implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("Using Alipay to pay " + amount + " dollars.");
    }
}

// 具体策略:微信支付
class WeChatPay implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("Using WeChat Pay to pay " + amount + " dollars.");
    }
}

// 具体策略:信用卡支付
class CreditCardPay implements PaymentStrategy {
    public void pay(double amount) {
        System.out.println("Using Credit Card to pay " + amount + " dollars.");
    }
}

// 上下文类
class PaymentContext {
    private PaymentStrategy strategy;

    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void pay(double amount) {
        strategy.pay(amount);
    }
}

// 客户端代码
public class StrategyPatternDemo {
    public static void main(String[] args) {
        PaymentStrategy alipay = new Alipay();
        PaymentStrategy weChatPay = new WeChatPay();
        PaymentStrategy creditCardPay = new CreditCardPay();

        PaymentContext context = new PaymentContext(alipay);
        context.pay(100); // 使用支付宝支付

        context.setStrategy(weChatPay);
        context.pay(200); // 使用微信支付

        context.setStrategy(creditCardPay);
        context.pay(300); // 使用信用卡支付
    }
}

1.5 应用场景

  1. 电商平台的支付方式切换
  2. 数据压缩工具支持多种压缩算法
  3. 游戏中角色的不同技能组合
  4. 日志系统中不同的日志存储方式(如文件、数据库、云服务)

策略模式适合使用在运行时需要灵活替换算法或行为的场景,是一种极具扩展性和灵活性的设计模式。

2 Kafka 和 Spring Boot 的版本对应关系

以下是 Kafka 和 Spring Boot 的版本对应关系,基于 Spring 官方提供的兼容性指南和常见的版本使用实践:


2.1 Spring Boot 与 Kafka 的版本对应关系

Spring Boot 版本Spring for Apache Kafka 版本Apache Kafka 客户端版本备注
3.1.x3.1.x3.5.x支持最新 Kafka 3.5.x 功能
3.0.x3.0.x3.4.x支持 Kafka Streams 和最新特性
2.7.x ~ 2.6.x2.7.x2.8.x ~ 2.7.x支持 Kafka 2.8.x 和早期版本
2.5.x ~ 2.3.x2.5.x ~ 2.3.x2.5.x ~ 2.3.x通常与 Kafka 2.x 系列配合使用

2.2 如何查看具体的版本兼容性?

2.2.1 Spring Boot 官方 BOM

Spring Boot 管理 Kafka 客户端和 Spring for Apache Kafka 的版本。你可以查看 Spring Boot 的 官方 BOM 文档。

2.2.2 Spring for Apache Kafka Release Notes

Spring Kafka 文档明确了支持的 Kafka 客户端版本,例如:

  • Spring Kafka Releases
2.2.3 Kafka 自身的版本支持

Kafka 客户端通常向后兼容早期的 Kafka Broker 版本,但建议尽量保持客户端和 Broker 的版本一致。


2.3 示例配置

2.3.1 Maven 配置

Spring Boot 的依赖管理通常自动匹配 Spring Kafka 和 Kafka Client 的版本。例如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>
2.3.2 手动指定 Kafka 客户端版本

如果需要特定版本的 Kafka 客户端,可以显式声明:

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>3.5.1</version> <!-- 根据实际需求调整 -->
</dependency>

2.4 注意事项

  1. Kafka 客户端与 Broker 的兼容性
    Kafka 客户端一般兼容同版本及以下版本的 Kafka Broker(向后兼容)。

  2. 测试环境验证
    在实际使用中,推荐使用相同版本的 Kafka 客户端和 Broker,避免潜在兼容性问题。

  3. 升级路径
    如果需要升级 Kafka 或 Spring Boot,请先查阅对应的 Release Notes,逐步升级相关依赖并进行全面测试。

3 和其他消息队列相比,kafka的优势

Kafka 相较于其他消息队列(如 RabbitMQ、ActiveMQ、Redis 等)的主要优势包括以下几个方面:


** 3.1 高吞吐量**

Kafka 设计为能够处理高吞吐量数据流,原因包括:

  • 分布式架构:Kafka 支持分区和分布式部署,能够线性扩展处理能力。
  • 顺序磁盘写入:Kafka 使用顺序磁盘写入代替随机写入,极大地提高了 I/O 性能。
  • 批量处理:支持批量消息的生产和消费,降低了网络传输和磁盘操作的开销。

3.2 高可用性和持久性

  • 复制机制:Kafka 的数据分区支持多副本,确保即使某些节点宕机,数据仍然可用。
  • 分布式存储:数据存储在磁盘中,且通过日志存储实现消息的持久化,提供了可靠性。

3.3 可扩展性

  • Kafka 的分布式架构允许无缝增加节点,通过简单的水平扩展就可以提高集群的处理能力和存储能力。

3.4 低延迟

Kafka 针对大规模实时数据流处理进行了优化,可以实现毫秒级延迟,适用于实时分析和事件处理场景。


3.5 消息顺序保证

Kafka 的分区机制确保同一分区内的消息是有序的,这对于需要严格顺序的应用场景非常重要。


3.6 灵活的消费模型

Kafka 提供了多种消费方式:

  • 多种消费模式:支持发布-订阅模式和点对点模式。
  • 消费者组:通过消费者组实现并行消费和负载均衡。

3.7 强大的生态系统

Kafka 具有强大的生态系统支持:

  • Kafka Streams:内置流式处理框架,用于处理消息流。
  • Kafka Connect:支持与各种外部系统(如数据库、文件系统)的连接。
  • 支持多语言:Kafka 提供多语言的客户端(Java、Python、Go 等)。

3.8 支持回溯和多次消费

Kafka 的消息保存在磁盘上,可配置保留时间,消费者可以通过偏移量回溯消费,不同消费者可以以不同的速度读取相同的数据。


3.9 成本效率

Kafka 的高性能使其在大多数场景下能够以较低的硬件和资源消耗处理高吞吐量的数据流。


3.10 社区活跃与企业广泛使用

Kafka 由 Apache 社区支持,生态系统和更新速度非常活跃,是大多数企业(如 LinkedIn、Uber、Netflix)在大数据和流处理场景下的首选。


3.11 对比总结

特性KafkaRabbitMQActiveMQ
吞吐量
消息持久化强(磁盘日志存储)中(需要配置)中(需要配置)
消费模式发布订阅、消费者组点对点、发布订阅点对点、发布订阅
消息顺序分区内有序无序(需要额外设置)无序(需要额外设置)
可扩展性优秀(分布式架构)一般(扩展困难)一般(扩展困难)
生态系统丰富(Kafka Streams, Kafka Connect)较少较少

Kafka 在高吞吐量、大规模实时数据处理以及复杂数据流集成场景中表现尤为突出,适合大数据平台、实时监控、日志分析等场景。

4 kafka 如何实现搞可靠性

Kafka 的可靠性来源于其独特的架构设计和多层次的保障机制,以下是 Kafka 实现高可靠性的主要原因:


4.1 数据持久化

  • 顺序写磁盘:Kafka 将消息以顺序方式写入磁盘日志,避免随机写操作的高开销,大幅提高磁盘写入效率。
  • 分段日志存储:消息日志分为多个分段文件(Segment),新消息写入最新的分段,老分段被归档或删除。
  • 零拷贝传输:利用操作系统的零拷贝技术,减少数据在内存和磁盘间的拷贝次数,提高可靠性和性能。

4.2 副本机制

  • 多副本复制:每个分区可以配置多个副本,主副本负责读写,副本用于同步数据以防主副本故障。
  • Leader 和 Follower
    • 每个分区有一个 Leader 副本,其余为 Follower 副本。
    • 只有 Leader 接受生产者和消费者的读写请求,Follower 异步同步数据。
  • ACK 确认机制
    • Kafka 提供不同的 acks 设置:
      • acks=0:生产者不等待确认,最低可靠性。
      • acks=1:Leader 确认接收到消息后返回,可靠性适中。
      • acks=all:所有 ISR 副本确认接收到消息后返回,最高可靠性。

4.3 ISR(In-Sync Replica,同步副本集)

  • ISR 是一组与 Leader 副本保持同步的 Follower 副本。
  • 只有 ISR 副本能够在 Leader 副本故障时被选为新的 Leader,保证数据一致性。
  • Kafka 定期检查副本的同步状态,滞后过大的副本会被移出 ISR。

4.4 数据分区和副本分布

  • 分区机制:每个主题被划分为多个分区,分区是 Kafka 的并发和容错基础。
  • 副本分布策略:Kafka 自动将分区副本分布在不同的 Broker 上,防止单点故障。
  • Broker 冗余:即使部分 Broker 故障,Kafka 能够继续运行,保证高可用性。

4.5 消息确认和重试机制

  • 消息确认:消费者通过提交消费位移(Offset)来确认已消费的消息。
  • 未确认消息重试:如果消费位移未提交,Kafka 不会将消息标记为已消费,消费者可以重新消费这些消息。
  • 自动恢复:生产者或消费者在故障后可通过重试机制恢复操作。

4.6 强制数据不丢失的配置

  • 配置参数
    • min.insync.replicas:指定 Leader 必须保持同步的副本数量,小于该值时拒绝写入。
    • replica.lag.time.max.ms:限制 Follower 的同步延迟时间,超时的副本会被移出 ISR。
    • unclean.leader.election.enable:是否允许未同步的副本成为 Leader。设置为 false 可以避免数据丢失。

4.7 Broker 和 Controller 的协作

  • Kafka 集群通过 ZooKeeper(或 KRaft 模式)来管理 Broker 和分区的元数据,保证分区 Leader 的选举和负载均衡的正确性。
  • Controller 负责监控 Broker 状态,并在故障发生时快速重新分配分区 Leader。

4.8 生产者和消费者的容错机制

  • 生产者重试:生产者在消息发送失败时可以自动重试,配合幂等性配置(enable.idempotence=true)防止消息重复。
  • 消费者组再平衡:消费者组支持动态成员管理,在消费者加入或退出时,分区会被重新分配,确保消费任务不会中断。

4.9 高效的日志清理策略

  • Kafka 提供基于时间或日志大小的清理策略,配合 Compact 模式实现按键去重,保持消息持久化的同时节省存储空间。

4.10 总结

Kafka 的可靠性源于其多副本机制、日志持久化、确认和重试机制等设计。通过合理配置参数(如 acks=allmin.insync.replicas),并结合分区和副本分布策略,Kafka 能够提供高度可靠的数据存储和传输保障。

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

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

相关文章

记一次IDOR 和访问控制缺失漏洞挖掘

视频教程在我主页简介和专栏里 测试 IDOR&#xff08;不安全的直接对象引用&#xff09; 漏洞时&#xff0c;我会使用一系列工具&#xff0c;确保不会遗漏任何问题。以下是我的测试方法&#xff1a; 设置 Firefox 和 Pwnfox&#xff1a; 1、我使用 Firefox 浏览器&#xff0c…

GS论文阅读--Hard Gaussian Splatting

前言 本文也是对高斯点云的分布进行优化的&#xff0c;看&#xff01; 文章目录 前言1.背景介绍2.关键内容2.1 位置梯度驱动HGS2.2 渲染误差引导HGS 3.文章贡献 1.背景介绍 在训练过程中&#xff0c;它严重依赖于视图空间位置梯度的平均幅度来增长高斯以减少渲染损失。然而&…

JS基础-操作数组(7)

一.增删改查 1.改 重新赋值 2.增 arr.puch() 末尾追加 arr.unshift() 开头追加 a)案例&#xff1a;数组筛选 3.删除 arr.pop() 删除最后一个元素 arr.shift() 删除第一个元素 splice&#xff08;&#xff09; 删除指定元素

C++otlv4连接sql serveer使用记录(注意点)

C使用otlv4在做插入时&#xff0c;有一些设计的坑需要注意 插入数据&#xff1a; 当要给表中插入单个字符时&#xff0c;数据库表设计使用varchar(1)是合理的&#xff0c;但是otlv4一直报错char。 后续查很久才知道&#xff0c;otlv4所写的绑定的字符数组的长度应该实际数组…

Chapter 6.5-Adding a classification head

Chapter 6 -Fine-tuning for classification 6.5-Adding a classification head 为进行分类微调&#xff0c;须修改预训练的大语言模型&#xff08;LLM&#xff09;。我们将原本把隐藏表征映射到含50,257个词的词表的输出层&#xff0c;替换为一个更小、仅映射到 “0&#xff…

洛谷题目 P1006 [NOIP2008 提高组] 传纸条 题解 (本题较难)

题目传送门&#xff1a; P1006 [NOIP2008 提高组] 传纸条 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 前言&#xff1a; 本题来源于2008年NOIp 提高组竞赛题目&#xff1a;传纸条&#xff0c;本题涉及到动态DP、图论里的费用流知识点&#xff0c;学过图论的都应该对这道题…

智能电动汽车 --- 人工智能(AI)入门

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 简单&#xff0c;单纯&#xff0c;喜欢独处&#xff0c;独来独往&#xff0c;不易合同频过着接地气的生活…

VUE之路由Props、replace、编程式路由导航、重定向

目录 1、路由_props的配置 2、路由_replaces属性 3、编程式路由导航 4、路由重定向 1、路由_props的配置 1&#xff09;第一种写法&#xff0c;将路由收到的所有params参数作为props传给路由组件 只能适用于params参数 // 创建一个路由器&#xff0c;并暴露出去// 第一步…

VS C++ 配置OPENCV环境

VS C 配置OPENCV环境 1.下载opencv2.安装环境3.opencv环境4.VS配置opencv环境5.EXE执行文件路径的环境lib和dll需要根据是debug还是release环境来区分使用哪个 6.Windows环境 1.下载opencv 链接: link 2.安装环境 双击运行即可 3.opencv环境 include文件路径:opencv\build\…

【Redis】持久化机制

目录 前言&#xff1a; RDB 触发RDB持久化方法有俩种&#xff1a; 1.手动触发 2.自动触发 RDB文件的优缺点&#xff1a; AOF: AOF工作机制&#xff1a;​编辑 ​编辑重写机制&#xff1a; 前言&#xff1a; Redis是一个内存数据库&#xff0c;将数据存储在内存中&…

蓝桥杯lesson3---string的使用

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” string的概念 string字符串是一种更加高级的封装&#xff0c;string字符串中包含了大量的方法&#xff0c;这些方法使得字符串的操作变得更加简单&#xff0c;string的使用&…

Arduino D1 通过 Wi-Fi 控制 LED

Arduino D1 通过 Wi-Fi 控制 LED 硬件连接 将 LED 的正极&#xff08;长脚&#xff09;连接到 Arduino D1 的 D1 引脚。将 LED 的负极&#xff08;短脚&#xff09;通过一个电阻&#xff08;例如 220 欧姆&#xff09;连接到 Arduino D1 的 GND 引脚。 安装必要的库 在 Ard…

大模型 / 智能体在智能运维领域的应用总结与发展趋势概述

智能体 智能运维 &#xff1f; 回顾大模型的发展 大模型的发展在过去两年间呈现出爆炸式的增长&#xff0c;成为推动人工智能领域快速进步的关键力量。 2023年3月&#xff1a;百度发布了其知识增强的大语言模型产品“文心一言”&#xff0c;这标志着国内AI大模型产业竞争的…

Unity中在UI上画线

在UI中画一条曲线 我封装了一个组件,可以实现基本的画线需求. 效果 按住鼠标左键随手一画. 用起来也很简单,将组件挂到空物体上就行了,红色的背景是Panel. 你可以将该组件理解为一个Image,只不过形状更灵活一些罢了,所以它要放在下面的层级(不然可能会被挡住). 代码 可以…

【自然语言处理(NLP)】介绍、发展史

文章目录 介绍发展史1. 规则驱动时期&#xff08;20世纪50年代-80年代&#xff09;技术特点标志性成果 2. 统计方法兴起&#xff08;1990年代-2000年代&#xff09;技术特点标志性成果 3. 神经网络复兴&#xff08;2010年代初至今&#xff09;技术特点标志性成果 4. 集成与应用…

【书籍连载】《软件测试架构实践与精准测试》| 川模型的价值

各位软件领域的精英们&#xff0c;今天小编邀请你继续深入学习《软件测试架构实践与精准测试》。 《软件测试架构实践与精准测试》是作者李龙&#xff08;安畅检测首席技术专家&#xff09;基于软件测试“川模型”的著作。本书结合作者首次提出的软件测试新的模型“川模型”测试…

RPC是什么?和HTTP区别?

RPC 是什么&#xff1f;HTTP 是什么&#xff1f; 作为一个程序员&#xff0c;假设我们需要从A电脑的进程发送一段数据到B电脑的进程&#xff0c;我们一般会在代码中使用 Socket 进行编程。 此时&#xff0c;可选性一般就是 TCP 和 UDP 二选一&#xff0c;由于 TCP 可靠、UDP…

08.七种排序算法实现(C语言)

目录 一.排序的基本概念 1.1 排序的概念 1.2 常见的排序算法 二.常见排序算法的实现 2.1 插入排序&#xff08;直接&#xff09; 1.基本思想 2.直接插入排序的特性 3.代码实现 2.2 希尔排序 1.基本思想 2.希尔插入排序的特性 3.代码实现 2.3 选择排序 1.基本思想 2…

Jmeter使用Request URL请求接口

简介 在Jmeter调试接口时&#xff0c;有时不清楚后端服务接口的具体路径&#xff0c;可以使用Request URL和cookie来实现接口请求。以下内容以使用cookie鉴权的接口举例。 步骤 ① 登录网站后获取具体的Request URL和cookie信息 通过浏览器获取到Request URL和cookie&#…

Apache Tomcat文件包含漏洞复现(详细教程)

1.漏洞原理 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;其安装后会默认开启ajp连接器&#xff0c;方便与其他web服务器通过ajp协议进行交互。属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发…