Sharding-JDBC介绍及分库分表实践

news2024/11/18 15:29:27

1.1 ShardingSphere简介

最早是当当网内部使用的一款分库分表框架,名字叫Sharding-JDBC,定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零,适用于任何基于 JDBC 的 ORM 框架,支持任何第三方的数据库连接池,支持任意实现 JDBC 规范的数据库。
2017年的时候开始对外开源,在大量社区贡献者的不断迭代下,功能也逐渐完善,现已更名为ShardingSphere。
2020年正式成为Apache软件基会的顶级项。由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。

1.2 Sharding-JDBC优点

Sharding-JDBC定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。
客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖。
Sharding-JDBC直接封装JDBC API。
旧代码迁移成本几乎为零。
适用于任何基于 JDBC 的 ORM 框架。
支持任何第三方的数据库连接池。
支持任意实现 JDBC 规范的数据库。

1.3 核心概念

1.3.1 LogicTable(逻辑表)

数据分片的逻辑表,对于水平拆分的数据库(表),同一类表的总称。例:订单数据根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order。

1.3.2 ActualTable(真实表)

在分片的数据库中真实存在的物理表。即上个示例中的t_order_0到t_order_9。

1.3.3 DataNode(数据节点)

数据分片的最小单元。由数据源名称和数据表组成,例:ds_1.t_order_0。配置时默认各个分片数据库的表结构均相同,直接配置逻辑表和真实表对应关系即可。如果各数据库的表结果不同,可使用ds.actual_table配置。

1.3.4 BindingTable(绑定表)

指在任何场景下分片规则均一致的主表和子表。例:订单表和订单项表,均按照订单ID分片,则此两张表互为BindingTable关系。BindingTable关系的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。

1.3.5 BroadcastTable(广播表)

指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。

1.4 分片

1.4.1 分片键

用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。例:订单表订单ID分片尾数取模分片,则订单ID为分片字段。SQL中如果无分片字段,将执行全路由,性能较差,支持多分片字段。

1.4.2 分片算法

1.4.2.1 精确分片算法

精确分片算法(PreciseShardingAlgorithm)精确分片算法(=与IN语句),用于处理使用单一键作为分片键的=与IN进行分片的场景。需要配合StandardShardingStrategy使用

1.4.2.2 范围分片算法

范围分片算法(RangeShardingAlgorithm)用于处理使用单一键作为分片键的BETWEEN AND进行分片的场景。需要配合StandardShardingStrategy使用。

1.4.2.3 复合分片算法

复合分片算法(ComplexKeysShardingAlgorithm)用于多个字段作为分片键的分片操作,同时获取到多个分片健的值,根据多个字段处理业务逻辑。需要在复合分片策略(ComplexShardingStrategy )下使用。

1.4.2.4 Hint分片算法

Hint分片算法(HintShardingAlgorithm)稍有不同,上边的算法中我们都是解析 语句提取分片键,并设置分片策略进行分片。但有些时候我们并没有使用任何的分片键和分片策略,可还想将 SQL 路由到目标数据库和表,就需要通过手动干预指定SQL的目标数据库和表信息,也叫强制路由。

1.4.3 分片策略

包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键 + 分片算法,也就是分片策略。目前提供5种分片策略。
一个好的分片策略=好的分片键+好的的分片算法

1.4.3.1 标准分片策略

对应StandardShardingStrategy。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理。

1.4.3.2复合分片策略

对应ComplexShardingStrategy。复合分片策略。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。

1.4.3.3 行表达式分片策略

对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: t_user_$->{u_id % 8} 表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0到t_user_7。

1.4.3.4 Hint分片策略

对应HintShardingStrategy。通过Hint而非SQL解析的方式分片的策略。

1.4.3.5 不分片策略

对应NoneShardingStrategy。不分片的策略。

1.5 分布式主键

等同于本文3.4部分

1.6 分布式事务

数据库事务需要满足ACID(原子性、一致性、隔离性、持久性)四个特性。
原子性(Atomicity)指事务作为整体来执行,要么全部执行,要么全不执行。
一致性(Consistency)指事务应确保数据从一个一致的状态转变为另一个一致的状态。
隔离性(Isolation)指多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability)指已提交的事务修改数据会被持久保存。
在单一数据节点中,事务仅限于对单一数据库资源的访问控制,称之为本地事务。几乎所有的成熟的关系型数据库都提供了对本地事务的原生支持。 但是在基于微服务的分布式应用环境下,越来越多的应用场景要求对多个服务的访问及其相对应的多个数据库资源能纳入到同一个事务当中,分布式事务应运而生。

1.6.1 本地事务

在不开启任何分布式事务管理器的前提下,让每个数据节点各自管理自己的事务。 它们之间没有协调以及通信的能力,也并不互相知晓其他数据节点事务的成功与否。 本地事务在性能方面无任何损耗,但在强一致性以及最终一致性方面则力不从心。

1.6.2 XA强一致事务

XA协议最早的分布式事务模型是X/OPEN国际联盟提出的模型,简称XA协议。
基于XA协议实现的分布式事务对业务侵入很小。 它最大的优势就是对使用方透明,用户可以像使用本地事务一样使用基于XA协议的分布式事务。 XA协议能够严格保障事务ACID特性。
严格保障事务ACID特性是一把双刃剑。 事务执行在过程中需要将所需资源全部锁定,它更加适用于执行时间确定的短事务。 对于长事务来说,整个事务进行期间对数据的独占,将导致对热点数据依赖的业务系统并发性能衰退明显。 因此,在高并发的性能至上场景中,基于XA协议的分布式事务并不是最佳选择。

1.6.3 柔性事务

如果将实现了ACID的事务要素的事务称为刚性事务的话,那么基于BASE事务要素的事务则称为柔性事务。BASE是基本可用、柔性状态和最终一致性这三个要素的缩写。
基本可用(Basically Available)保证分布式事务参与方不一定同时在线。
柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉。
而最终一致性(Eventually consistent)通常是通过消息可达的方式保证系统的最终一致性。

1.7 读写分离

在这里插入图片描述

1.7.1 读写分离核心概念

1.7.1.1 主库

添加、更新以及删除数据操作所使用的数据库,目前仅支持单主库。

1.7.1.2 从库

查询数据操作所使用的数据库,可支持多从库。

1.7.1.3 主从同步

将主库的数据异步的同步到从库的操作。由于主从同步的异步性,从库与主库的数据会短时间内不一致。

1.7.1.4 负载均衡策略

通过负载均衡策略将查询请求疏导至不同从库。

1.7.1.5 Config Map

配置读写分离数据源的元数据,可通过调用ConfigMapContext.getInstance()获取ConfigMap中的masterSlaveConfig数据。例:如果机器权重不同则流量可能不同,可通过ConfigMap配置机器权重元数据。

1.7.2 核心功能

提供了一主多从的读写分离配置,可独立使用,也可配合分库分表使用
同一线程且同一数据库连接内,如有写入操作,以后的读操作均从主库读取,用于保证数据一致性。
Spring命名空间
基于Hint的强制主库路由。

1.7.3 不支持范围

主库和从库的数据同步。
主库和从库的数据同步延迟导致的数据不一致。
主库双写或多写。

二、Sharding-JDBC实际操作

核心依赖:

		<dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>

2.1 配置分片算法前准备操作

在配置Sharding-JDBC分片算法之前,肯定都需要做的一些配置,配置数据源,数据节点,设置主键及生成算法这种基础的配置,有了这些配置之后,我们才能继续配置分片算法。

2.1.1 配置数据源

我这里设置了两个库,配置了两个数据源。
在这里插入图片描述

2.1.2 配置数据节点

$->是Sharding为我们提供的行表达式,这个表达式意思就是我们配置的数据节点为m0库course0表,m0库course1表,m1库course0表和m1库course1表,一共四个节点,这样的配置就很简便,我设置的库和表比较少,直接列举出来好像也行,但是如果分了很多库,很多表,逐个列举就会非常麻烦。
在这里插入图片描述

#数据节点
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{0..1}.course$->{0..1}

2.1.3 配置全局主键及生成策略

下面为course表设置的主键是cid,用了雪花算法保证全局主键唯一。
在这里插入图片描述

#设置主键
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
#主键生成策略,雪花算法
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE

2.2 精准分片算法实践

2.2.1 配置类

首先要设置分片键设置逻辑表名为course的分表策略,这里就需要我们自定义算法类了
分库策略类似,将table-strategy改为database-strategy,设置一个分库策略的自定义算法类
在这里插入图片描述

#分片键
spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=user_id
#分表策略-精准
spring.shardingsphere.sharding.tables.course.table-strategy.standard.precise-algorithm-class-name=com.mine.sharding.algorithm.MyPreciseTableShardingAlgorithm

2.2.2 自定义算法类

实现Sharding提供的精准分片接口,重写一下doSharding方法,接下来的几个分片算法,也都是差不多的操作。
在这里插入图片描述

public class MyPreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    //select * from course where cid = '' or cid in ('','')
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
        String logicTableName = preciseShardingValue.getLogicTableName();
        String columnName = preciseShardingValue.getColumnName();
        Long cidValue = preciseShardingValue.getValue();
        //实现course$->{cid%2}
        BigInteger shardingValueB = BigInteger.valueOf(cidValue);
        BigInteger resB = shardingValueB.mod(new BigInteger("2"));
        String key = logicTableName+resB;
        if (collection.contains(key)){
            return key;
        }
        throw new UnsupportedOperationException("route:"+key+" is not supported,please check your config");

    }
}

2.3 范围分片算法实践

2.3.1 配置类

在这里插入图片描述

#分片键
spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=user_id
#分表策略-范围
spring.shardingsphere.sharding.tables.course.table-strategy.standard.range-algorithm-class-name=com.mine.sharding.algorithm.MyRangeTableShardingAlgorithm

2.3.2 自定义算法类

在这里插入图片描述

public class MyRangeTableShardingAlgorithm implements RangeShardingAlgorithm<Long> {

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        Long upperValue = rangeShardingValue.getValueRange().upperEndpoint();
        Long lowerValue = rangeShardingValue.getValueRange().lowerEndpoint();

        String logicTableName = rangeShardingValue.getLogicTableName();
        //course_$->{cid%2}

        return Arrays.asList(logicTableName+"0",logicTableName+"1");
    }
}

2.4 复合分片算法实践

什么是复合,或者是复杂,不再是单一条件了,可以看到,配置类中的sharding-column加s了,不再是单数了
这种复合的分片策略,支持多个分片键,按多个分片键组合出复杂的分片策略

2.4.1 配置类

在这里插入图片描述

#分片键,可多个
spring.shardingsphere.sharding.tables.course.table-strategy.complex.sharding-columns=cid,user_id
#分表策略
spring.shardingsphere.sharding.tables.course.table-strategy.complex.algorithm-class-name=com.mine.sharding.algorithm.MyComplexTableShardingAlgorithm

2.4.2 自定义算法类

在这里插入图片描述

public class MyComplexTableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {

    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
        Range<Long> cidRange = complexKeysShardingValue.getColumnNameAndRangeValuesMap().get("cid");
        Collection<Long> userIdCol = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("user_id");

        Long cidUpper = cidRange.upperEndpoint();
        Long cidLower = cidRange.lowerEndpoint();

        List<String> result = new ArrayList<>();
        for (Long userId : userIdCol) {
            BigInteger userIdB = BigInteger.valueOf(userId);
            BigInteger target = userIdB.mod(new BigInteger("2"));
            result.add(complexKeysShardingValue.getLogicTableName()+target);
        }
        return result;
    }
}

2.5 Hint分片算法(强制路由)实践

2.5.1 配置类

配置文件中,没有指定分片键,为什么呢,大家可以看名字,强制路由,强制了,我也就没必要再预先设置一个分片键了,在程序中干预,指定SQL的目标数据库和表信息。

在这里插入图片描述

#Hint在配置中不指定分片键
#分表策略
spring.shardingsphere.sharding.tables.course.table-strategy.hint.algorithm-class-name=com.mine.sharding.algorithm.MyHintTableShardingAlgorithm

2.5.2 自定义算法类

在这里插入图片描述

public class MyHintTableShardingAlgorithm implements HintShardingAlgorithm<Integer> {

    /**
     * Hint限制:
     * 不支持union查询
     * 不支持多层子查询
     * 不支持函数计算
     */

    @Override
    public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Integer> hintShardingValue) {

        String key = hintShardingValue.getLogicTableName() + hintShardingValue.getValues().toArray()[0];
        if (collection.contains(key)) {
            return Arrays.asList(key);
        }
        throw new UnsupportedOperationException("route:" + key + " is not supported,please check your config");
    }
}

2.6.3 测试类

Hint算法如何在程序中干预呢,我们写一个简单的测试方法
在这里插入图片描述
我们可以看到,是通过HintManager来指定,很方便
但是也有一点需要注意的地方,这个是线程安全的,用完之后得关掉,不能带到一下个线程里面。
在这里插入图片描述

    /**
     * Hint
     * 强制路由
     */
    @Test
    public void queryCourseLHint() {
        HintManager hintManager = HintManager.getInstance();
        hintManager.addTableShardingValue("course", 0);
        List<Course> courses = courseMapper.selectList(null);
        courses.forEach(System.out::println);
        hintManager.close();

    }

2.6 广播表实践

在所有的数据源里面,做同样的操作,就是说每个数据源都会保存同样的,全量的数据

在这里插入图片描述

spring.shardingsphere.sharding.broadcast-tables=dict

2.7 绑定表实践

对分片键相同的表做关联查询,最主要就是要避免笛卡尔积

在这里插入图片描述

spring.shardingsphere.sharding.binding-tables[0]=user,dict

2.8 读写分离实践

前提,在数据库层面配置好主从库

6.8.1 配置主从库数据源

在这里插入图片描述


2.8.2 配置主从节点读写分离

当然,这里也需要指定主键及生成算法
在这里插入图片描述

#主从配置、读写分离
spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m
spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=s

spring.shardingsphere.sharding.tables.student.actual-data-nodes=ds0.student
spring.shardingsphere.sharding.tables.student.key-generator.column=sid
spring.shardingsphere.sharding.tables.student.key-generator.type=SNOWFLAKE


这次的内容到这里就结束了,作者水平有限,文章不足之处敬请指出

Best Regards

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

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

相关文章

【Ant Design】Form.Item创建自定义表单

一、概述 Antd是一个非常强大的UI组件库&#xff0c;里面的Form表单组件也基本能满足我们大多数场景。但是也有需要自定义表单的场景。 Vue2里我们使用v-model&#xff0c;结合子组件的model属性&#xff0c;来实现自定义组件的双向绑定。 Vue3里我们使用v-model&#xff0c;…

AGCTF 2023陇剑杯wp

SSW SmallSword_1 导出HTTP 对象的时候发现有sql 注入的语句&#xff0c;猜测攻击手法是 sql 注入 在这里发现了可疑的 php 文件 追踪 15340 发现可控参数&#xff0c;也就是连接密码 Flag&#xff1a;flag{0898e404bfabd0ebb702327b19f} SmallSword_2 知道攻击手法&…

Nacos整合Feign远程调用

Feign使用 Feign是一个声明式的http客户端&#xff0c;其作用就是帮助我们优雅的实现http请求的发送。 将Feign的Client抽取为独立模块&#xff0c;并且把接口有关的POJO、默认的Feign配置都放到这个模块中&#xff0c;提供给所有消费者使用。 例如&#xff0c;将UserClien…

vue小测试之拖拽、自定义事件

在开始之前我去复习了一下&#xff0c;clientX、clientY、pageX、pageY的区别&#xff0c;对于不熟悉offsetLeft和offsetTop的也可以在这里去复习一下。 vue拖拽指令之offsetX、clientX、pageX、screenX_wade3po的博客-CSDN博客_vue offset 客户区坐标位置&#xff08;clientX&…

虚拟工厂搭建,一键导入、即刻生产 | 大界 RoBIM CLOUD 云平台发布

大界在建筑、船舶、工程机械以及能源行业经过多年的场景实践&#xff0c;逐步形成了跨行业的 “算法数据流程” 的模型服务能力&#xff0c;并积累和沉淀为 RoBIM Cloud 平台产品。 RoBIM Cloud RoBIM Cloud 是一款云原生的智能机器人柔性生产平台&#xff0c;历时 3 年研发。大…

MavenCentral库发布记录

最近发布了 Android 路由库 URouter&#xff0c;支持 AGP8、ActivityResult启动等特性。 把提交到 Maven Central 过程记录一下。 一、注册 Sonatype 账号&#xff0c;新建项目 注册 https://​​issues.sonatype.org 登录后&#xff0c;新建项目&#xff1a; 相关选项&…

苹果macOS 14开发者预览版Beta 7发布 新增超过100款视频壁纸和屏保

8 月 31 日&#xff0c;苹果向 Mac 电脑用户推送了 macOS 14 开发者预览版 Beta 7 更新&#xff08;内部版本号&#xff1a;23A5337a&#xff09;&#xff0c;本次更新距离上次发布隔了 8 天。 苹果发布 Beta 7 更新的同时&#xff0c;还发布了第 6 个公测版&#xff0c;正式版…

Vue项目build打包编译后如何再修改后台请求地址

在public文件夹下新建config.js文件 在config.js中添加请求地址&#xff1a; window.myURL {baseURL: http://127.0.0.1:8080, }在index.html中引入创建的config.js <script src"./config.js" type"text/javascript"></script>在请求后台地…

访问学者申请需要具备哪些条件?

访问学者申请是一项重要的学术活动&#xff0c;要求申请者具备一定的条件和资格。知识人网小编提箱&#xff0c;申请访问学者通常需要满足以下条件&#xff1a; 1. 学术背景&#xff1a;申请者通常需要拥有博士学位或相当于博士学位的学术资格。他们的学术背景应该与他们希望进…

报错处理:Out of memory

报错环境&#xff1a; Linux 具体报错&#xff1a; Out of memory error&#xff0c;系统内存不足 排错思路&#xff1a; 当系统的内存资源被耗尽时&#xff0c;会出现 Out of memory 错误。这可能是由于应用程序占用了大量的内存&#xff0c;或者系统负载过高导致内存不足引起…

sap 一次性供应商 供应商账户组 临时供应商

sap中有一次性供应商这个名词&#xff0c;一次性供应商和非一次性供应商又有什么区别呢&#xff1f; 有如何区分一次性供应商和非一次性供应商呢&#xff1f; 1 区分一次性供应商和非一次性供应商的标志 在供应商的表LFA1中有个字段标示XCPDK&#xff08;一次性科目&#xff…

轻松打造高效Linux工作环境

引言 作为一名Linux持续学习者&#xff0c;我们经常会遇到繁琐的日常工作任务&#xff0c;例如查找某个文件、文件传输、调试等。如何便捷高效地完成这些任务是我们必须面对的问题。本文将为你提供一些实用的技巧和工具&#xff0c;帮助你轻松打造高效的Linux工作环境。 快速查…

IDEA 设置提示信息

IDEA 设置提示信息 File->Settings->Editor->Code Completion 取消勾选 Math case

联网智能实时监控静电离子风机的工作流程

联网智能实时监控静电离子风机是通过将静电离子风机与互联网连接&#xff0c;实现对其状态和性能的远程监控和管理。 具体实现该功能的方法可以包括以下几个步骤&#xff1a; 1. 传感器安装&#xff1a;在静电离子风机上安装适当的传感器&#xff0c;用于感知相关的参数&…

六、Kafka-Eagle监控

目录 6.1 MySQL 环境准备6.2 Kafka 环境准备6.3 Kafka-Eagle 安装 6.1 MySQL 环境准备 Kafka-Eagle 的安装依赖于 MySQL&#xff0c;MySQL 主要用来存储可视化展示的数据 6.2 Kafka 环境准备 修改/opt/module/kafka/bin/kafka-server-start.sh 命令 vim bin/kafka-server-sta…

运用全新空调插座秒变智能新体验

最近台风肆虐&#xff0c;城市内涝等灾害频频发生&#xff1b;气候离不开环境&#xff0c;环境也离不开气候&#xff0c;在这两者之间&#xff0c;人类却成了第三者。 随手关灯&#xff0c;节约用电&#xff0c;是一种再普通不过的行为&#xff0c;然而10亿人在同一时间做同样…

SAP接口调用方式总结

目录 一、RFC调用/JCO调用二、Restful调用三、Webservice调用四、直联接口五、PI接口&#xff1a;具体不做赘述&#xff0c;可以百度总结&#xff1a; 前言&#xff1a;跟外围系统对接&#xff0c;首要要确认好接口的调用方式&#xff0c;然后再根据相关的调用方式进行相应的操…

windows11安装msi文件的方法

文章导航: 问题介绍开启Windows Installer服务安装msi文件 问题介绍 因为msi后缀的文件属于软件安装文件, 一般情况我们直接双击或者打开就可进行相应的安装操作. 但是对于新电脑, 自己刚买来, 而且不知道这种文件该如何打开的情况, 我们进行了这篇文件的介绍~ 希望能够帮助…

C#,《小白学程序》第十二课:日历的编制,时间DateTime的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十二课&#xff1a;日历的编制&#xff0c;时间DateTime的计算方法与代码 /// 本课学习时间类型的数据 DateTime 的简单方法&#xff0c;并编制一个月的日历。 /// </summary> /// <param name"sender"…

通义千问部署搭建

文章目录 一、部署11.1 打开通义千问-7B-预训练-模型库-选择资源1.2 使用Netbook2.1 运行2.2 复制脚本2.2.1 问题1 &#xff1a;ImportError: This modeling file requires the following packages that were not found in your environment: transformers_stream_generator. R…