JavaEE技术之MySql高级-ShardingSphere5(SpringBoot版本:3.0.5)

文章目录

  • 1 ShardingSphere-JDBC读写分离
    • 1.1 创建SpringBoot程序
      • 1.1.1、创建项目
      • 1.1.2、添加依赖
      • 1.1.3、创建实体类
      • 1.1.4、创建Mapper
      • 1.1.5、配置 Spring Boot
      • 1.1.6、配置shardingsphere
    • 1.2 测试
      • 1.2.1 读写分离测试
      • 1.2.2 负载均衡测试
      • 1.2.3 事务测试
      • 常见错误
  • 2 ShardingSphere-JDBC垂直分片
    • 2.1 准备服务器
      • 2.1.1、创建server-user容器
      • 2.1.2、创建server-order容器
    • 2.2 程序实现
      • 2.2.1、创建实体类
      • 2.2.2、创建Mapper
      • 2.2.3、配置垂直分片
    • 2.3 测试垂直分片
  • 3 ShardingSphere-JDBC水平分片
    • 3.1 准备服务器
      • 3.1.1、创建server-order0容器
      • 3.1.2、创建server-order1容器
    • 3.2 水平分片
      • 3.2.1、配置一个分片节点
      • 3.2.2、水平分库配置
      • 3.2.3、水平分表配置
    • 3.3 多表关联
      • 3.3.1、创建关联表
      • 3.3.2、创建实体类
      • 3.3.3、创建Mapper
      • 3.3.4、配置关联表
      • 3.3.5、测试插入数据

1 ShardingSphere-JDBC读写分离

1.1 创建SpringBoot程序

1.1.1、创建项目

项目类型:Spring Initializr

SpringBoot脚手架:http://start.aliyun.com

项目名:sharding-jdbc-demo

SpringBoot版本:3.0.5

1.1.2、添加依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core</artifactId><version>5.4.0</version></dependency><!--兼容jdk17和spring boot3--><dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.33</version></dependency><dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.8</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

1.1.3、创建实体类

package com.atguigu.shardingjdbcdemo.entity;@TableName("t_user")
@Data
public class User {@TableId(type = IdType.AUTO)private Long id;private String uname;
}

1.1.4、创建Mapper

package com.atguigu.shardingjdbcdemo.mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {
}

1.1.5、配置 Spring Boot

application.properties:

# 配置 DataSource Driver
spring.datasource.driver-class-name=org.apache.shardingsphere.driver.ShardingSphereDriver
# 指定 YAML 配置文件
spring.datasource.url=jdbc:shardingsphere:classpath:shardingsphere.yaml

1.1.6、配置shardingsphere

shardingsphere.yaml

模式配置:

mode:type: Standalonerepository:type: JDBC

数据源配置:

dataSources:write_ds:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3306/db_userusername: rootpassword: 123456read_ds_0:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3307/db_userusername: rootpassword: 123456read_ds_1:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3308/db_userusername: rootpassword: 123456

读写分离配置:

rules:- !READWRITE_SPLITTINGdataSources:readwrite_ds:writeDataSourceName: write_dsreadDataSourceNames:- read_ds_0- read_ds_1transactionalReadQueryStrategy: PRIMARY # 事务内读请求的路由策略,可选值:PRIMARY(路由至主库)、FIXED(同一事务内路由至固定数据源)、DYNAMIC(同一事务内路由至非固定数据源)。默认值:DYNAMICloadBalancerName: randomloadBalancers:random:type: RANDOM

输出sql:

props:sql-show: true

1.2 测试

1.2.1 读写分离测试

package com.atguigu.shardingjdbcdemo;@SpringBootTest
class ShardingJdbcDemoApplicationTests {@Autowiredprivate UserMapper userMapper;/*** 写入数据的测试*/@Testpublic void testInsert(){User user = new User();user.setUname("张三丰");userMapper.insert(user);}}

1.2.2 负载均衡测试

/*** 负载均衡测试*/
@Test
public void testSelect(){for (int i = 0; i < 100; i++) {User user1 = userMapper.selectById(1);}
}

负载均衡算法配置:

rules:- !READWRITE_SPLITTINGloadBalancers:random:type: RANDOMround_robin:type: ROUND_ROBINweight:type: WEIGHTprops:read_ds_0: 1read_ds_1: 2

1.2.3 事务测试

transactionalReadQueryStrategy: PRIMARY

事务内读请求的路由策略,可选值:

PRIMARY(路由至主库)

FIXED(同一事务内路由至固定数据源)

DYNAMIC(同一事务内路由至非固定数据源)。默认值:DYNAMIC

测试1:

不添加@Transactional:insert对主库操作,select对从库操作

测试2:

添加@Transactional:则insert和select按照transactionalReadQueryStrategy的配置执行

/*** 事务测试*/
@Transactional//开启事务
@Test
public void testTrans(){User user = new User();user.setUname("铁锤");userMapper.insert(user);List<User> users = userMapper.selectList(null);
}

**注意:**在JUnit环境下的@Transactional注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback,也会对事务回滚)

常见错误

在这里插入图片描述

ShardingSphere-JDBC远程连接的方式默认的密码加密规则是:mysql_native_password

因此需要在服务器端修改服务器的密码加密规则,如下:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

2 ShardingSphere-JDBC垂直分片

2.1 准备服务器

服务器规划:使用docker方式创建如下容器

在这里插入图片描述

  • 服务器:容器名server-user,端口 3301

  • 服务器:容器名server-order,端口3302

2.1.1、创建server-user容器

  • step1:创建容器:
docker run -d \
-p 3318:3306 \
-v mysql-order-conf:/etc/mysql/conf.d \
-v mysql-order-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name mysql-order \
mysql:8
  • step2:登录MySQL服务器:
#进入容器:
docker exec -it server-user env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • step3:创建数据库:
CREATE DATABASE db_user;
USE db_user;
CREATE TABLE t_user (id BIGINT AUTO_INCREMENT,uname VARCHAR(30),PRIMARY KEY (id)
);

2.1.2、创建server-order容器

  • step1:创建容器:
docker run -d \
-p 3302:3306 \
-v /atguigu/server/order/conf:/etc/mysql/conf.d \
-v /atguigu/server/order/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order \
mysql:8.0.29
  • step2:登录MySQL服务器:
#进入容器:
docker exec -it server-order env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • step3:创建数据库:
CREATE DATABASE db_order;
USE db_order;
CREATE TABLE t_order (id BIGINT AUTO_INCREMENT,order_no VARCHAR(30),user_id BIGINT,PRIMARY KEY(id) 
);

2.2 程序实现

2.2.1、创建实体类

package com.atguigu.shardingjdbcdemo.entity;@TableName("t_order")
@Data
public class Order {@TableId(type = IdType.AUTO)private Long id;private String orderNo;private Long userId;
}

2.2.2、创建Mapper

package com.atguigu.shardingjdbcdemo.mapper;@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}

2.2.3、配置垂直分片

模式配置

mode:type: Standalonerepository:type: JDBC

数据源配置:

dataSources:user_ds:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3301/db_userusername: rootpassword: 123456order_ds:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3302/db_orderusername: rootpassword: 123456

垂直分片配置:

rules:- !SHARDINGtables:t_user:actualDataNodes: user_ds.t_usert_order:actualDataNodes: order_ds.t_order

输出sql:

props:sql-show: true

2.3 测试垂直分片

@Autowired
private UserMapper userMapper;@Autowired
private OrderMapper orderMapper;/*** 垂直分片:插入数据测试*/
@Test
public void testInsertOrderAndUser(){User user = new User();user.setUname("强哥");userMapper.insert(user);Order order = new Order();order.setOrderNo("ATGUIGU001");order.setUserId(user.getId());orderMapper.insert(order);}/*** 垂直分片:查询数据测试*/
@Test
public void testSelectFromOrderAndUser(){User user = userMapper.selectById(1L);Order order = orderMapper.selectById(1L);
}

3 ShardingSphere-JDBC水平分片

3.1 准备服务器

服务器规划:使用docker方式创建如下容器

在这里插入图片描述

  • 服务器:容器名server-order0,端口3310

  • 服务器:容器名server-order1,端口3311

3.1.1、创建server-order0容器

  • step1:创建容器:
docker run -d \
-p 3319:3306 \
-v /atguigu/server/order0/conf:/etc/mysql/conf.d \
-v /atguigu/server/order0/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order2 \
mysql:8.0.29
  • step2:登录MySQL服务器:
#进入容器:
docker exec -it server-order0 env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • step3:创建数据库:

注意:水平分片的id需要在业务层实现,不能依赖数据库的主键自增

CREATE DATABASE db_order;
USE db_order;
CREATE TABLE t_order0 (id BIGINT,order_no VARCHAR(30),user_id BIGINT,PRIMARY KEY(id) 
);
CREATE TABLE t_order1 (id BIGINT,order_no VARCHAR(30),user_id BIGINT,PRIMARY KEY(id) 
);

3.1.2、创建server-order1容器

  • step1:创建容器:
docker run -d \
-p 3311:3306 \
-v /atguigu/server/order1/conf:/etc/mysql/conf.d \
-v /atguigu/server/order1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order1 \
mysql:8.0.29
  • step2:登录MySQL服务器:
#进入容器:
docker exec -it server-order1 env LANG=C.UTF-8 /bin/bash
#进入容器内的mysql命令行
mysql -uroot -p
#修改默认密码插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
  • **step3:创建数据库:**和server-order0相同

注意:水平分片的id需要在业务层实现,不能依赖数据库的主键自增

CREATE DATABASE db_order;
USE db_order;
CREATE TABLE t_order0 (id BIGINT,order_no VARCHAR(30),user_id BIGINT,PRIMARY KEY(id) 
);
CREATE TABLE t_order1 (id BIGINT,order_no VARCHAR(30),user_id BIGINT,PRIMARY KEY(id) 
);

3.2 水平分片

3.2.1、配置一个分片节点

模式配置

mode:type: Standalonerepository:type: JDBC

数据源配置:

dataSources:user_ds:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3301/db_userusername: rootpassword: 123456order_ds_0:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3310/db_orderusername: rootpassword: 123456order_ds_1:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: jdbc:mysql://192.168.100.101:3311/db_orderusername: rootpassword: 123456

配置一个order分片节点:

rules:- !SHARDINGtables:t_user:actualDataNodes: user_ds.t_usert_order:actualDataNodes: order_ds_0.t_order0

输出sql:

props:sql-show: true

修改Order实体类的主键策略:

//@TableId(type = IdType.AUTO)//依赖数据库的主键自增策略
@TableId(type = IdType.ASSIGN_ID)//分布式id

测试代码:

/*** 水平分片:插入数据测试*/
@Test
public void testInsertOrder(){Order order = new Order();order.setOrderNo("ATGUIGU001");order.setUserId(1L);orderMapper.insert(order);
}

3.2.2、水平分库配置

使用行表达式:核心概念 :: ShardingSphere (apache.org)

将数据 分片到order_ds_0和order_ds_1中

actualDataNodes: order_ds_${0..1}.t_order0

分片算法配置

分片规则:order表中user_id为偶数时,数据插入server-order0服务器user_id为奇数时,数据插入server-order1服务器。这样分片的好处是,同一个用户的订单数据,一定会被插入到同一台服务器上,查询一个用户的订单时效率较高。

rules:- !SHARDINGtables:t_user:actualDataNodes: user_ds.t_usert_order:actualDataNodes: order_ds_${0..1}.t_order0databaseStrategy:standard:shardingColumn: user_idshardingAlgorithmName: userid_inlineshardingAlgorithms:userid_inline:type: INLINEprops:algorithm-expression: order_ds_${user_id % 2}

测试:

/*** 水平分片:分库插入数据测试*/
@Test
public void testInsertOrderDatabaseStrategy(){for (long i = 0; i < 4; i++) {Order order = new Order();order.setOrderNo("ATGUIGU" + System.currentTimeMillis());order.setUserId(i + 1);orderMapper.insert(order);}
}

3.2.3、水平分表配置

将数据 分片到order_ds_0和order_ds_1的t_order0和t_order1中

actualDataNodes: order_ds_${0..1}.t_order${0..1}

分片算法配置

分片规则:order表中id为偶数时,数据插入t_order0数据库id为奇数时,数据插入t_order1数据库

rules:- !SHARDINGtables:t_user:actualDataNodes: user_ds.t_usert_order:actualDataNodes: order_ds_${0..1}.t_order${0..1}databaseStrategy:standard:shardingColumn: user_idshardingAlgorithmName: userid_inlinetableStrategy:standard:shardingColumn: idshardingAlgorithmName: orderid_inlineshardingAlgorithms:userid_inline:type: INLINEprops:algorithm-expression: order_ds_${user_id % 2}orderid_inline:type: INLINEprops:algorithm-expression: t_order${id % 2}

测试:

/*** 水平分片:分表插入数据测试*/
@Test
public void testInsertOrderTableStrategy(){for (long i = 0; i < 4; i++) {Order order = new Order();order.setOrderNo("ATGUIGU" + System.currentTimeMillis());order.setUserId(1L);orderMapper.insert(order);}for (long i = 0; i < 4; i++) {Order order = new Order();order.setOrderNo("ATGUIGU" + System.currentTimeMillis());order.setUserId(2L);orderMapper.insert(order);}
}

3.3 多表关联

3.3.1、创建关联表

server-order0、server-order1服务器中分别创建两张订单详情表t_order_item0、t_order_item1

我们希望同一个用户的订单表和订单详情表中的数据都在同一个数据源中,避免跨库关联,因此这两张表我们使用相同的分片策略。

那么在t_order_item中我们也需要创建order_iduser_id这两个分片键

CREATE TABLE t_order_item0(id BIGINT,user_id BIGINT,order_id BIGINT,price DECIMAL(10,2),`count` INT,PRIMARY KEY(id)
);CREATE TABLE t_order_item1(id BIGINT,user_id BIGINT,order_id BIGINT,price DECIMAL(10,2),`count` INT,PRIMARY KEY(id)
);

3.3.2、创建实体类

package com.atguigu.shardingjdbcdemo.entity;@TableName("t_order_item")
@Data
public class OrderItem {@TableId(type = IdType.ASSIGN_ID) //分布式idprivate Long id;private Long userId;private Long orderId;private BigDecimal price;private Integer count;
}

3.3.3、创建Mapper

package com.atguigu.shargingjdbcdemo.mapper;@Mapper
public interface OrderItemMapper extends BaseMapper<OrderItem> {
}

3.3.4、配置关联表

t_order_item的分片表、分片策略、分布式序列策略和t_order一致

rules:- !SHARDINGtables:t_user:actualDataNodes: user_ds.t_usert_order:actualDataNodes: order_ds_${0..1}.t_order${0..1}databaseStrategy:standard:shardingColumn: user_idshardingAlgorithmName: userid_inlinetableStrategy:standard:shardingColumn: idshardingAlgorithmName: orderid_inlinet_order_item:actualDataNodes: order_ds_${0..1}.t_order_item${0..1}databaseStrategy:standard:shardingColumn: user_idshardingAlgorithmName: userid_inlinetableStrategy:standard:shardingColumn: order_idshardingAlgorithmName: orderid_item_inlineshardingAlgorithms:userid_inline:type: INLINEprops:algorithm-expression: order_ds_${user_id % 2}orderid_inline:type: INLINEprops:algorithm-expression: t_order${id % 2}orderid_item_inline:type: INLINEprops:algorithm-expression: t_order_item${order_id % 2}

3.3.5、测试插入数据

同一个用户的订单表和订单详情表中的数据都在同一个数据源中,避免跨库关联

   /*** 测试关联表插入*/@Testpublic void testInsertOrderAndOrderItem(){for (long i = 0; i < 2; i++) {Order order = new Order();order.setOrderNo("ATGUIGU" + System.currentTimeMillis());order.setUserId(1L);orderMapper.insert(order);for (long j = 0; j < 2; j++) {OrderItem orderItem = new OrderItem();orderItem.setUserId(1L);orderItem.setOrderId(order.getId());orderItem.setPrice(new BigDecimal(10));orderItem.setCount(2);orderItemMapper.insert(orderItem);}}for (long i = 0; i < 2; i++) {Order order = new Order();order.setOrderNo("ATGUIGU" + System.currentTimeMillis());order.setUserId(2L);orderMapper.insert(order);for (long j = 0; j < 2; j++) {OrderItem orderItem = new OrderItem();orderItem.setUserId(2L);orderItem.setOrderId(order.getId());orderItem.setPrice(new BigDecimal(5));orderItem.setCount(2);orderItemMapper.insert(orderItem);}}}

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

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

相关文章

JSP技术讲解

目录 1、JSP简介 2、JSP体验 3、JSP运行原理 4、JSP基本语法 5、JSP指令 6、JSP内置九大对象 7、JSP标签 8、JSP配置 9、JSP排错 10、总结 在前面的Servlet学习中发现Servlet本质是一个java程序&#xff0c;因此Servlet更加擅长编写程序的业务逻辑&#xff0c;而如果要…

数据结构学习——线性表、顺序表

1.线性表 线性表 &#xff08; linear list &#xff09; 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一…

ICode国际青少年编程竞赛- Python-2级训练场-列表入门

ICode国际青少年编程竞赛- Python-2级训练场-列表入门 1、 Dev.step(3)2、 Flyer.step(1) Dev.step(-2)3、 Flyer.step(1) Spaceship.step(7)4、 Flyer.step(5) Dev.turnRight() Dev.step(5) Dev.turnLeft() Dev.step(3) Dev.turnLeft() Dev.step(7) Dev.turnLeft() Dev.…

pytest教程-41-钩子函数-pytest_runtest_teardown

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了pytest_runtest_call钩子函数的使用方法&#xff0c;本小节我们讲解一下pytest_runtest_teardown钩子函数的使用方法。 pytest_runtest_teardown 钩子函数在每个测试用例执行完成后被调用&…

数据结构学习——二叉树

1. 树概念及结构 1.1 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个特殊的结点&…

【Docker学习】docker run的端口映射-p和-P选项

docker run的端口映射选项分为-p&#xff08;小写&#xff0c;全称--publish&#xff09;&#xff0c;-P&#xff08;大写&#xff0c;全称--publish-all&#xff09;&#xff0c;之前认为只有改变容器发布给宿主机的默认端口号才会进行-p的设置&#xff0c;而不改变默认端口号…

Java面试八股文(MySQL篇)

数据库三范式 数据库事务介绍 索引介绍 SQL优化手段 mysql union 与 union all 语法及用法 并发事务带来的问题 大表如何优化 索引类型介绍 MYSQL数据库锁介绍

leetcode91.解码方法(动态规划)

问题描述&#xff1a; 一条包含字母 A-Z 的消息通过以下映射进行了 编码 &#xff1a; A -> "1" B -> "2" ... Z -> "26" 要 解码 已编码的消息&#xff0c;所有数字必须基于上述映射的方法&#xff0c;反向映射回字母&#xff08;可…

如何才能做好源代码防泄密

目前很多企业都拥有自己的研发机构&#xff0c;其研发成果往往体现在源代码和技术文档方面&#xff0c;这些核心机密&#xff0c;如何防止研发参与人员泄密&#xff0c;如何防止核心成员把研究成果带走另立山头&#xff0c;或者提供给竞争对手&#xff0c;是一个很现实的一个问…

Vue-路由介绍

目录 一、思考引入 二、路由介绍 一、思考引入 单页面应用程序&#xff0c;之所以开发效率高&#xff0c;性能高&#xff0c;用户体验好&#xff0c;是因为页面按需更新。 而如果要按需更新&#xff0c;首先需要明确&#xff1a;访问路径和组件的对应关系。该关系通过路由来…

Vue CLI配置代理、2.0、3.0

一、vue cli2.0 代理配置 proxy: {/api:{target: "http://localhost:8067",pathRewrite: {/api: }}, } 一、vue cli3.0 代理配置 proxy: {/api: {target: http://localhost:8067,pathRewrite: {/api: }} }

【C++】滑动窗口:最大连续1的个数

1.题目 2.算法思路 其实在做这道题的时候并不需要真的把0翻转成1&#xff0c;只需要找到最长的子数组且该子数组中0的个数不大于K&#xff0c;就可以了&#xff01; 当然我们首先想到的是暴力穷举法&#xff1a; 找到所有符合题意的子数组&#xff0c;跳出最长的那个就可以了…