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…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
