Redisson学习专栏(三):高级特性与实战(Spring/Spring Boot 集成,响应式编程,分布式服务,性能优化)

article/2025/7/14 15:45:01

文章目录

  • 前言
  • 一、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实战:

  1. 启用配置类
@Configuration
@EnableRedissonHttpSession(maxInactiveIntervalInSeconds = 1800, // 30分钟会话超时redisNamespace = "prod:session"      // 生产环境命名空间
)
public class SessionConfig {@Beanpublic RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {// 关键:使用Redisson专用连接工厂return new RedissonConnectionFactory(redisson);}
}
  1. Session存储机制
  • 存储结构:Hash结构存储会话属性
HMSET prod:session:sid1 attribute1 "value1" attribute2 "value2"  
EXPIRE prod:session:sid1 1800
  • 优势:
    • 属性级修改(仅更新变更字段)
    • 自动续期机制(每次访问刷新TTL)
    • 会话变更事件监听(支持集群同步)
  1. 集群环境验证
@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优化项
@CacheableGET + SET读多写少支持TTL与本地缓存联动
@CachePutSET强制更新缓存原子化写入保证一致性
@CacheEvictDEL数据变更时失效缓存支持模式匹配删除(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控制

  1. 时间维度策略
@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();}};}};
}
  1. 热点数据识别
@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的发布/订阅机制实现,下面给出架构图。
Redisson RPC架构

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的分布式任务调度引擎特别适合需要在分布式环境下执行定时任务、延迟任务和并行任务的场景,能够有效解决传统单机任务调度器在分布式环境下的局限性。
核心组件:

  1. 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);
  1. RExecutorService
    分布式执行服务,用于执行已提交的Runnable或Callable任务。
  2. 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();}
}

高级特性:

  1. 任务重试
    Redisson支持任务执行失败时的自动重试机制:
RScheduledExecutorService executor = redisson.getExecutorService("myExecutor");
executor.registerWorkers(WorkerOptions.defaults().retryAttempts(3)  // 重试次数.retryInterval(5, TimeUnit.SECONDS)  // 重试间隔
);
  1. 任务拦截器
    可以通过实现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);}
});
  1. 任务分片
    对于大数据量处理,可以使用任务分片:
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 连接池配置

  1. 核心连接池参数
    在Redisson配置中,连接池主要通过以下参数控制:
Config config = new Config();
config.useSingleServer()// 连接池参数.setConnectionPoolSize(64)          // 最大连接数.setConnectionMinimumIdleSize(24)   // 最小空闲连接数.setIdleConnectionTimeout(10000)    // 空闲连接超时时间(毫秒).setConnectTimeout(1000)            // 连接超时时间(毫秒).setTimeout(3000)                   // 命令等待超时时间(毫秒).setRetryAttempts(3)                // 命令失败重试次数.setRetryInterval(1500);            // 命令重试间隔时间(毫秒)
  1. 连接池参数详解
参数名默认值说明推荐值(生产环境)
connectionPoolSize64最大连接数根据QPS调整,一般50-500
connectionMinimumIdleSize24最小空闲连接数最大连接数的1/3到1/2
idleConnectionTimeout10000空闲连接超时时间(ms)60000-120000
connectTimeout10000连接建立超时时间(ms)1000-3000
timeout3000命令执行超时时间(ms)根据业务调整
retryAttempts3命令重试次数2-5
retryInterval1500命令重试间隔(ms)1000-3000
  1. 连接池配置原则
  • 连接数计算:理想连接数 ≈ QPS × 平均响应时间(秒),例如:QPS=1000,平均响应时间=10ms,理论需要10个连接,实际应留有余量,建议设置为理论值的1.5-2倍。
  • 空闲连接设置:应避免频繁创建/销毁连接,生产环境建议最小空闲连接数不低于10。
  • 超时设置:连接超时应小于服务超时,命令超时应根据业务容忍度设置。

4.2 网络参数调优

  1. 网络相关核心参数
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密钥库密码
  1. 网络参数详解
参数名默认值说明优化建议
keepAlivefalseTCP Keepalive生产环境建议true
tcpNoDelaytrue禁用Nagle算法保持true
pingConnectionInterval30000PING命令间隔(ms)60000
sslEnableEndpointIdentificationtrueSSL端点验证生产环境必须true
sslProviderJDKSSL实现高性能场景可用OPENSSL
  1. 高级网络配置
    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 集群模式特殊配置

  1. 集群连接池配置
config.useClusterServers().setMasterConnectionPoolSize(64)     // 主节点连接池大小.setSlaveConnectionPoolSize(64)     // 从节点连接池大小.setMasterConnectionMinimumIdleSize(24) // 主节点最小空闲.setSlaveConnectionMinimumIdleSize(24)  // 从节点最小空闲.setScanInterval(2000);             // 集群状态扫描间隔(ms)
  1. 读写分离配置
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实战应用。


http://www.hkcw.cn/article/ALXOFoQAMT.shtml

相关文章

行程规划:智能规划,轻松旅行

在旅行中&#xff0c;一个好的行程规划是成功旅行的关键。它不仅能帮助你合理安排时间&#xff0c;还能让你的旅行更加经济、高效。成都为普云科技有限公司推出的“行程规划”APP&#xff0c;就是这样一个贴心的旅行助手。它不仅能让你自由记录旅游路线&#xff0c;还能实时记账…

动态报表筛选多项时的优化处理

如图所示 在有比较麻烦且数量比较的动态筛选条件时&#xff0c;就可以单独用一个页面&#xff0c;来囊括所有的参数选项&#xff0c;依次把从接口那得到的筛选列表按id来成数组&#xff0c;依次判断返回赋即可&#xff0c;非常方便

PSpice软件快速入门系列--07.如何进行Worst Case最坏情况分析

背景介绍&#xff1a;由于电路特性受电路中不同元器件的影响程度不同&#xff0c;当电路中不同元器件分别变化时&#xff0c;即使元器件值的变化相同&#xff0c;但电路特性变化的绝对值不会相同&#xff0c;而且其变化的方向也可能不同。PSpice提供了最坏情况分析&#xff0c;…

从收货到上架,海外仓系统如何智能优化入库管理?

在全球电商交易蓬勃发展的当下&#xff0c;跨境电商市场规模持续扩大&#xff0c;海外仓的重要性愈发凸显。其中高效、精准的入库管理&#xff0c;不仅是提升海外仓运营效率的关键&#xff0c;更是赢得客户信任、增强市场竞争力的核心要素。然而&#xff0c;传统的入库模式往往…

特朗普称美国汽车制造商“必须在国内生产整车”

当地时间5月30日,美国总统特朗普表示,包括特斯拉在内的美国汽车制造商必须在美国生产整车和所有零部件,而不是在国外生产。特朗普表示,之前汽车制造商在加拿大、墨西哥、欧洲生产零部件,这让他很困扰,但在接下来的一年里,这些汽车制造商“必须在美国生产整车”。(总台记…

特朗普称6月4日起把进口钢铁关税提高至50%

当地时间5月30日,美国总统特朗普在宾夕法尼亚州举行的一场集会上表示,将把进口钢铁的关税从25%提高至50%。随后,特朗普在社交媒体平台上发文表示,该决定从自6月4日起生效。美国白宫当天在社交媒体上发布公告称,“为进一步保护美国钢铁行业免受外国和不公平竞争的影响,从下…

官方通报:跳至兵马俑三号坑男子已被控制

造成两尊铠甲武士俑损坏 官方通报跳至兵马俑三号坑男子已被控制陕西省西安市公安局临潼分局今日发布警情通报,跳至兵马俑三号坑男子已被公安机关控制。2025年5月30日17时30分许,孙某(男,30岁)进入兵马俑景区参观时,翻越遗址坑护栏及防护网跳至三号坑内推拉陶俑,造成两尊…

【速通RAG实战:进阶】21、取长补短:LangChain与LlamaIndex等RAG框架的企业级融合实践

一、RAG框架的现状与核心挑战 (一)主流框架的优势与局限 LangChain、LlamaIndex等RAG框架已成为构建智能问答系统的基础设施,但在企业级落地中暴露出以下矛盾: 灵活性与专业性的冲突:LangChain的模块化设计支持复杂工作流,但对垂直领域(如医疗、金融)的深度优化不足;…

宝塔部署 Vue + NestJS 全栈项目

这里写自定义目录标题 前言一、Node.js版本管理器1、安装2、配置 二、NestJS项目管理&#xff08;等同Node项目&#xff09;1、Git安装2、拉取项目代码3、无法自动认证4、添加Node项目5、配置防火墙&#xff08;两道&#xff09; 三、Vue项目管理1、项目上传2、Nginx安装3、配置…

MES系统:助力企业数字化转型

MES管理系统是一个高效、灵活的生产管理系统&#xff0c;能够帮助企业提高生产效率和产品质量&#xff0c;从而获得更大的商业价值。如果你是一家制造企业&#xff0c;那么MES管理系统是你不能错过的重要工具。 一、MES系统核心功能大揭秘&#xff1a; 1、计划管理&#xff1a…

当客服遇见大模型:知识管理智能化转型

数字化转型浪潮下&#xff0c;客服中心作为企业服务前沿阵地&#xff0c;正经历一场深刻变革。面对日益多元、个性化的客户需求&#xff0c;传统依赖人工维护的知识管理体系已难以为继。AI大模型的崛起&#xff0c;为客服中心开辟了新赛道——这不仅是技术迭代&#xff0c;更是…

[NOIP 2001 普及组] 求先序排列 Java

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);String infixOrder sc.nextLine(); // 中序String postOrder sc.nextLine(); // 后序sc.close();System.out.println(preOrder(infixOrder, postOrder))…

可蓝牙通信、光电隔离型RS-485集线器——DAM-3222

产品概述 DAM-3222是一款防各类浪涌设计光电隔离型RS-485集线器&#xff0c;集成2路RS485路主机和1路RS485从机接口。支持有线串口连接电脑上位机配置&#xff0c;还支持蓝牙通信&#xff0c;手机蓝牙可通过微信小程序进行参数配置&#xff0c;在安装现场也可以轻松通过手机修…

数据结构 --链表

前言 今天把链表重新用c写了一遍&#xff0c;首先单纯的写一个链表并不困难&#xff0c;无非是定义一个结构体ListNode&#xff0c;设置变量data和下一个指针的地址next&#xff0c;然后完成增删查改的操作&#xff0c;需要注意的是在删除节点的时候记得先保存当前需要删除的节…

【原理扫描】不安全的crossdomain.xml文件和CORS(跨站资源共享)原始验证失败验证与彻底方案

不安全的crossdomain.xml文件【原理扫描】 CORS(跨站资源共享)原始验证失败【原理扫描】 吐槽一下 该漏扫是通过内网漏扫部署服务进行扫描内网minio端口探测到该minio配置不当造成的威胁。 通过nginx配置无效&#xff0c;且必须从MINIO本身解决&#xff1b;MINIO配置存在兼容…

【Web应用】若依框架:基础篇11功能详解-系统接口

文章目录 ⭐前言⭐一、课程讲解⭐二、自己动手实操⭐总结 标题详情作者JosieBook头衔CSDN博客专家资格、阿里云社区专家博主、软件设计工程师博客内容开源、框架、软件工程、全栈&#xff08;,NET/Java/Python/C&#xff09;、数据库、操作系统、大数据、人工智能、工控、网络、…

每日一题:H指数

继续给大家带来每日一题 题目描述 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义&#xff1a;h 代表“高引用次数” &#xff0c;一名科研人员的 h 指数 是指…

MPU9250_WE库详解

MPU9250_WE库 https://docs.arduino.cc/libraries/mpu9250_we/ https://github.com/wollewald/MPU9250_WE 三款MPU6050、MPU6500、MPU9250陀螺仪 其初始化以及函数应用方法基本一致,创建初始化对象名称有所差异 初始化相关函数 用于初始化传感器。该函数会尝试与传感器建…

onlyoffice docspace 协作空间企业版使用秘籍-1.如何连接外部存储

背景介绍 ONLYOFFICE 协作空间是一个可在自定义房间中协作处理文本文档、电子表格、演示文稿、表格和 PDF 文件的平台。用户可设置灵活的访问权限&#xff0c;与同事、客户及合作伙伴共享房间和文档。最棒的一个功能是支持文档的中文全文检索功能,方便根据内容找到需要的文档。…

openppp2 -- 1.0.0.25225 优化多线接入运营商路由调配

本文涉及到的内容&#xff0c;涉及到上个发行版本相关内容&#xff0c;人们在阅读本文之前&#xff0c;建议应当详细阅读上个版本之中的VBGP技术相关的介绍。 openppp2 -- 1.0.0.25196 版本新增的VBGP技术-CSDN博客 我们知道在现代大型的 Internet 网络服务商&#xff0c;很多…