Spring Boot ShardingJDBC分库分表(草稿)
ShardingJDBC分库分表
1.Maven 引用
<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
2.数据库和表格
数据库
*****_ch
*****_hk
*****_us
*****_olap表格
kline
kline_D_0
kline_D_1
.......
kline_D_15kline
kline_M_0
kline_M_1
.......
kline_M_15kline_m1
kline_m1_250121
.......
kline_m1_2501221kline_M5_0
.......
kline_M5_15kline_M30_0
.......
kline_M30_15kline_M60_0
.......
kline_M60_15kline_W_0
.......
kline_W_15kline_Y_0
.......
kline_Y_15trade_record_240101trade_record_250213_0
........
trade_record_250221_249
CREATE DEFINER=`admin`@`%` PROCEDURE `CreateKlineTables`()
BEGINDECLARE i INT DEFAULT 0;DECLARE j INT DEFAULT 0;DECLARE table_name VARCHAR(64);DECLARE date_parts TEXT;DECLARE date_part VARCHAR(10);-- 定义时间周期数组SET date_parts = 'M5,M30,M60,D,W,M,Y';-- 循环遍历时间周期WHILE j < LENGTH(date_parts) - LENGTH(REPLACE(date_parts, ',', '')) + 1 DOSET date_part = SUBSTRING_INDEX(SUBSTRING_INDEX(date_parts, ',', j + 1), ',', -1);-- 循环创建表SET i = 0;WHILE i < 16 DOSET table_name = CONCAT('kline_', date_part, '_', i);SET @sql = CONCAT('CREATE TABLE IF NOT EXISTS ', table_name, ' LIKE kline');PREPARE stmt FROM @sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;SET i = i + 1;END WHILE;SET j = j + 1;END WHILE;
END
CREATE DEFINER=`admin`@`%` PROCEDURE `CreateTradeRecordTables`(IN date_part VARCHAR(10))
BEGINDECLARE i INT DEFAULT 0;DECLARE table_name VARCHAR(64);-- 循环创建表WHILE i < 250 DOSET table_name = CONCAT('trade_record_', date_part, '_', i);SET @sql = CONCAT('CREATE TABLE IF NOT EXISTS ', table_name, ' like trade_record_240101');PREPARE stmt FROM @sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;SET i = i + 1;END WHILE;
END
CREATE DEFINER=`admin`@`%` PROCEDURE `DropTradeRecordTables`(IN date_part VARCHAR(10))
BEGINDECLARE i INT DEFAULT 0;DECLARE table_name VARCHAR(64);-- 循环删除表WHILE i < 250 DOSET table_name = CONCAT('trade_record_', date_part, '_', i);SET @sql = CONCAT('DROP TABLE IF EXISTS ', table_name);PREPARE stmt FROM @sql;EXECUTE stmt;DEALLOCATE PREPARE stmt;SET i = i + 1;END WHILE;
END
2.application.yaml配置
- 配置文件
spring:port: 8888tomcat:uri-encoding: UTF-8max-http-post-size: 20MBmax-http-header-size: 20MBhttp:encoding:force: truecharset: UTF-8enabled: trueaop:auto: truemain:allow-bean-definition-overriding: truejpa:database-platform: org.hibernate.dialect.MySQL5InnoDBDialectshow-sql: falsehibernate:ddl-auto: nonedsx:olap:type: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: username: password: hikari:maximum-pool-size: 20minimum-idle: 20shardingsphere:datasource:names: center, ds0, ds1, ds2center:type: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: username: password: hikari:maximum-pool-size: 20minimum-idle: 20ds0:type: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: username: password: hikari:maximum-pool-size: 20minimum-idle: 20ds1:type: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: username: password: hikari:maximum-pool-size: 20minimum-idle: 20ds2:type: com.zaxxer.hikari.HikariDataSourcedriverClassName: com.mysql.cj.jdbc.DriverjdbcUrl: username: password: hikari:maximum-pool-size: 20minimum-idle: 20props:sql:show: falsesharding:default-data-source-name: centertables:trade_record:actual-data-nodes: ds$->{0..2}.trade_record_$->{0..10}database-strategy: standard: sharding-column: market_codeprecise-algorithm-class-name: com.zzc.sharding.DbShardingByMarketTypeAlgorithmtable-strategy:complex:sharding-columns: trade_date,symbol_idalgorithm-class-name: com.zzc.sharding.TableShardingByDateAndSymbolAlgorithmkline_m1:actual-data-nodes: ds$->{0..2}.kline_m1# actual-data-nodes: ds$->{0..1}database-strategy:standard:sharding-column: market_codeprecise-algorithm-class-name: com.zzc.sharding.DbShardingByMarketTypeAlgorithmtable-strategy:complex:sharding-columns: trade_datealgorithm-class-name: com.zzc.sharding.TableShardingByDateAlgkline:actual-data-nodes: ds$->{0..2}.kline_${['M5', 'M30','M60','D','W','M','Y']}_${0..15}# actual-data-nodes: ds$->{0..1}database-strategy:standard:sharding-column: market_codeprecise-algorithm-class-name: com.zzc.sharding.DbShardingByMarketTypeAlgorithmtable-strategy:complex:sharding-columns: kline_type,symbol_idalgorithm-class-name: com.zzc.sharding.TableShardingByKlineTypeAndSymbolIdAlg
- 创建路由规则 DbShardingByMarketTypeAlgorithm
package com.zzc.sharding;import java.util.Collection;@Slf4j
public class DbShardingByMarketTypeAlgorithm implements PreciseShardingAlgorithm<String> {private DatabaseShardingConfig config;@Overridepublic String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {// 从 sql 中获取 marketTypeString marketType = preciseShardingValue.getValue();if (config == null) {config = SpringContextUtil.getBean(DatabaseShardingConfig.class);}// 依据 marketType 获取配置的数据库名String dbName = config.getDbName(marketType);if (!collection.contains(dbName)) {log.error("Database sharding error. column-value : [{}], DatabaseShardingConfig dbName : [{}], shardingsphere configs : [{}]", marketType, dbName, collection);throw new IllegalArgumentException("Database sharding error.");}return dbName;}
}
- TableShardingByDateAndSymbolAlgorithm
package com.zzc.sharding;@Slf4j
public class TableShardingByDateAndSymbolAlgorithm implements ComplexKeysShardingAlgorithm {private static final String FIELD_NAME_DATE = "trade_date";private static final String FIELD_NAME_SYMBOL = "symbol_id";private DatabaseShardingConfig config;@Overridepublic Collection<String> doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {if (config == null) {config = SpringContextUtil.getBean(DatabaseShardingConfig.class);}// 从 sql 中获取成交日期 data 字段String date = ((List<String>) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(FIELD_NAME_DATE)).get(0);// 从 sql 中获取成交日期 symbol_id 字段Long symbolId = ((List<Long>) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get(FIELD_NAME_SYMBOL)).get(0);// 以逻辑表名 x + "241118_1" 类似字符串为实际表名,返回最终的表名String logicTable = complexKeysShardingValue.getLogicTableName();DatabaseShardingConfig.TableShardingConfig shardingConfig = config.getTableShardingConfig(logicTable);return Collections.singletonList(logicTable + "_" + date.substring(2).replaceAll("-", "") + "_" + symbolId % shardingConfig.getTableShardingNum());}
}
- TableShardingByDateAlg
package com.zzc.sharding;@Slf4j
public class TableShardingByDateAlg implements ComplexKeysShardingAlgorithm {@Overridepublic Collection<String> doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {// 从 sql 中获取成交日期 trade_date 字段String date = ((List<String>) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("trade_date")).get(0);// 以逻辑表名 x + "_241118" 类似字符串为实际表名,返回最终的表名String logicTable = complexKeysShardingValue.getLogicTableName();return Collections.singletonList(logicTable+ "_" + date.substring(2).replaceAll("-", ""));}
}
- TableShardingByKlineTypeAndSymbolIdAlg
package com.zzc.sharding;@Slf4j
public class TableShardingByKlineTypeAndSymbolIdAlg implements ComplexKeysShardingAlgorithm {private DatabaseShardingConfig config;@Overridepublic Collection<String> doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {if (config == null) {config = SpringContextUtil.getBean(DatabaseShardingConfig.class);}String klineType = ((List<String>) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("kline_type")).get(0);Long symbolId = ((List<Long>) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("symbol_id")).get(0);String logicTable = complexKeysShardingValue.getLogicTableName();DatabaseShardingConfig.TableShardingConfig shardingConfig = config.getTableShardingConfig(logicTable);log.warn("symbolId:{}",symbolId);log.warn("klineType:{}",klineType);log.warn("shardingConfig:{}",shardingConfig);return Collections.singletonList(logicTable+ "_" + klineType + "_" + symbolId % shardingConfig.getTableShardingNum());}
}
- 定时任务创建表格
package com.zzc.service.schedule;@Slf4j
@Component
@RequiredArgsConstructor
public class QuotationDataManagementJob {/** 获取锁等待时间 */private final static int LOCK_WAIT_SECONDS = 10;/** 获取锁后的锁的自动释放时间 */private final static int LOCK_LEASE_SECONDS = 30 * 60;/** 创建分表语句(使用模版表创建实际表) */private final static String SHARDING_TABLE_CREATE_SQL = "CREATE TABLE IF NOT EXISTS %s LIKE %s;";/** 删除分表语句(数据清理,防止 mysql 磁盘占用过大) */private final static String SHARDING_TABLE_CLEAR_SQL = "DROP TABLE IF EXISTS %s;";private final static String DS_SHARDING = "shardingDataSource";private final static String DS_OLAP = "olapDataSource";private final DatabaseShardingConfig dbShardingConfig;private final RedissonClient redissonClient;private final DataSource shardingDataSource;private final DataSource olapDataSource;/*** 每周五下午12点30分生成下一周的行情表*/@Scheduled(cron = "0 30 12 ? * FRI")public void createShardingTableJob() {RLock lock = redissonClient.getLock(LOCK_CREATE_SHARDING_TABLE);RedisLockUtils.lockExecute(lock, LOCK_WAIT_SECONDS, LOCK_LEASE_SECONDS, TimeUnit.SECONDS, () -> {dbShardingConfig.getTables().forEach((tableName, config) -> {if(config.getRunCreateJob())createShardingTable(tableName, config);});return null;});log.info("createShardingTable job done");}/*** 每天10点清理数据*/@Scheduled(cron = "0 0 10 * * ?")public void clearShardingTableJob() {RLock lock = redissonClient.getLock(LOCK_CLEAR_SHARDING_TABLE);RedisLockUtils.lockExecute(lock, LOCK_WAIT_SECONDS, LOCK_LEASE_SECONDS, TimeUnit.SECONDS, () -> {dbShardingConfig.getTables().forEach((tableName, config) -> {clearShardingTable(tableName, config);});return null;});log.info("clearShardingTable job done");}private void createShardingTable(String tableName, DatabaseShardingConfig.TableShardingConfig config) {if (DS_OLAP.equals(config.getDs())) {try {Connection connection = olapDataSource.getConnection();List<String> nextWeekWorkDays = getNextWeekWorkDays();nextWeekWorkDays.forEach(day -> {createShardingTable("olap", connection, tableName, day, config);});} catch (Throwable t) {log.error("createShardingTable error. db : [olap] tableName : [{}]", tableName, t);}} else {((ShardingDataSource) shardingDataSource).getDataSourceMap().forEach((dbName, myDataSource) -> {if (dbName.equals(dbShardingConfig.getCenterDs())) {// 中心库不生成相关表return;}try {Connection connection = myDataSource.getConnection();List<String> nextWeekWorkDays = getNextWeekWorkDays();nextWeekWorkDays.forEach(day -> {createShardingTable(dbName, connection, tableName, day, config);});} catch (Throwable t) {log.error("createShardingTable error. db : [{}] tableName : [{}]", dbName, tableName, t);}});}}/*** 创建分表** @param dbName 数据库名称* @param connection 数据库连接* @param tableName 表名称* @param day 工作日 - 预留给手动补数据使用*/private void createShardingTable(String dbName, Connection connection, String tableName, String day, DatabaseShardingConfig.TableShardingConfig config) {DatabaseShardingConfig.TableShardingConfig tableShardingConfig = dbShardingConfig.getTableShardingConfig(tableName);if (config.getTableShardingNum() > 1) {for (int i = 0; i < tableShardingConfig.getTableShardingNum(); i++) {String realTableName = tableName + "_" + day.substring(2) + "_" + i;try {String sql = String.format(SHARDING_TABLE_CREATE_SQL, realTableName, tableShardingConfig.getTemplateTable());connection.createStatement().execute(sql);log.info("createShardingTable success. db : [{}] tableName : [{}], realTableName : [{}], sql : [{}]", dbName, tableName, realTableName, sql);} catch (Throwable t) {log.error("createShardingTable error. db : [{}] tableName : [{}], realTableName : [{}]", dbName, tableName, realTableName, t);}}} else {String realTableName = tableName + "_" + day.substring(2);try {String sql = String.format(SHARDING_TABLE_CREATE_SQL, realTableName, tableShardingConfig.getTemplateTable());connection.createStatement().execute(sql);log.info("createShardingTable success. db : [{}] tableName : [{}], realTableName : [{}], sql : [{}]", dbName, tableName, realTableName, sql);} catch (Throwable t) {log.error("createShardingTable error. db : [{}] tableName : [{}], realTableName : [{}]", dbName, tableName, realTableName, t);}}}/*** 获取下一周的全部工作日** @return 下一周的工作日*/private List<String> getNextWeekWorkDays() {LocalDate today = LocalDate.now();// 下周一LocalDate nextMonday = today.with(TemporalAdjusters.next(DayOfWeek.MONDAY));List<String> workDays = new ArrayList<>();DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYYMMDD);for (int i = 0; i < 5; i++) {// 下周一到下周五LocalDate date = nextMonday.plusDays(i);workDays.add(date.format(formatter));}return workDays;}private void clearShardingTable(String tableName, DatabaseShardingConfig.TableShardingConfig config) {if (DS_OLAP.equals(config.getDs())) {try {Connection connection = olapDataSource.getConnection();List<String> nextWeekWorkDays = getToBeClearDays(tableName);nextWeekWorkDays.forEach(day -> {clearShardingTable("olap", connection, tableName, day, config);});} catch (Throwable t) {log.error("clearShardingTable error. db : [olap] tableName : [{}]", tableName, t);}} else {((ShardingDataSource) shardingDataSource).getDataSourceMap().forEach((dbName, myDataSource) -> {if (dbName.equals(dbShardingConfig.getCenterDs())) {// 中心库不删除相关表return;}try {Connection connection = myDataSource.getConnection();List<String> nextWeekWorkDays = getToBeClearDays(tableName);nextWeekWorkDays.forEach(day -> {clearShardingTable(dbName, connection, tableName, day, config);});} catch (Throwable t) {log.error("clearShardingTable error. db : [{}] tableName : [{}]", dbName, tableName, t);}});}}/*** 清理分表** @param dbName 数据库名称* @param connection 数据库连接* @param tableName 表名称* @param day 工作日 - 预留给手动补数据使用*/private void clearShardingTable(String dbName, Connection connection, String tableName, String day, DatabaseShardingConfig.TableShardingConfig config) {if (config.getTableShardingNum() > 1) {for (int i = 0; i < config.getTableShardingNum(); i++) {String realTableName = tableName + "_" + day.substring(2) + "_" + i;try {String sql = String.format(SHARDING_TABLE_CLEAR_SQL, realTableName);connection.createStatement().execute(sql);log.info("clearShardingTable success. db : [{}] tableName : [{}], realTableName : [{}], sql : [{}]", dbName, tableName, realTableName, sql);} catch (Throwable t) {log.error("clearShardingTable error. db : [{}] tableName : [{}], realTableName : [{}]", dbName, tableName, realTableName, t);}}} else {String realTableName = tableName + "_" + day.substring(2);try {String sql = String.format(SHARDING_TABLE_CLEAR_SQL, realTableName);connection.createStatement().execute(sql);log.info("clearShardingTable success. db : [{}] tableName : [{}], realTableName : [{}], sql : [{}]", dbName, tableName, realTableName, sql);} catch (Throwable t) {log.error("clearShardingTable error. db : [{}] tableName : [{}], realTableName : [{}]", dbName, tableName, realTableName, t);}}}/*** 获取待清理的表对应的日期** @param tableName 逻辑表名称* @return 待清理的日期*/private List<String> getToBeClearDays(String tableName) {List<String> days = new ArrayList<>();DatabaseShardingConfig.TableShardingConfig tableShardingConfig = dbShardingConfig.getTableShardingConfig(tableName);LocalDate today = LocalDate.now();LocalDate startDay = today.minusDays(tableShardingConfig.getClearOffset());LocalDate endDay = today.minusDays(tableShardingConfig.getKeepDays());DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.YYYYMMDD);for (LocalDate date = startDay; date.isBefore(endDay); date = date.plusDays(1)) {days.add(date.format(formatter));}return days;}}
- 配置
package com.zzc.service.config;@Data
@Slf4j
@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "refinitiv.api-service.db-sharding")
@PropertySource(value = "classpath:guda-refinitiv-api-db-sharding.yaml", factory = YamlPropertySourceFactory.class)
public class DatabaseShardingConfig {private String centerDs;private Map<String, TableShardingConfig> tables;private Map<String, String> marketConfigs;@Setter(AccessLevel.PRIVATE)private Map<String, String> dbMap;@PostConstructpublic void init() {if (marketConfigs == null || marketConfigs.isEmpty()) {throw new RuntimeException("DatabaseShardingConfig error. configs is empty");}Map<String, String> tmp = new HashMap<>();marketConfigs.forEach((dbName, markets) -> {for (String market : markets.split(",")) {tmp.put(market.trim(), dbName);}});dbMap = tmp;log.info("DatabaseShardingConfig init success. config: [{}]", this);}/*** 根据市场类型获取对应的数据库名称** @param market 市场类型(MarketCodeType 枚举的 name)* @return 数据库名称*/public String getDbName(String market) {return dbMap.get(market);}/*** 根据表名获取对应的分库配置** @param tableName 表名* @return 分库配置*/public TableShardingConfig getTableShardingConfig(String tableName) {return tables.get(tableName);}@Data@NoArgsConstructor@AllArgsConstructorpublic static class TableShardingConfig {/** 模板表名 */private String templateTable;/** 分多少张表 */private int tableShardingNum;/** 数据保留天数 */private int keepDays;/** 从哪一天开始清理 */private int clearOffset;/** 数据库名称 */private String ds;/** 是否按日期分表 */private Boolean runCreateJob = true;}
}
refinitiv.api-service:db-sharding:centerDs: 'center'tables:trade_record:# 模版表templateTable: 'trade_record_240101'# 分多少张表tableShardingNum: 250# 数据保留天数keepDays: 7# 从哪一天开始清理(一直清理到 keepDays 为止)clearOffset: 15ds: 'shardingDataSource'olap_quotation_snapshot:# 模版表templateTable: 'olap_quotation_snapshot_240101'# 分多少张表tableShardingNum: 1# 数据保留天数keepDays: 30# 从哪一天开始清理(一直清理到 keepDays 为止)clearOffset: 40ds: 'olapDataSource'kline_m1:# 模版表templateTable: 'kline_m1'# 分多少张表tableShardingNum: 1# 数据保留天数keepDays: 30# 从哪一天开始清理(一直清理到 keepDays 为止)clearOffset: 40ds: 'shardingDataSource'kline:# 模版表templateTable: 'kline'# 分多少张表tableShardingNum: 16# 数据保留天数keepDays: 30# 从哪一天开始清理(一直清理到 keepDays 为止)clearOffset: 40ds: 'shardingDataSource'runCreateJob: falsemarketConfigs:# db0 存储 US, US_PINK, US_OPTION 相关数据# ds2: 'US, US_PINK, US_OPTION'ds1: 'HK, HK_WRNT, HK_BONDA, HK_TRUST'ds0: 'US, US_PINK, US_OPTION, SH, SZ, SZ_INDEX, SZ_FUND, SZ_GEM, US_ETF'
相关文章:
Spring Boot ShardingJDBC分库分表(草稿)
ShardingJDBC分库分表 1.Maven 引用 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency><dependency><…...

Jenkins 环境搭建---基于 Docker
前期准备 提前安装jdk、maven、nodeJs(如果需要的话) 创建 jenkins 环境目录,用来当做挂载卷 /data/jenkins/ 一:拉取 Jenkins 镜像 docker pull jenkins/jenkins:lts 二:设置 Jenkins挂载目录 mkdir -p ~/jen…...
如何在自定义组件中使用v-model实现双向绑定
在 Vue 2 中,v-model 是双向数据绑定的语法糖,它默认将 value 作为 prop 传入组件,并通过监听 input 事件来更新父组件的数据。若要在自定义组件中实现 v-model 的双向绑定,需遵循以下步骤: 1. 基本实现:va…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_pool_t 类型
ngx_pool_t 定义在 src/core/ngx_core.h typedef struct ngx_pool_s ngx_pool_t; ngx_pool_s 定义在 src/core/ngx_palloc.h struct ngx_pool_s {ngx_pool_data_t d;size_t max;ngx_pool_t *current;ngx_chain_t *chain;ng…...
如何在 ubuntu 上使用 Clash 与 docker 开启代理拉起
如何在 ubuntu 上使用 Clash https://github.com/doreamon-design/clash/releases上面是clash 的地址 clash_2.0.24_linux_386.tar.gz 下载 386 的 如果你的电脑是inter tar -xzvf clash_2.0.24_linux_386.tar.gz 启动 ./clash 然后会在电脑上生成一个config的文件 /home/xxx/…...
linux tcpdump抓包
参数说明: -i 指定网卡 -w 指定保存文件 -s0 完整抓包 -G 指定间隔时长(秒) -C 指定每个文件大小(M) 用法1: 指定端口输出到指定文件 tcpdump -i em3 -w 182910.pcap 用法2: 指定端口每10分钟输出到不同文件 tcpdump -i em3 -s0 -G 600 -w %Y_%m%d_%H%M_%S.pcap 用法3: 指…...
PLSQL连接Oracle 19c报错ORA-28040
PLSQL连接Oracle 19c报错ORA-28040 原因解析解决办法原因解析 使用PLSQL Developer连接19c数据库报错: ORA-28040: No matching authentication protocol报错信息解析: [oracle@ora19c ~]$ oerr ora 2804028040, 0000, "No matching authentication protocol" /…...

汽车免拆诊断案例 | 2010 款路虎揽胜车空调偶尔出风异常
故障现象 一辆2010款路虎揽胜车,搭载5.0 L发动机,累计行驶里程约为16万km。车主反映,接通空调开关后,有时出风忽大忽小,有时不出风,有时要等2 min左右才出风;有时两三天出现一次,…...

音视频入门基础:RTP专题(9)——FFmpeg接收RTP流的原理和内部实现
一、引言 由《音视频入门基础:RTP专题(2)——使用FFmpeg命令生成RTP流》可以知道,推流端通过下面FFmpeg命令可以将一个媒体文件转推RTP,生成RTP流: ffmpeg -re -stream_loop -1 -i input.mp4 -vcodec cop…...

Nginx 安装及配置教程(Windows)【安装】
文章目录 一、 Nginx 下载 1. 官网下载2. 其它渠道 二、 Nginx 安装三、 配置四、 验证五、 其它问题 1. 常用命令2. 跨域问题 软件 / 环境安装及配置目录 一、 Nginx 下载 1. 官网下载 安装地址:https://nginx.org/en/download.html 打开浏览器输入网址 htt…...

《跟李沐学 AI》AlexNet论文逐段精读学习心得 | PyTorch 深度学习实战
前一篇文章,使用 AlexNet 实现图片分类 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 本篇文章内容来自于学习 9年后重读深度学习奠基作之一:AlexNet【下】【论文精读】】的心得。 《跟李沐…...
嵌入式0xDEADBEEF
在嵌入式系统中,0xDEADBEEF 是一个常见的“魔数”(magic number),通常用于调试和内存管理。它的含义和用途如下: 1. 调试用途 未初始化内存的标记:在调试时,0xDEADBEEF 常用于标记未初始化或已…...
B+树作为数据库索引结构的优势对比
MySQL作为数据库,它的功能就是做数据存储和数据查找;使用B树作为索引结构是为了实现高效的查找、插入和删除操作。 B树的查找、插入、删除的复杂度都为 O(log n),它是一个多叉树的结构,能兼顾各种操作的效率的数据结构。如果使用…...
自适应SQL计划管理(Adaptive SQL Plan Management)在Oracle 12c中的应用
在Oracle Database 12c Release 1 (12.1)版本中,引入了对SQL计划管理(SPM)功能的增强,特别是关于SQL计划基线的自动进化机制。这一改进允许数据库更加智能地管理和优化SQL查询的执行计划,确保即使数据分布发生变化&…...

什么是DeFi (去中心化金融)
DeFi (去中心化金融) 概述 💰 1. DeFi 基础概念 1.1 什么是 DeFi? DeFi 是建立在区块链上的金融服务生态系统,它: 无需中心化中介开放且透明无需许可即可参与代码即法律 1.2 DeFi 的优势 开放性:任何人都可以参与…...

计算机毕业设计Python农产品推荐系统 农产品爬虫 农产品可视化 农产品大数据(源码+LW文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...

LLM论文笔记 15: Transformers Can Achieve Length Generalization But Not Robustly
Arxiv日期:2024.2.14机构:Google DeepMind / University of Toronto 关键词 长度泛化位置编码数据格式 核心结论 1. 实验结论:十进制加法任务上的长度泛化最佳组合: FIRE位置编码 随机化位置编码 反向数据格式 索引提示&…...

SpringAI做对了什么
开发|界面|引擎|交付|副驾——重写全栈法则:AI原生的倍速造应用流 你好,这里是nine[谈架构]系列。 欢迎关注评论私信交流~ SpringAI 在 AI 编程领域延续了Spring的诸多优势,从易于集成、到通用…...

DeepSeek预测25考研分数线
25考研分数马上要出了。 目前,多所大学已经陆续给出了分数查分时间,综合往年情况来看,每年的查分时间一般集中在2月底。 等待出成绩的日子,学子们的心情是万分焦急,小编用最近爆火的“活人感”十足的DeepSeek帮大家预…...

C++笔记之标准库中的std::copy 和 std::assign 作用于 std::vector
C++笔记之标准库中的std::copy 和 std::assign 作用于 std::vector code review! 文章目录 C++笔记之标准库中的std::copy 和 std::assign 作用于 std::vector1. `std::copy`1.1.用法1.2.示例2.`std::vector::assign`2.1.用法2.2.示例3.区别总结4.支持assign的容器和不支持ass…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...