Spring Boot集成ShardingSphere实现按月数据分片及创建自定义分片算法 | Spring Cloud 44

news2024/11/24 16:40:47

一、前言

在前面我们通过以下章节对数据分片有了基础的了解:

Spring Boot集成ShardingSphere实现数据分片(一) | Spring Cloud 40

Spring Boot集成ShardingSphere实现数据分片(二) | Spring Cloud 41

Spring Boot集成ShardingSphere实现数据分片(三) | Spring Cloud 42

书接上回,本章进行对以下部分进行讲解演示:

  • 基于时间范围的分片算法(INTERVAL)实现按月数据分片
  • 创建自定义ShardingSphere分片算法及实现按月数据分片

下面我们开始正文内容。

二、时间范围分片算法

2.1 简介

  • 类型:INTERVAL

  • 可配置属性:

属性名称数据类型说明默认值
datetime-patternString分片键的时间戳格式,必须遵循 Java DateTimeFormatter 的格式。例如:yyyy-MM-dd HH:mm:ssyyyy-MM-ddHH:mm:ss 等。但不支持与 java.time.chrono.JapaneseDate 相关的 Gy-MM
datetime-lowerString时间分片下界值,格式与 datetime-pattern 定义的时间戳格式一致
datetime-upper (可选项)String时间分片上界值,格式与 datetime-pattern 定义的时间戳格式一致当前时间
sharding-suffix-patternString分片数据源或真实表的后缀格式,必须遵循 Java DateTimeFormatter 的格式,必须和 datetime-interval-unit 保持一致。例如:yyyyMM对应MONTHS
datetime-interval-amount (可选项)int分片键时间间隔,超过该时间间隔将进入下一分片1
datetime-interval-unit (可选项)String分片键时间间隔单位,必须遵循 Java ChronoUnit 的枚举值。例如:MONTHSDAYS
  • 所属类:org.apache.shardingsphere.sharding.algorithm.sharding.datetime.IntervalShardingAlgorithm

  • 注意事项:

    此算法主动忽视了 datetime-pattern 的时区信息。 这意味着当 datetime-lower, datetime-upper 和传入的分片键含有时区信息时,不会因为时区不一致而发生时区转换。 当传入的分片键为 java.time.Instant 时存在特例处理,其会携带上系统的时区信息后转化为 datetime-pattern 的字符串格式,再进行下一步分片。

ShardingSphere内置提供了多种分片算法,请见官网:
https://shardingsphere.apache.org/document/5.2.1/cn/user-manual/common-config/builtin-algorithm/sharding/

2.2 使用示例

2.2.1 项目总体结构

在这里插入图片描述

2.2.2 Maven依赖

shading-sphere/shading-tables/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>shading-sphere</artifactId>
        <groupId>com.gm</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shading-tables</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>


        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.33</version>
        </dependency>

    </dependencies>

</project>
  • shardingsphere-jdbc-core-spring-boot-starter使用版本5.2.1

  • JDBCORM 框架选用mybatis-plus

2.2.3 逻辑表 t_share_month

DROP TABLE IF EXISTS `t_share_month_202304`;
CREATE TABLE `t_share_month_202304`  (
  `id` bigint NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `create_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

DROP TABLE IF EXISTS `t_share_month_202305`;
CREATE TABLE `t_share_month_202305`  (
  `id` bigint NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `create_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

DROP TABLE IF EXISTS `t_share_month_202306`;
CREATE TABLE `t_share_month_202306`  (
  `id` bigint NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `create_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

2.2.4 配置文件

shading-sphere/shading-tables/src/main/resources/application.yml

spring:
  application:
    name: @artifactId@
  shardingsphere:
    # 数据源配置
    datasource:
      names: ds1
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.0.35:3306/db1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        username: root
        password: '1qaz@WSX'

    # 定义规则
    rules:
      sharding:
        # 数据分片规则配置
        tables:
          # 指定某个表的分片配置,逻辑表名
          t_share_month:
            actual-data-nodes: ds1.t_share_month_202$->{304..306}
            #actual-data-nodes: ds1.t_share_month_${2022..2030}${(1..12).collect{t ->t.toString().padLeft(2,'0')}}
            table-strategy:
              standard:
                sharding-column: create_time
                sharding-algorithm-name: t_share_month_table_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
        # 分片算法配置
        sharding-algorithms:
          # 分片算法名称
          t_share_month_table_inline:
            type: INTERVAL
            props:
              datetime-pattern: yyyy-MM-dd HH:mm:ss
              datetime-lower: 2023-04-01 00:00:00
              datetime-interval-unit: MONTHS
              sharding-suffix-pattern: yyyyMM
        # 分布式序列算法配置(如果是自动生成的,在插入数据的sql中就不要传id,null也不行,直接插入字段中就不要有主键的字段)
        keyGenerators:
          # 分布式序列算法名称
          snowflake:
            # 分布式序列算法类型
            type: SNOWFLAKE

    props:
      sql-show: true #显示sql

配置简要说明:

  • 逻辑表t_share_month按照create_time分片键进行每月数据分片

注意事项:

  • 当部分月份的物理表未实际创建时,会造成分布式序列不生效,此时如物理表主键采用分布式序列会提示:Cause: java.sql.SQLException: Field 'id' doesn't have a default value

三、自定义分片算法

ShardingSphere支持两种方式来扩展自定义算法:SPIClassBasedCLASS_BASE实际上是已经实现了的SPI

目录结构及依赖情况,请见2.2.12.2.2章节。

ShardingSphere内置提供了多种分片算法,请见官网:
https://shardingsphere.apache.org/document/5.2.1/cn/user-manual/common-config/builtin-algorithm/sharding/

3.1 创建自定义分片算法

新建一个类MonthStrategyShardingAlgorithm并实现StandardShardingAlgorithm接口。

com/gm/shading/tables/component/MonthStrategyShardingAlgorithm.java

import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
public class MonthStrategyShardingAlgorithm implements StandardShardingAlgorithm<LocalDateTime> {

    /** 配置值需要储存 */
    private Properties props;

    private static final DateTimeFormatter yyyyMM = DateTimeFormatter.ofPattern("yyyyMM");

    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<LocalDateTime> preciseShardingValue) {
        LocalDateTime dateTime = preciseShardingValue.getValue();
        String tableSuffix = dateTime.format(yyyyMM);
        String logicTableName = preciseShardingValue.getLogicTableName();
        String table = logicTableName.concat("_").concat(tableSuffix);
        System.out.println("MonthStrategyShardingAlgorithm.doSharding table name: {}" + table);
        return collection.stream().filter(s -> s.equals(table)).findFirst().orElseThrow(() -> new RuntimeException("逻辑分表不存在"));
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<LocalDateTime> rangeShardingValue) {
        // 逻辑表名
        String logicTableName = rangeShardingValue.getLogicTableName();

        // between and 的起始值
        Range<LocalDateTime> valueRange = rangeShardingValue.getValueRange();

        Set<String> queryRangeTables = extracted(logicTableName, valueRange.lowerEndpoint(), valueRange.upperEndpoint());
        ArrayList<String> tables = new ArrayList<>(collection);
        tables.retainAll(queryRangeTables);
        System.out.println("MonthStrategyShardingAlgorithm.doSharding tables collection name: {}" + tables);
        return tables;
    }


    /**
     * 根据范围计算表明
     *
     * @param logicTableName 逻辑表明
     * @param lowerEndpoint  范围起点
     * @param upperEndpoint  范围终端
     * @return 物理表名集合
     */
    private Set<String> extracted(String logicTableName, LocalDateTime lowerEndpoint, LocalDateTime upperEndpoint) {
        Set<String> rangeTable = new HashSet<>();
        while (lowerEndpoint.isBefore(upperEndpoint)) {
            String str = getTableNameByDate(lowerEndpoint, logicTableName);
            rangeTable.add(str);
            lowerEndpoint = lowerEndpoint.plusMonths(1);
        }
        // 获取物理表明
        String tableName = getTableNameByDate(upperEndpoint, logicTableName);
        rangeTable.add(tableName);
        return rangeTable;
    }

    /**
     * 根据日期获取表明
     *
     * @param dateTime       日期
     * @param logicTableName 逻辑表名
     * @return 物理表名
     */
    private String getTableNameByDate(LocalDateTime dateTime, String logicTableName) {
        String tableSuffix = dateTime.format(yyyyMM);
        return logicTableName.concat("_").concat(tableSuffix);
    }

    @Override
    public Properties getProps() {
        return props;
    }

    @Override
    public void init(Properties properties) {
        this.props = properties;
    }

    @Override
    public String getType() {
        return "CREATE_TIME";
    }

}

3.2 基于ClassBased使用自定义分片算法

完整配置文件如下:

server:
  port: 8844

spring:
  application:
    name: @artifactId@
  shardingsphere:
    # 数据源配置
    datasource:
      names: ds1
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.0.35:3306/db1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        username: root
        password: '1qaz@WSX'

    # 定义规则
    rules:
      sharding:
        # 数据分片规则配置
        tables:
          # 指定某个表的分片配置,逻辑表名
          t_share_month:
            actual-data-nodes: ds1.t_share_month_202$->{304..306}
            #actual-data-nodes: ds1.t_share_month_${2022..2030}${(1..12).collect{t ->t.toString().padLeft(2,'0')}}
            table-strategy:
              standard:
                sharding-column: create_time
                sharding-algorithm-name: t_share_month_table_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
        # 分片算法配置
        sharding-algorithms:
          # 分片算法名称
          t_share_month_table_inline:
            type: CLASS_BASED
            props:
              strategy: standard
              # 自定义标准分配算法
              algorithmClassName: com.gm.shading.tables.component.MonthStrategyShardingAlgorithm

        # 分布式序列算法配置(如果是自动生成的,在插入数据的sql中就不要传id,null也不行,直接插入字段中就不要有主键的字段)
        keyGenerators:
          # 分布式序列算法名称
          snowflake:
            # 分布式序列算法类型
            type: SNOWFLAKE

    props:
      sql-show: true #显示sql

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

自定义算法核心配置:

          # 分片算法名称
          t_share_month_table_inline:
            type: CLASS_BASED
            props:
              strategy: standard
              # 自定义标准分配算法
              algorithmClassName: com.gm.shading.tables.component.MonthStrategyShardingAlgorithm

3.3 基于SPI使用自定义分片算法

3.3.1 SPI配置

META-INF/services/org.apache.shardingsphere.sharding.spi.ShardingAlgorithm 文件中添加自定义分片算法全类名:

com.gm.shading.tables.component.MonthStrategyShardingAlgorithm

在这里插入图片描述

3.3.2 配置文件

完整配置文件如下:

server:
  port: 8844

spring:
  application:
    name: @artifactId@
  shardingsphere:
    # 数据源配置
    datasource:
      names: ds1
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.0.35:3306/db1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
        username: root
        password: '1qaz@WSX'

    # 定义规则
    rules:
      sharding:
        # 数据分片规则配置
        tables:
          # 指定某个表的分片配置,逻辑表名
          t_share_month:
            actual-data-nodes: ds1.t_share_month_202$->{304..306}
            #actual-data-nodes: ds1.t_share_month_${2022..2030}${(1..12).collect{t ->t.toString().padLeft(2,'0')}}
            table-strategy:
              standard:
                sharding-column: create_time
                sharding-algorithm-name: t_share_month_table_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
        # 分片算法配置
        sharding-algorithms:
          # 分片算法名称
          t_share_month_table_inline:
            type: CREATE_TIME

        # 分布式序列算法配置(如果是自动生成的,在插入数据的sql中就不要传id,null也不行,直接插入字段中就不要有主键的字段)
        keyGenerators:
          # 分布式序列算法名称
          snowflake:
            # 分布式序列算法类型
            type: SNOWFLAKE

    props:
      sql-show: true #显示sql

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

自定义算法核心配置:

        # 分片算法配置
        sharding-algorithms:
          # 分片算法名称
          t_share_month_table_inline:
            type: CREATE_TIME

注意事项:

  • 配置文件中分片算法的type属性,必须与自定义分片算法中的getType()方法的值相对应。

3.4 源码

上述示例完整源码请见:https://gitee.com/gm19900510/springboot-cloud-example.git

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

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

相关文章

【Windows】高效的本地文件搜索工具《Everything》

&#x1f433;好用高效的本地文件搜索工具《Everything》 &#x1f9ca;一、什么是Everything&#x1f9ca;二、为什么选择Everything&#x1f9ca;三、下载Everything&#x1f9ca;四、Everything为什么高效 &#x1f9ca;一、什么是Everything Everything是一个运行于Window…

单片机GD32F303RCT6 (Macos环境)开发 (五)—— IAP代码架构工程

IAP代码架构工程 1、IAP一般分两个工程&#xff0c;一个Bootloader工程&#xff0c;一个Application工程。 这两个工程的差异后面会讲。 IAP架构工程的好处在于产品上线以后&#xff0c;想要升级的话&#xff0c;不用借助烧录器&#xff0c;就可以完成产品的软件升级。 2、Boo…

轻量级团队协作工具推荐,提高效率从选择开始

首先不得不夸一句&#xff1a;爱用Zoho工具的人&#xff0c;都十分自律和高效&#xff0c;因为Zoho旗下有多种简单好用的团队协作工具。 1、Zoho Projects项目管理工具 项目任务进度和团队沟通与协作管理软件Zoho Projects是一款基于web的软件。专为团队协作而设计&#xff0c;…

手写卡尔曼滤波

形象图 里面的my_Kalman.ipynb 和ppt就是了&#xff0c;其他的是原始资料和 辅助函数 链接&#xff1a;https://pan.baidu.com/s/1J1nA–oqoj8OvgbrA3LfbQ?pwd1264 提取码&#xff1a;1264 import numpy as np import matplotlib.pyplot as plt from matplotlib.animation i…

物理验证LVS对bulk(体)的理解和处理技巧

对于物理验证中的LVS&#xff0c;需要对各种物理器件进行SpiceVsGDS的比对&#xff0c;基于现在流行的std-cell的库的设计方法&#xff0c;LVS需要对CMOS器件多相应的处理&#xff0c;这里会涉及到一些具体的物理库的知识和小的技巧&#xff0c;这里结合具体的物理设计和CDL形态…

网络安全战略:如何应对不断变化的威胁环境?

网络安全一直是大家所关注的重点。在如今的数字化时代&#xff0c;网络安全问题日益严峻&#xff0c;网络攻击者使用更加复杂和高级的攻击方式&#xff0c;企图从各种角度入侵和危害我们的计算机网络。因此&#xff0c;我们必须制定一套完善的网络安全战略&#xff0c;以便更好…

LeetCode 牛客单链表OJ题目分享

目录 链表的回文结构相交链表环形链表I环形链表II 链表的回文结构 链接: link 题目描述&#xff1a; 题目思路&#xff1a; 本题思路是找到每一条链表的中间节点&#xff0c;之后逆置中间节点之后的链表&#xff0c;定义两个指针&#xff0c;分别指向逆置后链表的头部的链表的…

8年资深测试总结,性能测试基础知识(大全)你的进阶之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试&#xf…

力扣sql中等篇练习(十七)

力扣sql中等篇练习(十七) 1 计算布尔表达式的值 1.1 题目内容 1.1.1 基本题目信息1 1.1.2 基本题目信息2 1.1.3 示例输入输出 a 示例输入 b 示例输出 1.2 示例sql语句 # 使用SELECT子句中的子查询查询到对应的值 SELECT t1.left_operand,t1.operator,t1.right_operand,cas…

Obsidian templater日记模板添加一个随机问题

Obsidian templater日记模板添加一个随机问题 简介 每天日记里写同样的东西&#xff0c;感觉有点无聊&#xff0c;想问自己一些问题&#xff0c;每天不同。 查到有插件random structural diary&#xff0c;我想要的功能就是这样&#xff0c;但是没懂这个插件怎么放进templat…

【Android入门到项目实战-- 9.3】—— 加速度传感器的详细使用教程

基础知识 加速度传感器可以返回x、y、z三轴的加速度数值&#xff0c;该数值受地心引力的影响。 将手机平放桌面上&#xff0c;x、y、z轴默认为9.81&#xff1b;手机向下z轴为-9.81。 将手机向左倾斜&#xff0c;x轴为正&#xff0c;向右倾斜&#xff0c;x为负&#xff1b; 将手…

Windows11安装hadoop-3.3.0

一、安装Java 1. 下载Java 进入下载页面Java Archive Downloads - Java SE 8 Java SE Development Kit 8u191中 选择适合操作系统的下载文件 在安装好的路径下&#xff0c;将Java目录复制到C:\根目录下&#xff0c;形成C:\Java\jdk1.8.0_191目录结构 2. 设置环境变量 二、…

Docker虚拟化概念

Docker虚拟化概念 1、虚拟化技术的概念 虚拟化技术主要是将物理资源转变为逻辑上可以管理的资源&#xff1b;用以打破物理资源结构之间的壁垒&#xff1b;让计算的原件运行在虚拟的基础之上&#xff1b;而不是直接运行在硬件设备资源上&#xff1b; 说白了就是硬件资源转变成…

大数据开会记录【NiFi数据集成、AllData数据中台管理系统、RuoYi】

今天上午和下午开了个小会&#xff0c;上午说了一下Nifi&#xff0c;下午具体说了一下nifi和ruoyi。 目录 上午 下午 上午 三个人开会。 上次说的挖掘平台&#xff0c;您这边是否有技术人员对nifi比较熟悉&#xff0c;并且能够将相关功能集成到数据中台系统中。 现在结构化的…

不收费的电脑数据恢复软件EasyRecovery16

EasyRecovery是一款操作安全、恢复性比较高的数据恢复工具&#xff0c;小伙伴们可以使用EasyRecovery恢复各种各样被删除的文件、视频、图片等。EasyRecovery还可以支持恢复被格式化的媒体文件&#xff0c;只是使用EasyRecovery恢复时时间较久。如果小伙伴们有误删除的文件需要…

【Qt 从入门到入土】上篇

【Qt 从入门到入土】下篇 一个非常好的学习 Qt 的视频 本文目录 1. Qt 概述1.1 什么是 Qt1.2 Qt 的发展史1.3 支持的平台1.4 Qt 的版本1.5 Qt 的优点1.6 成功案例 2. 创建 Qt 项目2.1 使用向导创建2.2 手动创建2.3 .pro文件2.4 一个最简单的 Qt 应用程序2.5 Qt 命名规范和常用…

【Java入门合集】第三章面向对象编程(下)

【Java入门合集】第三章面向对象编程&#xff08;下&#xff09; 博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 学习目标 理解面向对象三大主要特征&#xff1b; 掌握类与对象的区别与使用&#xff1b; 掌握类中构造方法以及构造方法重载的概念及使用&#xff1b; 掌握包…

已做过算法题总结

217、存在重复元素(easy) 输入&#xff1a;nums [1,2,3,1] 输出&#xff1a;true 输入&#xff1a;nums [1,2,3,4] 输出&#xff1a;false 输入&#xff1a;nums [1,1,1,3,3,4,3,2,4,2] 输出&#xff1a;true 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &…

【2106. 摘水果】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 在一个无限的 x 坐标轴上&#xff0c;有许多水果分布在其中某些位置。给你一个二维整数数组 fruits &#xff0c;其中 fruits[i] [positioni, amounti] 表示共有 amounti 个水果放置在 positioni 上…

Android平台播放透明视频

Android平台播放透明视频 思路 设计一种特殊的视频&#xff0c;它的一半内容存储alpha信息&#xff0c;另一半内容存储rgb信息&#xff0c;接着通过OpenGL获取每个像素点的alpha值和rgb值进行混合&#xff0c;最后出来的画面就是带有透明效果的视频了。 可以上下的分&#xf…