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…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
