Redisson学习专栏(三):高级特性与实战(Spring/Spring Boot 集成,响应式编程,分布式服务,性能优化)
文章目录
- 前言
- 一、Spring Boot深度整合实战
- 1.1 分布式缓存管理
- 1.2 声明式缓存
- 1.3 响应式编程
- 二、分布式服务治理
- 2.1 服务端实现
- 2.2 客户端调用
- 2.3 高级特性
- 2.4 服务治理功能
- 三、分布式任务调度引擎
- 四、连接池配置与网络参数调优
- 4.1 连接池配置
- 4.2 网络参数调优
- 4.3 集群模式特殊配置
- 最佳实践配置示例
- 五、如何规避大Key
- 总结
前言
在掌握了Redisson的基础功能后,我们已经能够熟练使用分布式集合、分布式锁、原子操作等核心功能来构建简单的分布式应用。然而,真实的生产环境往往面临着更复杂的挑战——如何将Redisson无缝融入Spring生态?如何应对高并发场景下的性能瓶颈?如何实现跨服务的协同调度?
这正是本专栏要重点探讨的内容。我们将从框架整合的实践出发,逐步深入到分布式系统设计的核心领域。通过Redisson与Spring Cache的深度集成,开发者可以轻松实现声明式的分布式缓存,而不再需要手动管理缓存逻辑。响应式API的引入则为高吞吐量系统提供了新的可能性,让我们能够以更优雅的方式处理异步数据流。
一、Spring Boot深度整合实战
1.1 分布式缓存管理
关键配置(application.yml):
spring:redis:redisson:config: |singleServerConfig:address: "redis://prod-redis:6379" # 生产环境集群地址password: ${REDIS_PASSWORD} # 从环境变量读取密码database: 0# 连接池黄金参数connectionPoolSize: 256 # 最大连接数 = (QPS * 平均耗时ms)/1000 * 1.5connectionMinimumIdleSize: 64 # 防止突发流量idleConnectionTimeout: 60000 # 空闲连接超时(ms)connectTimeout: 10000 # 连接建立超时timeout: 3000 # 命令执行超时threads: 32 # 业务处理线程数nettyThreads: 16 # I/O线程数
分布式Session实战:
- 启用配置类
@Configuration
@EnableRedissonHttpSession(maxInactiveIntervalInSeconds = 1800, // 30分钟会话超时redisNamespace = "prod:session" // 生产环境命名空间
)
public class SessionConfig {@Beanpublic RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {// 关键:使用Redisson专用连接工厂return new RedissonConnectionFactory(redisson);}
}
- Session存储机制
- 存储结构:Hash结构存储会话属性
HMSET prod:session:sid1 attribute1 "value1" attribute2 "value2"
EXPIRE prod:session:sid1 1800
- 优势:
- 属性级修改(仅更新变更字段)
- 自动续期机制(每次访问刷新TTL)
- 会话变更事件监听(支持集群同步)
- 集群环境验证
@RestController
public class SessionController {@GetMapping("/session")public String testSession(HttpSession session) {// 写入会话session.setAttribute("lastAccess", Instant.now());// 跨服务读取验证return "Session ID: " + session.getId() + " | Last Access: " + session.getAttribute("lastAccess");}
}
测试流程:
1. 请求服务A:GET /session → 返回SessionId: sid1
2. 请求服务B:携带Cookie JSESSIONID=sid1
3. 服务B正确返回服务A写入的时间戳
1.2 声明式缓存
核心注解全解
注解 | 等效命令 | 适用场景 | Redisson优化项 |
---|---|---|---|
@Cacheable | GET + SET | 读多写少 | 支持TTL与本地缓存联动 |
@CachePut | SET | 强制更新缓存 | 原子化写入保证一致性 |
@CacheEvict | DEL | 数据变更时失效缓存 | 支持模式匹配删除(keyPattern) |
@Caching | 复合操作 | 多缓存操作组合 | 支持事务内执行 |
高级参数配置:
@Cacheable(value = "financialReports", key = "#year + '_' + #quarter",condition = "#year >= 2020", // 满足条件才缓存unless = "#result == null || #result.isSensitive()", // 结果过滤cacheManager = "secureCacheManager" // 指定加密缓存管理器
)
public Report getAnnualReport(int year, String quarter) {return reportService.generate(year, quarter);
}
缓存数据结构设计
Redisson存储格式:
# String结构(简单类型)
SET cacheName:key value EX 3600# Hash结构(对象类型)
HSET cacheName:key field1 value1 field2 value2
EXPIRE cacheName:key 3600
动态TTL控制
- 时间维度策略
@Cacheable(value = "seasonalProducts",key = "#productId",cacheManager = "dynamicTTLCacheManager"
)
public Product getProduct(String productId) {return productService.findById(productId);
}// 动态TTL配置
@Bean
public CacheManager dynamicTTLCacheManager(RedissonClient redisson) {return new RedissonSpringCacheManager(redisson) {@Overrideprotected CacheConfig createDefaultConfig() {return new CacheConfig(TimeUnit.HOURS.toMillis(1), // 默认1小时TimeUnit.MINUTES.toMillis(30)) {@Overridepublic long getTTL() {// 旺季延长缓存时间return isPeakSeason() ? TimeUnit.DAYS.toMillis(7) : super.getTTL();}};}};
}
- 热点数据识别
@Cacheable(value = "hotItems",key = "#itemId",cacheManager = "adaptiveCacheManager"
)
public Item getItem(String itemId) {return itemService.load(itemId);
}// 自适应缓存配置
public class AdaptiveCacheManager extends RedissonSpringCacheManager {private final HotKeyDetector hotKeyDetector;@Overrideprotected CacheConfig getCacheConfig(String cacheName, String key) {CacheConfig config = super.getCacheConfig(cacheName);if (hotKeyDetector.isHotKey(key)) {config.setMaxIdleTime(TimeUnit.HOURS.toMillis(24)); // 热点数据延长}return config;}
}
1.3 响应式编程
Reactive API实战流处理
注入响应式客户端:
@Autowired
private RedissonReactiveClient reactiveClient;
订单流处理示例:
public Flux<Order> getHotOrders() { RScoredSortedSetReactive<Order> orderSet = reactiveClient.getScoredSortedSet("hot_orders"); return orderSet.entryRangeReversed(0, 9) .flatMap(entry -> orderRepository.findById(entry.getValue())) .onErrorResume(e -> Metrics.recordFailure("hot_orders"));
}
背压机制天然支撑10万+/秒订单流处理,延迟低于50ms。
二、分布式服务治理
Redisson的分布式远程服务(Remote Service)功能提供了一种简单高效的方式来实现跨JVM的Java方法调用,使得开发者可以像调用本地方法一样调用远程服务,主要基于Redis的发布/订阅机制实现,下面给出架构图。
2.1 服务端实现
基本服务注册:
// 获取远程服务实例
RRemoteService remoteService = redisson.getRemoteService();// 服务实现类
public class MyServiceImpl implements MyService {@Overridepublic String doSomething(String param) {return "Processed: " + param;}
}// 注册服务
MyService serviceImpl = new MyServiceImpl();
remoteService.register(MyService.class, serviceImpl);
注册带有超时设置的服务:
// 设置服务超时时间为5秒
remoteService.register(MyService.class, serviceImpl, 5);
异步服务注册:
// 异步执行的服务实现
public class MyAsyncServiceImpl implements MyAsyncService {@Overridepublic RFuture<String> doSomethingAsync(String param) {// 返回Redisson的RFuture对象return RedissonPromise.newSucceededFuture("Async: " + param);}
}// 注册异步服务
remoteService.register(MyAsyncService.class, new MyAsyncServiceImpl());
2.2 客户端调用
同步调用:
RRemoteService remoteService = redisson.getRemoteService();
MyService service = remoteService.get(MyService.class);// 同步调用
String result = service.doSomething("test");
System.out.println(result); // 输出: Processed: test
异步调用:
MyAsyncService asyncService = remoteService.get(MyAsyncService.class);// 异步调用
RFuture<String> future = asyncService.doSomethingAsync("asyncTest");
future.onComplete((result, exception) -> {if (exception != null) {exception.printStackTrace();} else {System.out.println(result); // 输出: Async: asyncTest}
});
带超时的调用:
// 设置调用超时时间为3秒
MyService service = remoteService.get(MyService.class, 3);try {String result = service.doSomething("timeoutTest");
} catch (RemoteServiceTimeoutException e) {// 处理超时异常e.printStackTrace();
}
2.3 高级特性
负载均衡:
// 获取带有负载均衡的服务
MyService service = remoteService.get(MyService.class, new RoundRobinLoadBalancer()); // 轮询策略// 可用的负载均衡器:
// - RandomLoadBalancer (随机)
// - RoundRobinLoadBalancer (轮询)
// - WeightedRoundRobinLoadBalancer (加权轮询)
服务Ack确认:
// 注册服务时设置需要ack确认
remoteService.register(MyService.class, serviceImpl, true);// 客户端调用
MyService service = remoteService.get(MyService.class);
service.doSomething("ackTest"); // 会等待服务端确认收到请求
自定义编解码器:
// 实现自定义编解码器
public class CustomCodec implements Codec {// 实现encode和decode方法
}// 使用自定义编解码器注册服务
remoteService.register(MyService.class, serviceImpl, new CustomCodec());// 客户端使用相同编解码器获取服务
MyService service = remoteService.get(MyService.class, new CustomCodec());
2.4 服务治理功能
服务发现:
// 获取所有已注册的服务名称
Collection<String> services = remoteService.getRegisteredServices();// 获取特定服务的所有实例
Collection<RemoteServiceServer> servers = remoteService.getNodes(MyService.class);
for (RemoteServiceServer server : servers) {System.out.println("Server: " + server.getAddr());
}
服务调用统计:
// 获取服务调用统计信息
RemoteServiceStats stats = remoteService.getStats(MyService.class);
System.out.println("Total calls: " + stats.getTotalCalls());
System.out.println("Failed calls: " + stats.getFailedCalls());
System.out.println("Average time: " + stats.getAverageTime());
写到这里是不是感觉Redisson的功能很强大,但是实际大型项目还是建议使用Dubbo等大型框架去进行RPC调用,主是因为Dubbo 基于 Netty,性能比 Redisson(基于 Redis PUB/SUB)更高,适合高并发场景。还有就是Dubbo 提供 熔断、动态路由、权重调整 等能力,Redisson 没有这些功能。Redisson提供的分布式治理功能大家感兴趣可以自己玩玩。
三、分布式任务调度引擎
Redisson的分布式任务调度引擎特别适合需要在分布式环境下执行定时任务、延迟任务和并行任务的场景,能够有效解决传统单机任务调度器在分布式环境下的局限性。
核心组件:
- RScheduler
调度器接口,主要方法包括:
// 调度一次性任务
ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit);// 调度固定延迟的周期性任务
ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit);// 使用CRON表达式调度任务
ScheduledFuture<?> schedule(String cronExpression, Runnable task);
- RExecutorService
分布式执行服务,用于执行已提交的Runnable或Callable任务。 - ScheduledFuture
表示异步调度的结果,可用于取消任务或检查任务状态。
基本使用:
// 创建Redisson客户端
RedissonClient redisson = Redisson.create(config);// 获取调度器实例
RScheduler scheduler = redisson.getExecutorService("myScheduler").getScheduler();// 调度一个10秒后执行的一次性任务
scheduler.schedule(() -> {System.out.println("Task executed at: " + new Date());
}, 10, TimeUnit.SECONDS);// 调度一个每分钟执行一次的周期性任务
scheduler.scheduleWithFixedDelay(() -> {System.out.println("Periodic task executed at: " + new Date());
}, 0, 1, TimeUnit.MINUTES);// 使用CRON表达式调度任务
scheduler.schedule("0 0/5 * * * ?", () -> {System.out.println("CRON task executed at: " + new Date());
});
分布式Worker示例:
public class DistributedWorker {public static void main(String[] args) {Config config = new Config();config.useClusterServers().addNodeAddress("redis://127.0.0.1:7000");RedissonClient redisson = Redisson.create(config);RExecutorService executor = redisson.getExecutorService("myExecutor");// 提交任务executor.submit(() -> {System.out.println("Distributed task executed by worker");return "result";});// 关闭客户端(不会立即关闭,会等待任务完成)redisson.shutdown();}
}
高级特性:
- 任务重试
Redisson支持任务执行失败时的自动重试机制:
RScheduledExecutorService executor = redisson.getExecutorService("myExecutor");
executor.registerWorkers(WorkerOptions.defaults().retryAttempts(3) // 重试次数.retryInterval(5, TimeUnit.SECONDS) // 重试间隔
);
- 任务拦截器
可以通过实现TaskListener接口来监听任务生命周期事件:
executor.addListener(new TaskListener() {@Overridepublic void onStarted(String taskId) {System.out.println("Task started: " + taskId);}@Overridepublic void onComplete(String taskId) {System.out.println("Task completed: " + taskId);}@Overridepublic void onError(String taskId, Throwable exception) {System.out.println("Task failed: " + taskId);}
});
- 任务分片
对于大数据量处理,可以使用任务分片:
RScheduledExecutorService executor = redisson.getExecutorService("myExecutor");
executor.schedule(new RunnableTask() {@Overridepublic void run() {// 任务逻辑}@Overridepublic List<Object> getTasks() {// 返回分片列表return Arrays.asList("shard1", "shard2", "shard3");}
}, new CronSchedule("0 0/5 * * * ?"));
集群环境定时任务
任务定义:
public class DataCleanTask implements Runnable, Serializable { @Override public void run() { log.info("Cleaning expired data at {}", Instant.now()); dataService.cleanExpired(); }
}
分布式调度:
RScheduledExecutorService executor = redisson.getExecutorService("globalCleaner"); executor.scheduleAtFixedRate( new DataCleanTask(), TimeUnit.DAYS.toMillis(1), // 初始延迟 TimeUnit.DAYS.toMillis(1) // 执行间隔
);
Redisson的分布式任务调度引擎为分布式系统提供了强大而灵活的任务调度能力,是构建可靠分布式应用的理想选择。
四、连接池配置与网络参数调优
4.1 连接池配置
- 核心连接池参数
在Redisson配置中,连接池主要通过以下参数控制:
Config config = new Config();
config.useSingleServer()// 连接池参数.setConnectionPoolSize(64) // 最大连接数.setConnectionMinimumIdleSize(24) // 最小空闲连接数.setIdleConnectionTimeout(10000) // 空闲连接超时时间(毫秒).setConnectTimeout(1000) // 连接超时时间(毫秒).setTimeout(3000) // 命令等待超时时间(毫秒).setRetryAttempts(3) // 命令失败重试次数.setRetryInterval(1500); // 命令重试间隔时间(毫秒)
- 连接池参数详解
参数名 | 默认值 | 说明 | 推荐值(生产环境) |
---|---|---|---|
connectionPoolSize | 64 | 最大连接数 | 根据QPS调整,一般50-500 |
connectionMinimumIdleSize | 24 | 最小空闲连接数 | 最大连接数的1/3到1/2 |
idleConnectionTimeout | 10000 | 空闲连接超时时间(ms) | 60000-120000 |
connectTimeout | 10000 | 连接建立超时时间(ms) | 1000-3000 |
timeout | 3000 | 命令执行超时时间(ms) | 根据业务调整 |
retryAttempts | 3 | 命令重试次数 | 2-5 |
retryInterval | 1500 | 命令重试间隔(ms) | 1000-3000 |
- 连接池配置原则
- 连接数计算:理想连接数 ≈ QPS × 平均响应时间(秒),例如:QPS=1000,平均响应时间=10ms,理论需要10个连接,实际应留有余量,建议设置为理论值的1.5-2倍。
- 空闲连接设置:应避免频繁创建/销毁连接,生产环境建议最小空闲连接数不低于10。
- 超时设置:连接超时应小于服务超时,命令超时应根据业务容忍度设置。
4.2 网络参数调优
- 网络相关核心参数
config.useSingleServer()// 网络参数.setKeepAlive(true) // 启用TCP Keepalive.setTcpNoDelay(true) // 启用TCP_NODELAY.setPingConnectionInterval(30000) // PING命令间隔(ms).setSslEnableEndpointIdentification(true) // SSL端点验证.setSslProvider(SslProvider.JDK) // SSL实现.setSslTruststorePassword("password") // SSL信任库密码.setSslKeystorePassword("password"); // SSL密钥库密码
- 网络参数详解
参数名 | 默认值 | 说明 | 优化建议 |
---|---|---|---|
keepAlive | false | TCP Keepalive | 生产环境建议true |
tcpNoDelay | true | 禁用Nagle算法 | 保持true |
pingConnectionInterval | 30000 | PING命令间隔(ms) | 60000 |
sslEnableEndpointIdentification | true | SSL端点验证 | 生产环境必须true |
sslProvider | JDK | SSL实现 | 高性能场景可用OPENSSL |
- 高级网络配置
Netty参数调优:
Redisson底层使用Netty,可通过以下方式调优:
config.setTransportMode(TransportMode.NIO) // 传输模式.setNettyThreads(32) // Netty线程数.setEventLoopGroup(new NioEventLoopGroup()) // 自定义EventLoopGroup.setUseLinuxNativeEpoll(true); // 启用Epoll(Linux)
优化建议:
- Linux环境开启Epoll:setUseLinuxNativeEpoll(true)
- Netty线程数建议设置为CPU核心数的2-4倍
- 高吞吐场景可使用TransportMode.EPOLL(Linux)或TransportMode.KQUEUE(Mac)
DNS监控:
config.setDnsMonitoringInterval(5000); // DNS监控间隔(ms)
4.3 集群模式特殊配置
- 集群连接池配置
config.useClusterServers().setMasterConnectionPoolSize(64) // 主节点连接池大小.setSlaveConnectionPoolSize(64) // 从节点连接池大小.setMasterConnectionMinimumIdleSize(24) // 主节点最小空闲.setSlaveConnectionMinimumIdleSize(24) // 从节点最小空闲.setScanInterval(2000); // 集群状态扫描间隔(ms)
- 读写分离配置
config.useClusterServers().setReadMode(ReadMode.SLAVE) // 优先从从节点读取.setSubscriptionMode(SubscriptionMode.SLAVE); // 订阅从从节点
最佳实践配置示例
Config config = new Config();
config.useClusterServers().addNodeAddress("redis://127.0.0.1:7000")// 连接池配置.setMasterConnectionPoolSize(128).setSlaveConnectionPoolSize(128).setMasterConnectionMinimumIdleSize(32).setSlaveConnectionMinimumIdleSize(32)// 超时配置.setConnectTimeout(2000).setTimeout(5000).setIdleConnectionTimeout(60000)// 重试配置.setRetryAttempts(3).setRetryInterval(1000)// 网络配置.setKeepAlive(true).setTcpNoDelay(true).setPingConnectionInterval(60000)// 集群配置.setScanInterval(3000)// Netty配置.setNettyThreads(48);if (Linux.isLinux()) {config.setTransportMode(TransportMode.EPOLL).setUseLinuxNativeEpoll(true);
}
通过以上详细的连接池配置和网络参数调优,可以显著提升Redisson的性能和稳定性,适应不同的生产环境需求。实际配置应根据具体业务场景、硬件配置和性能测试结果进行调整。
五、如何规避大Key
大Key问题是指Redis中存储的某些Key对应的Value过大,导致内存占用高、操作阻塞、网络负载大等问题。以下是Redisson处理大Key问题的几种策略:
- 分片存储策略
// 用户标签分片存储
public void addUserTag(Long userId, String tag) { int shard = userId % 16; RSet<String> tagSet = redisson.getSet("user_tags:" + shard); tagSet.add(tag);
}
- 使用过期时间:为可能变大的Key设置过期时间
RMapCache<String, String> map = redisson.getMapCache("myMap");
map.put("key", "value", 10, TimeUnit.MINUTES); // 10分钟后过期
- 分布式集合:对于大型集合,Redisson提供了分布式实现
RSetCache<String> distributedSet = redisson.getSetCache("mySet");
RList<String> distributedList = redisson.getList("myList");
总结
通过本专栏,您已掌握Redisson在复杂分布式系统中的工业化应用。当这些技术组合发力时,Redis将不再是简单的缓存,而是成为分布式系统的核心中枢。接下来,我们将在专栏四中展现Redisson实战应用。
相关文章:

Redisson学习专栏(三):高级特性与实战(Spring/Spring Boot 集成,响应式编程,分布式服务,性能优化)
文章目录 前言一、Spring Boot深度整合实战1.1 分布式缓存管理1.2 声明式缓存1.3 响应式编程 二、分布式服务治理2.1 服务端实现2.2 客户端调用2.3 高级特性2.4 服务治理功能 三、分布式任务调度引擎四、连接池配置与网络参数调优4.1 连接池配置4.2 网络参数调优4.3 集群模式特…...

华为欧拉系统中部署FTP服务与Filestash应用:实现高效文件管理和共享
华为欧拉系统中部署FTP服务与Filestash应用:实现高效文件管理和共享 前言一、相关服务介绍1.1 Huawei Cloud EulerOS介绍1.2 Filestash介绍1.3 华为云Flexus应用服务器L实例介绍二、本次实践介绍2.1 本次实践介绍2.2 本次环境规划三、检查云服务器环境3.1 登录华为云3.2 SSH远…...

基于Docker和YARN的大数据环境部署实践最新版
基于Docker和YARN的大数据环境部署实践 目的 本操作手册旨在指导用户通过Docker容器技术,快速搭建一个完整的大数据环境。该环境包含以下核心组件: Hadoop HDFS/YARN(分布式存储与资源调度)Spark on YARN(分布式计算…...

【大模型】Bert
一、背景与起源 上下文建模的局限:在 BERT 之前,诸如 Word2Vec、GloVe 等词向量方法只能给出静态的词表示;而基于单向或浅层双向 LSTM/Transformer 的语言模型(如 OpenAI GPT)只能捕捉文本从左到右(或右到…...
《Go小技巧易错点100例》第三十四篇
本期分享: 1.sync.Mutex锁复制导致的异常 2.Go堆栈机制下容易导致的并发问题 sync.Mutex锁复制导致的异常 以下代码片段存在一个隐蔽的并发安全问题: type Counter struct {sync.MutexCount int }func foo(c Counter) {c.Lock()defer c.Unlock()…...
vue3+element-plus el-date-picker日期、年份筛选设置本周、本月、近3年等快捷筛选
一、页面代码: <template> <!-- 日期范围筛选框 --> <el-date-picker v-model"dateRange" value-format"YYYY-MM-DD" type"daterange" range-separator"至" start-placeholder"开始日期" end-…...
Vue 技术文档
一、引言 Vue 是一款用于构建用户界面的渐进式 JavaScript 框架,具有易上手、高性能、灵活等特点,能够帮助开发者快速开发出响应式的单页面应用。本技术文档旨在全面介绍 Vue 的相关技术知识,为开发人员提供参考和指导。 二、环境搭建 2.1…...

3 分钟学会使用 Puppeteer 将 HTML 转 PDF
需求背景 1、网页存档与文档管理 需要将网页内容长期保存或归档为PDF,确保内容不被篡改或丢失,适用于法律文档、合同、技术文档等场景。PDF格式便于存储和检索。 2、电子报告生成 动态生成的HTML内容(如数据分析报告、仪表盘)需导出为PDF供下载或打印。PDF保留排版和样…...

速通《Sklearn 与 TensorFlow 机器学习实用指南》
1.机器学习概览 1.1 什么是机器学习 机器学习是通过编程让计算机从数据中进行学习的科学。 1.2 为什么使用机器学习? 使用机器学习,是为了让计算机通过数据自动学习规律并进行预测或决策,无需显式编程规则。 1.3 机器学习系统的类型 1.…...

Ubuntu 下搭建ESP32 ESP-IDF开发环境,并在windows下用VSCode通过SSH登录Ubuntu开发ESP32应用
Ubuntu 下搭建ESP32 ESP-IDF开发环境,网上操作指南很多,本来一直也没有想过要写这么一篇文章。因为我其实不太习惯在linux下开发应用,平时更习惯windows的软件操作,只是因为windows下开发ESP32的应用编译时太慢,让人受…...
[FreeRTOS- 野火] - - - 临界段
一、介绍 临界段最常出现在对一些全局变量进行操作的场景。 1.1 临界段的定义 临界段是指在多任务系统中,一段需要独占访问共享资源的代码。在这段代码执行期间,必须确保没有任何其他任务或中断可以访问或修改相同的共享资源。 临界段的主要目的是防…...
【洛谷P9303题解】AC代码- [CCC 2023 J5] CCC Word Hunt
在CCC单词搜索游戏中,单词可以隐藏在字母网格中,以直线或直角的方式排列。以下是对代码的详细注释和解题思路的总结: 传送门: https://www.luogu.com.cn/problem/P9303 代码注释 #include <iostream> #include <vecto…...

NodeMediaEdge接入NodeMediaServer
如何使用NME接入NMS 简介 NodeMediaEdge是一款部署在监控摄像机网络前端中,拉取Onvif或者rtsp/rtmp/http视频流并使用rtmp/kmp推送到公网流媒体服务器的工具。 通过云平台协议注册到NodeMediaServer后,可以同NodeMediaServer结合使用。使用图形化的管理…...

【Java基础-环境搭建-创建项目】IntelliJ IDEA创建Java项目的详细步骤
在Java开发的世界里,选择一个强大的集成开发环境(IDE)是迈向高效编程的第一步。而IntelliJ IDEA无疑是Java开发者中最受欢迎的选择之一。它以其强大的功能、智能的代码辅助和简洁的用户界面,帮助无数开发者快速构建和部署Java项目…...
WebSocket指数避让与重连机制
1. 引言 在现代Web应用中,WebSocket技术已成为实现实时通信的重要手段。与传统的HTTP请求-响应模式不同,WebSocket建立持久连接,使服务器能够主动向客户端推送数据,极大地提升了Web应用的实时性和交互体验。然而,在实…...
DrissionPage WebPage模式:动态交互与高效爬取的完美平衡术
在Python自动化领域,开发者常面临两难选择:Selenium虽能处理动态页面但效率低下,Requests库轻量高效却难以应对JavaScript渲染。DrissionPage的WebPage模式创新性地将浏览器控制与数据包收发融为一体,为复杂网页采集场景提供了全新…...
adb查看、设置cpu相关信息
查内存 adb shell dumpsys meminfo查CPU top -m 10打开 system_monitor adb shell am start -n eu.chainfire.perfmon/.LaunchActivity设置CPU的核心数 在/sys/devices/system/cpu目录下可以看到你的CPU有几个核心,如果是双核,就是cpu0和cpu1,…...

PHP7+MySQL5.6 查立得源码授权系统DNS验证版
# PHP7MySQL5.6 查立得源码授权系统DNS验证版 ## 一、系统概述 本系统是一个基于PHP7和MySQL5.6的源码授权系统,使用DNS TXT记录验证域名所有权,实现对软件源码的授权保护。 系统支持多版本管理,可以灵活配置不同版本的价格和下载路径&#…...
68元开发板,开启智能硬件新篇章——明远智睿SSD2351深度解析
在智能硬件开发领域,开发板的选择至关重要。它不仅关系到项目的开发效率,还直接影响到最终产品的性能与稳定性。而今天,我要为大家介绍的这款明远智睿SSD2351开发板,仅需68元,却拥有远超同价位产品的性能与功能&#x…...

【QQ音乐】sign签名| data参数加密 | AES-GCM加密 | webpack (下)
1.目标 网址:https://y.qq.com/n/ryqq/toplist/26 我们知道了 sign P(n.data),其中n.data是明文的请求参数 2.webpack生成data加密参数 那么 L(n.data)就是密文的请求参数。返回一个Promise {<pending>},所以L(n.data) 是一个异步函数…...
基于netmiko模块实现支持SSH or Telnet的多线程多厂商网络设备自动化巡检脚本
自动化巡检的需求 巡检工作通常包含大量的重复性操作,而这些重复性特征意味着其背后存在明确的规则和逻辑。这种规律性为实现自动化提供了理想的前提条件。 自动化工具 我们这里采用python作为自动化的执行工具。 过程 安装 netmiko pip install netmiko 模块的使…...
不用 apt 的解决方案(从源码手动安装 PortAudio)
第一步:下载并编译 PortAudio 源码 cd /tmp wget http://www.portaudio.com/archives/pa_stable_v190600_20161030.tgz tar -xvzf pa_stable_v190600_20161030.tgz cd portaudio# 使用 cmake 构建(推荐): mkdir build &&…...
【前端】JS引擎 v.s. 正则表达式引擎
JS引擎 v.s. 正则表达式引擎 它们的转义符都是\ 经过JS引擎会进行一次转义 经过正则表达式会进行一次转义在一次转义中\\\\\的转义过程: 第一个 \ (转义符) 会“吃掉”第二个 \,结果是得到一个字面量的 \。 第三个 \ (转义符) 会“吃掉”第四个 \&#x…...
开发体育平台,怎么接入最合适的数据接口
一、核心需求匹配:明确平台功能定位 1.实时数据驱动型平台 需重点关注毫秒级延迟与多端同步能力。选择支持 WebSocket 协议的接口,可实现比分推送延迟 < 0.5秒。例如某电竞直播平台通过接入支持边缘计算的接口,将团战数据同步速度提升至…...

3D虚拟工厂
1、在线体验 3D虚拟工厂在线体验 vue3three.jsblender 2、功能介绍 1. 全屏显示功能2. 镜头重置功能3. 企业概况信息模块4. 标签隐藏/显示功能5. 模型自动旋转功能6. 办公楼分层分解展示7. 白天/夜晚 切换8. 场景资源预加载功能9. 晴天/雨天/雾天10. 无人机视角模式11. 行人…...

http传输协议的加密
创建目录存放签证 [rootserver100 ~]# mkdir /etc/nginx/certs [rootserver100 ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/nginx/certs/timinglee.org.key -x509 -days 365 -out /etc/nginx/certs/timinglee.org.crt ..................................…...

半导体晶圆制造洁净厂房的微振控制方案-江苏泊苏系统集成有限公司
半导体晶圆制造洁净厂房的微振控制方案-江苏泊苏系统集成有限公司 微振控制在现行国家标准《电子工业洁净厂房设计规范》GB50472中有关微振控制的规定主要有:洁净厂房的微振控制设施的设计分阶段进行,应包括设计、施工和投产等各阶段的微振测试、厂房建…...
嵌入式(1):STM32 GPIO与AFIO深度解析:从原理到高阶应用实战
写在前面:本文基于STM32官方参考手册与实际项目经验,系统总结GPIO与AFIO的核心技术要点。每行代码都经过实际验证,可直接用于项目开发。 一、GPIO:芯片与世界的桥梁 1.1 GPIO的8种工作模式详解 工作模式等效电路典型应用场景配置…...
Netty 实战篇:Netty RPC 框架整合 Spring Boot,迈向工程化
本文将基于前面构建的 RPC 能力,尝试将其与 Spring Boot 整合,借助注解、自动扫描、依赖注入等机制,打造“开箱即用”的 Netty RPC 框架,提升开发效率与工程规范。 一、为什么要整合 Spring Boot? 手动 new 实例、写注…...
QML视图组件ListView、TableView、GridView介绍
1 MVD模型 Model:模型,包含数据及其结构。View:视图,用于显示数据。Delegate:代理,规定数据在视图中的显示方式。2 ListView 以列表形式展示数据。2.1 属性 model:设置或获取列表视图的数据模型delegate:定义了列表中每一项的外观和行为currentIndex:获取或设置当前选…...