芝法酱学习笔记(2.3)——shardingsphere分库分表
一、前言
之前的例子中,我们以一个简化了的销售单报表查询,展示了大数据量查询时,在索引和变量类型层面可以做的一些优化。可我们发现,无论怎么优化,一次查询都要好几秒。
这是一个现实问题,只要一个系统用户的业务足够多,运行时间足够长,数据库的单张表中就会存在海量的数据。数据量大到一定程度,无论怎么做性能都会下降。那是否有解决方法呢?
最容易想到的,就是分库分表了。其实在这个业务中,第一章已经给出了一个分库的方案,把不同用户放在不同的库中。然而单个用户的数据也可能较大,这时就需要分表了。
本节,就介绍市面上最主流的分库分表方案,shardingsphere。
二、代码展示
由于本节原理部分讲的很少,多数仅仅介绍shardingsphere如何使用。而该框架学习的难点仅仅在如何配置,理论部分涉及很少,故这次在开始位置,直接给出代码展示,大家可以看着代码,再看我后面的介绍。
三、shardingsphere配置
3.1 版本
本节使用的shardingsphere版本引用如下:
<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc</artifactId><version>5.5.1</version></dependency>
3.2 yml配置
shardingsphere有一个复杂的yml配置,我们先看官方文档的介绍。
其实,看着官方文档还是很复杂,而且配置时总觉得心慌,我们可以看着源码做配置。由于我们本次也牵扯监控中心和企业中心,监控中心是不分表的,所以用SpringBoot的默认数据源即可。所以本次数据要我们手动配置。创建shardingsphere数据源的核心代码为:
@Bean(name = "shardingSphereDataSource")public DataSource shardingSphereDataSource() throws SQLException, IOException {File file = new File(getClass().getClassLoader().getResource("shardingsphere.yml").getFile());DataSource dataSource = YamlShardingSphereDataSourceFactory.createDataSource(file);return dataSource;}
我们点进去这个YamlShardingSphereDataSourceFactory,可以看到配置类核心是这个结构体:
@Getter
@Setter
public final class YamlJDBCConfiguration implements YamlConfiguration {private String databaseName;private Map<String, Map<String, Object>> dataSources = new HashMap<>();private Collection<YamlRuleConfiguration> rules = new LinkedList<>();private YamlModeConfiguration mode;private YamlAuthorityRuleConfiguration authority;private YamlSQLParserRuleConfiguration sqlParser;private YamlTransactionRuleConfiguration transaction;private YamlGlobalClockRuleConfiguration globalClock;private YamlSQLFederationRuleConfiguration sqlFederation;private YamlSQLTranslatorRuleConfiguration sqlTranslator;private YamlLoggingRuleConfiguration logging;private Properties props = new Properties();......}
这里面的变量名,则是我们yml第一层的配置。我们本节只讲本例中用到的配置,其他细节大家可以看着官网仔细学习。
变量 | 名称 | 作用 |
---|---|---|
databaseName | 数据源名 | 配置数据源的名称,如果不是自动配置的,这个其实没啥用 |
dataSources | 数据源 | 在该节点下,配置多个数据源 |
mode | 模式 | 是单机模式还是集群模式,本例子配单机Standalone,还有配连接类型,本例配JDBC |
rule | 规则 | 该段配置是重中之重,配置分库分表的规则。该配置是一个数组,每种类型规则可以配一个 |
props | 变量 | 一些sharding框架用的变量,本例中用于开启log信息 |
3.3 规则配置
我们对YamlRuleConfiguration这个类ctrl + H,可以看到每种规则的类,这样可以确定我们每种规则具体该怎么配置。
shardingsphere的规则配置中,数组元素对应哪个类,使用shardingsphere的一个特有的注释,如数据分片的配置是:- !SHARDING
我们可以在官方文档中,查看每种规则配置的注释,这里给出本例用到的配置
类型类名 | 类型 | 注释 | 作用 |
---|---|---|---|
YamlShardingRuleConfiguration | 分片规则 | - !SHARDING | 用于描述如何分库分表 |
YamlSingleRuleConfiguration | 单表规则 | - !SINGLE | 用于扫描库中有哪些表,可以配置通配 |
YamlBroadcastRuleConfiguration | 广播表规则 | - !BROADCAST | 用于描述哪些表会被用作连表,并且该表是没做分表的 |
3.3.1 分片规则
分片规则怎么配,我们可以结合官网文档和源码来看
官网文档:
rules:
- !SHARDINGtables: # 数据分片规则配置<logic_table_name> (+): # 逻辑表名称actualDataNodes (?): # 由数据源名 + 表名组成(参考 Inline 语法规则)databaseStrategy (?): # 分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一standard: # 用于单分片键的标准分片场景shardingColumn: # 分片列名称shardingAlgorithmName: # 分片算法名称complex: # 用于多分片键的复合分片场景shardingColumns: # 分片列名称,多个列以逗号分隔shardingAlgorithmName: # 分片算法名称hint: # Hint 分片策略shardingAlgorithmName: # 分片算法名称none: # 不分片tableStrategy: # 分表策略,同分库策略keyGenerateStrategy: # 分布式序列策略column: # 自增列名称,缺省表示不使用自增主键生成器keyGeneratorName: # 分布式序列算法名称auditStrategy: # 分片审计策略auditorNames: # 分片审计算法名称- <auditor_name>- <auditor_name>allowHintDisable: true # 是否禁用分片审计hintautoTables: # 自动分片表规则配置t_order_auto: # 逻辑表名称actualDataSources (?): # 数据源名称shardingStrategy: # 切分策略standard: # 用于单分片键的标准分片场景shardingColumn: # 分片列名称shardingAlgorithmName: # 自动分片算法名称bindingTables (+): # 绑定表规则列表- <logic_table_name_1, logic_table_name_2, ...> - <logic_table_name_1, logic_table_name_2, ...> defaultDatabaseStrategy: # 默认数据库分片策略defaultTableStrategy: # 默认表分片策略defaultKeyGenerateStrategy: # 默认的分布式序列策略defaultShardingColumn: # 默认分片列名称# 分片算法配置shardingAlgorithms:<sharding_algorithm_name> (+): # 分片算法名称type: # 分片算法类型props: # 分片算法属性配置# ...# 分布式序列算法配置keyGenerators:<key_generate_algorithm_name> (+): # 分布式序列算法名称type: # 分布式序列算法类型props: # 分布式序列算法属性配置# ...# 分片审计算法配置auditors:<sharding_audit_algorithm_name> (+): # 分片审计算法名称type: # 分片审计算法类型props: # 分片审计算法属性配置# ...- !BROADCASTtables: # 广播表规则列表- <table_name>- <table_name>
源码:
@RepositoryTupleEntity("sharding")
@Getter
@Setter
public final class YamlShardingRuleConfiguration implements YamlRuleConfiguration {@RepositoryTupleField(type = Type.TABLE)private Map<String, YamlTableRuleConfiguration> tables = new LinkedHashMap<>();@RepositoryTupleField(type = Type.TABLE)private Map<String, YamlShardingAutoTableRuleConfiguration> autoTables = new LinkedHashMap<>();@RepositoryTupleField(type = Type.TABLE)@RepositoryTupleKeyListNameGenerator(ShardingBindingTableRepositoryTupleKeyListNameGenerator.class)private Collection<String> bindingTables = new LinkedList<>();@RepositoryTupleField(type = Type.DEFAULT_STRATEGY)private YamlShardingStrategyConfiguration defaultDatabaseStrategy;@RepositoryTupleField(type = Type.DEFAULT_STRATEGY)private YamlShardingStrategyConfiguration defaultTableStrategy;@RepositoryTupleField(type = Type.DEFAULT_STRATEGY)private YamlKeyGenerateStrategyConfiguration defaultKeyGenerateStrategy;@RepositoryTupleField(type = Type.DEFAULT_STRATEGY)private YamlShardingAuditStrategyConfiguration defaultAuditStrategy;@RepositoryTupleField(type = Type.ALGORITHM)private Map<String, YamlAlgorithmConfiguration> shardingAlgorithms = new LinkedHashMap<>();@RepositoryTupleField(type = Type.ALGORITHM)private Map<String, YamlAlgorithmConfiguration> keyGenerators = new LinkedHashMap<>();@RepositoryTupleField(type = Type.ALGORITHM)private Map<String, YamlAlgorithmConfiguration> auditors = new LinkedHashMap<>();@RepositoryTupleField(type = Type.OTHER)private String defaultShardingColumn;@RepositoryTupleField(type = Type.OTHER)private YamlShardingCacheConfiguration shardingCache;@Overridepublic Class<ShardingRuleConfiguration> getRuleConfigurationType() {return ShardingRuleConfiguration.class;}
}
这里文档基本写的很清楚了,大家看着文档配就行了。
这里主要讲解一下actualDataNodes的表达式
我们需要告诉shardingsphere,一个逻辑表可能出现的实际表有哪些,以便在连表查询时,shardingsphere帮我们做关联。自定义分表算法的回调中,也能获取到这些值(虽然可能用不到)。
以本例中的配置为例:
consign:#logicTable: consignactualDataNodes: ds${0..1}.consign_${2022..2024}${1..4},ds${0..1}.consign_0tableStrategy:standard:shardingAlgorithmName: year-month-shardingshardingColumn: bill_time_key
可以使用${}的形式,展示可能出现哪些情况。由于shardingsphere的设计问题,这里必须是数字,后面会讲解为什么。多种不同的可能,可以用","分割。
注意,要实现分库分表时的join操作正常,要把可能join的组合配置到bindingTables中,不然两个分表了的表join,该出现笛卡尔积了。
3.3.2 单表规则
这个配置必须配,不然只能查询到分片配置中已经配的逻辑表,会非常难绷。报错信息如下:
Cause: org.apache.shardingsphere.infra.exception.kernel.metadata.TableNotFoundException: Table or view 'item' does not exist.
该配置,可以用通配符,如:
- !SINGLEtables:# 加载全部单表- "ds0.*"
3.3.3 广播表配置
如果连表时,分表了的表和没分表的表做连表,如本例中的consign连item,并且没有配置分库的列时,就会报如下错误:
### Cause: java.sql.SQLException: Unknown exception.
More details: java.lang.NullPointerException: Cannot invoke "String.equalsIgnoreCase(String)" because "shardingColumn" is null
; uncategorized SQLException; SQL state [HY000]; error code [30000]; Unknown exception.
此时,把item配进去即可
- !BROADCASTtables: # 广播表规则列表- item
3.4 本例完整的配置
mode:type: Standalonerepository:type: JDBC
databaseName: mysql
dataSources:ds0:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.0.64:3306/study2024-class009-busy001?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: dbMgrpassword: qqhilvMgAl@7ds1:dataSourceClassName: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.0.64:3306/study2024-class009-busy002?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: dbMgrpassword: qqhilvMgAl@7
rules:- !SHARDINGdefaultDatabaseStrategy:standard:shardingAlgorithmName: enterprise-shardingshardingColumn: enp_iddefaultTableStrategy:none:shardingAlgorithms:year-month-sharding:type: CUSTOM_YEAR_MONTHenterprise-sharding:type: ENTERPRISE-SHARDINGtables:consign:#logicTable: consignactualDataNodes: ds${0..1}.consign_${2022..2024}${1..4},ds${0..1}.consign_0tableStrategy:standard:shardingAlgorithmName: year-month-shardingshardingColumn: bill_time_keyconsign_header:#logicTable: consign_headeractualDataNodes: ds${0..1}.consign_header_${2022..2024}${1..4},ds${0..1}.consign_header_0tableStrategy:standard:shardingAlgorithmName: year-month-shardingshardingColumn: bill_time_keybindingTables:- consign_header,consign- !SINGLEtables:# 加载全部单表- "ds0.*"- !BROADCASTtables: # 广播表规则列表- item
props:sql-show: true
四、自定义分片算法
在实际开发中,我们通常不会使用系统自带的算法。我们都会做一个自己的分片规则。
4.1 算法编写
在本例中,我们写了两个分片算法,一个是表的分片,根据年份和季度。另一个是数据库的分片,根据jwt中的库信息,告诉系统去哪个库中查询。这里我们先展示代码,再进行讲解。
4.1.1 YearMonthTableShardingAlgorithm
public class YearMonthTableShardingAlgorithm implements StandardShardingAlgorithm<Long> {@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {String tableName = shardingValue.getLogicTableName();Long billTimeSecond = shardingValue.getValue();LocalDateTime localDateTime = CommonUtil.parseFromSecond(billTimeSecond);int year = localDateTime.getYear();int monVal = localDateTime.getMonthValue();int season = (monVal+2)/3;if(year < 2022){return tableName+"_0";}else{return tableName+"_"+year+season;}}@Overridepublic Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {List<String> rtn = new ArrayList<String>();String tableName = rangeShardingValue.getLogicTableName();Long begTimeL = rangeShardingValue.getValueRange().lowerEndpoint();Long endTimeL = rangeShardingValue.getValueRange().upperEndpoint();LocalDateTime beginTime = CommonUtil.parseFromSecond(begTimeL);LocalDateTime endTime = CommonUtil.parseFromSecond(endTimeL);int yearBeg = beginTime.getYear();int yearEnd = endTime.getYear();int monBeg = beginTime.getMonthValue();int monEnd = endTime.getMonthValue();int seasonBeg = (monBeg+2)/3;int seasonEnd = (monEnd+2)/3;if(yearBeg < 2022){rtn.add(tableName+"_0");seasonBeg = 1;yearBeg = 2022;}for(int i = yearBeg; i <= yearEnd; i++){int curSeasonBeg = i > yearBeg ? 1: seasonBeg;int curSeasonEnd = i < yearEnd ? 4 : seasonEnd;for(int j = curSeasonBeg; j <= curSeasonEnd; j++){rtn.add(tableName+"_"+i+""+j);}}return rtn;}@Overridepublic String getType() {return "CUSTOM_YEAR_MONTH"; // 自定义算法类型名称}}
4.1.2 YearMonthTableShardingAlgorithm
@Slf4j
public class EnterpriseShardingAlgorithm implements StandardShardingAlgorithm<Long> {@Overridepublic String getType() {return "ENTERPRISE-SHARDING"; // 自定义算法类型名称}@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {ITokenUtil tokenUtil = SpringUtil.getBean(ITokenUtil.class);String prompt = DatasourceSetUtil.getDbPrompt();if(StringUtils.hasText(prompt)){return prompt;}if(tokenUtil.hasTokenObject()){AuthObject authObject = tokenUtil.getAuthObject();return authObject.getDbCode();}return "ds0";}@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {String prompt = DatasourceSetUtil.getDbPrompt();if(StringUtils.hasText(prompt)){return List.of(prompt);}ITokenUtil tokenUtil = SpringUtil.getBean(ITokenUtil.class);if(tokenUtil.hasTokenObject()){AuthObject authObject = tokenUtil.getAuthObject();return List.of(authObject.getDbCode());}return List.of("ds0");}
}
4.1.3 讲解
这里,我们继承了StandardShardingAlgorithm,其实还可以继承ComplexKeysShardingAlgorithm或HintShardingAlgorithm,具体用法大家可以参见官方文档。我们这里仅详细讲下StandardShardingAlgorithm。
第一个回调,doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) ,该回调用于处理equal时的分片。而doSharding(Collection collection, RangeShardingValue rangeShardingValue),用于处理范围查询时的分片。
getType回调,用于标识算法的名字,用于和配置关联。
4.2 meta-info的配置
仅仅写了算法,系统还不能识别,需要在Resource下的META-INFO.service中,配置都有哪些类是算法。
indi.zhifa.study2024.common.auth.sharding.YearMonthTableShardingAlgorithm
indi.zhifa.study2024.common.auth.sharding.EnterpriseShardingAlgorithm
五、数据源配置
如果手动配置数据源,并且结合mp使用,还是要在配置SqlSessionFactory时,像之前讲的一样,参考mp的自动配置,做一系列的操作。这里就不在帖子中展示那些冗余代码了,大家去参考代码中看。这里仅展示核心内容:
@Bean(name = "shardingSphereDataSource")public DataSource shardingSphereDataSource() throws SQLException, IOException {File file = new File(getClass().getClassLoader().getResource("shardingsphere.yml").getFile());DataSource dataSource = YamlShardingSphereDataSourceFactory.createDataSource(file);return dataSource;}@Bean(name = "shardingSqlSessionFactory")public SqlSessionFactory shardingSqlSessionFactory(@Qualifier("shardingSphereDataSource") DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();factory.setDataSource(dataSource);enableMpSqlSessionFactory(factory);return factory.getObject();}@Primary@Bean(name = "shardingTransactionManager")public PlatformTransactionManager shardingTransactionManager(@Qualifier("shardingSphereDataSource") DataSource monitorDataSource) {return new DataSourceTransactionManager(monitorDataSource);}
六、遇到的坑
shardingsphere分表时有个坑,表名必须为 逻辑名+_+数字
如consign_20221,千万不能写成consign_2022_1,不然在bindingTables的配置的检测过程时,会出错。
代码在文件
org.apache.shardingsphere.sharding.rule.checker.ShardingRuleChecker
private boolean isValidActualTableName(final ShardingTable sampleShardingTable, final ShardingTable shardingTable) {for (String each : sampleShardingTable.getActualDataSourceNames()) {Collection<String> sampleActualTableNames = sampleShardingTable.getActualTableNames(each).stream().map(actualTableName -> actualTableName.replace(sampleShardingTable.getTableDataNode().getPrefix(), "")).collect(Collectors.toSet());Collection<String> actualTableNames =shardingTable.getActualTableNames(each).stream().map(optional -> optional.replace(shardingTable.getTableDataNode().getPrefix(), "")).collect(Collectors.toSet());if (!sampleActualTableNames.equals(actualTableNames)) {return false;}}return true;}
我认为这个设定十分不合理,但也没办法,先做记录。
相关文章:
芝法酱学习笔记(2.3)——shardingsphere分库分表
一、前言 之前的例子中,我们以一个简化了的销售单报表查询,展示了大数据量查询时,在索引和变量类型层面可以做的一些优化。可我们发现,无论怎么优化,一次查询都要好几秒。 这是一个现实问题,只要一个系统用…...

vue3+vite+nginx打包
在开发环境下,已经可以正常地运行一个有增删改查功能的页面了,但如何把它发布到运行服务器呢?仍有许多的问题需要探索。 网上很多文章给了很大的帮助,但总是没有说明原理,对于像我这样的初学者来说,不知其…...

爬虫与反爬虫实现全流程
我选取的网页爬取的是ppt nba版 需要的工具:pycharm,浏览器 爬虫需要观察它的网页信息,然后开始首先爬取它的html,可以看到有人气,标题,日期,咨询 可以看到用get方法 import requests url"https://img-home.csdnimg.cn/images/20230724024159.png?origin_urlhttps%3A%2…...

Kimi进行学术方向选择精讲!
目录 1.文献搜索 2.辅助选题 3.选题判断 在我们之前的文章中,小编都强调了选题在文章价值中的核心作用。一篇优秀的文章背后,肯定有一个精心挑选的选题。选题的好坏直接影响着文章能够发表的期刊等级。许多宝子们却采取了相反的做法,将大量…...

湖北产教融合教育研究院重庆分院揭牌成立
百年大计,教育为本。为积极响应重庆市人才培养的迫切需求,充分发挥中国同等学力申硕综合服务领航者的专业优势,12月26日,湖北产教融合教育研究院重庆分院启动仪式在渝北区龙山一路278号祈年悦城4栋24层隆重举行。 湖北产教融合教育…...
探索CSS Houdini:下一代样式与动画技术
随着前端开发对用户体验的要求不断提高,传统的CSS在某些场景下难以满足开发者的高阶需求。在这种背景下,CSS Houdini 技术应运而生,为开发者提供了更高自由度和更强大的功能,开创了现代Web动画与样式的新可能。 什么是CSS Houdin…...

winserver搭建域环境
域环境的搭建 7.1理论知识 Windows Server 2008网络类型 工作组(Work Group) 在安装Windows系统的时候 ,工作组名一般为“workgroup”,也可以任意起个名字,在同一工作组或不同工作组在访问时也没有什么分别,在使用时&a…...

鸿蒙开发工程师成长的五个阶段
在科技日新月异的今天,鸿蒙(HarmonyOS)作为华为自主研发的操作系统,正以其独特的魅力和广阔的应用前景吸引着越来越多的开发者加入。鸿蒙不仅承载着华为对未来智能设备互联互通的愿景,也为开发者提供了一个充满挑战与机…...

Redis集成到SpingBoot 的数据结构常见操作
一.环境配置 1.依赖注入 2.yaml文件配置 3.启动本地Redis服务 (或在虚拟机上启动,这里为了方便演示在本地启动) 4.启动成功案例 5.创建一个Controller我们开始演示 RestController public class MyController {Autowiredprivate StringRedisTemplate redisTemplate;} 二 …...
输入输出(I/O):熟悉 Java 的 I/O 类库,尤其是 NIO 和文件操作
输入输出(I/O):熟悉 Java 的 I/O 类库,尤其是 NIO 和文件操作 在 Java 中,I/O(输入输出)操作是开发中非常重要的一部分,用于与文件、网络和其他数据流交互。Java 提供了传统的 I/O&…...

mysql建立主从集群
mysql建立主从集群需要多个mysql服务器,主从数据库是通过log日志来进行同步的,所以需开启log-bin。本地安装多个mysql参考底部 主数据库配置 打开主数据库my.ini配置文件,给其配置server_id1 [mysqld] port3306 basedirD:/phpstudy_pro/1/…...

Python AI 教程之四:无监督学习
什么是无监督学习? 无监督学习是机器学习的一个分支,用于处理未标记的数据。与监督学习(其中数据被标记为特定类别或结果)不同,无监督学习算法的任务是在不了解数据含义的情况下寻找数据中的模式和关系。这使得无监督学习成为探索性数据分析的强大工具,其目标是了解数据…...

ReactiveStreams、Reactor、SpringWebFlux
注意: 本文内容于 2024-12-28 21:22:12 创建,可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容,请访问原文地址:ReactiveStreams、Reactor、SpringWebFlux。感谢您的关注与支持! ReactiveStreams是…...
Qt 的信号槽机制详解:之信号槽引发的 Segmentation Fault 问题拆析(下)
Qt 的信号槽机制详解:之信号槽引发的 Segmentation Fault 问题拆析(下) 前言一. 信号槽的误用导致崩溃的常见原因1.信号和槽连接的对象被提前释放案例解决方法 2.参数类型不匹配案例解决方法 3. 多线程信号槽使用不当案例解决方法 4. 信号重复…...
opencv(cpp) Mat使用总结
opencv访问矩阵的通道数 #include <opencv2/opencv.hpp> #include <iostream>int main() {// 创建一个3通道的彩色图像(例如,BGR格式)cv::Mat colorImage cv::Mat::zeros(100, 100, CV_8UC3);// 创建一个单通道的灰度图像cv::M…...

【Hackthebox 中英 Write-Up】Web Request | 分析 HTTP 请求和响应
欢迎来到我的writeup分享!我希望大家不要只关注结果或答案,而是通过耐心阅读,尝试逆向工程理解背后的运作原理。在这里,你不仅能找到解题的思路,还能学到更多与Hack The Box等平台相关的技术和技巧,期待与你…...
c#多线程之生产者-消费者模型
在 C# 中实现 生产者-消费者模式,通常需要多个线程来处理数据的生产和消费。我们可以使用 Queue<T> 来作为存储数据的队列,并使用 Thread、Mutex 或 Monitor 来确保线程安全。BlockingCollection<T> 是 C# 提供的一个线程安全的集合…...
Spring Boot中幂等性的应用
在 Spring Boot 中,幂等性是实现分布式系统设计和接口调用的一个重要概念,尤其在高并发、分布式环境下,确保接口重复调用不会引发系统数据异常至关重要。 幂等性概念 幂等性(Idempotence)是指一次请求和重复多次请求…...
【机器学习】分类
文章目录 1. 能否用回归解决分类问题2. 生成模型(概率生成)3. 判别模型(逻辑回归)4. 多分类问题 1. 能否用回归解决分类问题 二元分类 数据分布不规律,回归函数会尽量减少误差,导致不合理的偏移离分界较远…...

5.若依的角色权限控制
RBAC 基于角色的访问控制,通过角色来分配和管理用户的菜单权限。 修改课程管理的菜单到主类目下 新建角色并分配菜单 新建用户并分配角色 添加一个根菜单,父级为主类目...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...