Redisson学习专栏(二):核心功能深入学习(分布式锁,分布式集合,原子操作与计数器,事件与监听)
本文是“Redisson学习专栏”第二篇,聚焦其核心分布式功能实现原理与最佳实践
文章目录
- 前言:分布式系统核心能力实践
- 一、分布式锁:高并发下的守卫者
- 1.1 可重入锁 (Reentrant Lock)
- 1.2 公平锁 (Fair Lock)
- 1.3 联锁 (MultiLock)
- 1.4 红锁 (RedLock)
- 关键参数说明
- 二、Watchdog 机制与超时释放
- 2.1 Watchdog (看门狗) 机制
- 2.1.1看门狗机制为何选择10秒续期间隔?
- 2.2 超时释放
- 三、混合缓存利器:RMapCache
- 四、协调任务流:分布式队列与发布订阅
- 4.1 分布式队列
- 4.2 发布订阅 (Pub/Sub):
- 五、全局计数:分布式原子操作
- 六、感知数据变化:监听 Redis 键空间事件
- 总结
前言:分布式系统核心能力实践
在分布式架构中,跨进程的协调与数据一致性是关键技术挑战。作为基于Redis的Java客户端,Redisson通过原生分布式数据结构,为开发者提供了高效的分布式解决方案。
在上篇专栏完成基础架构解析后,本文将深入核心分布式功能实现:
- 分布式锁体系: 可重入锁、公平锁的Redis实现,以及MultiLock、RedLock的适用场景分析
- 缓存优化实践: RMapCache本地+分布式缓存混合模式
- 协调机制: 分布式队列与发布订阅的应用实现
- 原子操作: 分布式计数器的底层原理
- 事件驱动: 键空间监听机制与可靠性解析
技术栈要求:熟悉Redis基础及Java并发编程,示例基于Redisson 3.17+
一、分布式锁:高并发下的守卫者
1.1 可重入锁 (Reentrant Lock)
- 原理: 基于 Redis Hash 结构存储锁信息。Key 为锁名称,Field 为客户端 ID(通常为 UUID + 线程 ID),Value 为持有计数(重入次数)。
- 加锁: HINCRBY lock_name client_id 1(首次获取时设置过期时间)。
- 解锁: HINCRBY lock_name client_id -1,当计数为 0 时删除 Key。通过 Lua 脚本保证原子性。
- 核心价值: 同一线程可多次获取锁,避免死锁。
- 适用场景: 标准分布式锁需求,支持同一线程重复加锁。
// 获取锁实例
RLock lock = redissonClient.getLock("orderLock");try {// 尝试加锁(默认启用Watchdog自动续期)lock.lock();// 支持重入lock.lock();// 执行业务逻辑processOrder();} finally {// 释放锁(需与加锁次数匹配)lock.unlock();lock.unlock();
}
1.2 公平锁 (Fair Lock)
- 原理: 在可重入锁基础上增加排队机制。使用 Redis List 结构维护等待队列。
- 加锁: 客户端尝试获取锁失败时,在队列尾部(RPUSH)添加自己的 ID,并订阅其前一个节点的释放消息(Pub/Sub),进入阻塞等待。
- 解锁: 释放锁时,通过 Pub/Sub 通知队列中的下一个等待者。保证先到先得。
- 适用场景: 需严格按申请顺序获取锁的场景。
RLock fairLock = redissonClient.getFairLock("taskQueueLock");try {// 加锁(默认30秒租期,Watchdog自动续期)fairLock.lock();// 获取队列首任务String task = taskQueue.poll();executeTask(task);} finally {fairLock.unlock();
}// 指定锁超时时间(不启用Watchdog)
fairLock.lock(10, TimeUnit.SECONDS); // 10秒后自动释放
1.3 联锁 (MultiLock)
- 原理: 将多个独立的锁(可属于不同的 Redis 节点)组合成一个逻辑锁。
- 加锁: 按顺序尝试获取所有底层锁。若任意一个失败,则释放所有已获得的锁。
- 解锁:按顺序释放所有底层锁。
- 适用场景: 需同时锁定多个独立资源时(如:跨多个系统的操作)。
// 创建多个锁实例
RLock lock1 = redissonClient.getLock("resource1");
RLock lock2 = redissonClient.getLock("resource2");
RLock lock3 = redissonClient.getLock("resource3");// 构建联锁
RLock multiLock = redissonClient.getMultiLock(lock1, lock2, lock3);try {// 尝试获取所有锁(整体作为原子操作)boolean success = multiLock.tryLock(100, 10, TimeUnit.SECONDS);if (success) {// 所有资源锁定成功updateMultipleResources();}
} finally {multiLock.unlock();
}
1.4 红锁 (RedLock)
- 目标: 在 Redis 主从架构下提供更强的一致性保证(防止主节点宕机未同步锁信息)。
- 原理 (N 个独立 Master 节点):
- 客户端获取当前时间 T1。
- 依次向 N 个节点发送加锁命令(包含相同的随机值和锁过期时间)。
- 计算获取锁耗时:锁有效时间 = 锁过期时间 - (T2 - T1)(T2 为最后响应时间)。
- 当且仅当客户端在多数节点 (N/2 + 1) 上成功获取锁,且总耗时小于锁过期时间时,认为加锁成功。
- 争议与注意事项:
- 时钟漂移问题: 节点间时钟不一致可能影响锁有效性判断。
- 性能与成本: 需要部署多个独立 Redis Master 节点,操作延迟较高。
- Martin Kleppmann 的质疑: 详细讨论了网络分区、GC 暂停等场景下的潜在问题。
- 实践建议: 仅在极高一致性要求且能容忍复杂性和性能损耗的场景下使用。需充分理解其局限性。Redisson 实现了完善的 RedLock 算法。
// 为每个独立Redis实例创建锁
Config config1 = new Config();
config1.useSingleServer().setAddress("redis://node1:6379");
RedissonClient client1 = Redisson.create(config1);
RLock lock1 = client1.getLock("criticalLock");Config config2 = // ... node2配置
RLock lock2 = // ... Config config3 = // ... node3配置
RLock lock3 = // ...// 构建红锁
RLock redLock = redissonClient.getRedLock(lock1, lock2, lock3);try {// 尝试加锁(超过半数节点成功即视为成功)if (redLock.tryLock()) {// 执行关键操作(如金融交易)executeCriticalOperation();}
} finally {redLock.unlock();
}// 关闭独立客户端(重要!)
client1.shutdown();
// ... 关闭其他客户端
关键参数说明
方法 | 参数说明 | 默认值 |
---|---|---|
lock() | 阻塞直到获取锁,启用Watchdog | - |
lock(leaseTime, unit) | 指定锁持有时间,不启用Watchdog | - |
tryLock() | 立即返回获取结果(成功/失败) | false |
tryLock(waitTime, leaseTime, unit) | 等待指定时间,获取后持有指定时长 | waitTime=0 |
重要提示:
- 红锁需要至少3个独立Redis主节点(非集群分片)
- 调用unlock()次数需与lock()次数匹配
- 使用tryLock时务必检查返回值
- 红锁客户端需单独创建和关闭
二、Watchdog 机制与超时释放
2.1 Watchdog (看门狗) 机制
看门狗机制解决了这样的一个问题:业务执行时间可能超过锁的初始过期时间。
原理:
- 客户端成功获取锁(未显式指定 leaseTime)时,Redisson 会启动一个后台守护线程。
- 该线程定期(默认在锁过期时间的 1/3 时间点,如 30s 过期则每 10s)向 Redis 发送命令重置锁的过期时间(续期)。
- 只要客户端 JVM 进程存活且持有锁,看门狗会持续续期。
- 客户端主动释放锁或进程崩溃时,续期停止。
关键点: lock.lock() 默认启用 Watchdog(默认 30s 过期,每 10s 续期)。lock.lock(10, TimeUnit.SECONDS) 指定 leaseTime 则不启用 Watchdog。
2.1.1看门狗机制为何选择10秒续期间隔?
设计原理分析:
Redisson的看门狗机制选择10秒作为默认续期间隔,是经过多重技术考量后的平衡设计,核心因素如下:
- 过期时间的三分之一原则:首先默认过期时间为30秒,该比例确保在锁过期前至少进行3次续期尝试(0s, 10s, 20s)。
- 性能与可靠性的平衡点:
续期间隔 | 优点 | 缺点 |
---|---|---|
5秒 | 容错性更高 | Redis压力倍增 |
15秒 | 减少Redis负载 | 容错窗口不足 |
10秒 | 最佳平衡 | - |
关键设计:
- 时钟漂移容错: 假设各节点时钟存在1-2秒误差,10秒间隔确保时钟漂移不会导致续期失败。计算公式:续期间隔 > 最大时钟漂移 × 3
- GC暂停容忍: 考虑JVM的Stop-The-World GC暂停(通常<1秒),10秒间隔可承受多次GC暂停影响。
- 网络延迟补偿:
// Redisson续期操作核心逻辑
void scheduleExpirationRenewal() {// 计算下次续期时间 = 当前时间 + 1/3锁有效期Timeout task = timer.newTimeout(new TimerTask() {public void run(Timeout timeout) {// 异步续期操作(含网络请求)renewExpirationAsync(); }}, lockWatchdogTimeout / 3, TimeUnit.MILLISECONDS);
}
- 故障转移窗口:Redis集群故障转移时间通常5-10秒,10秒间隔为集群切换留出缓冲时间。
关键结论:10秒间隔是分布式系统设计中的经典时间窗口,平衡了网络不确定性(Network Uncertainty)和系统负载。它确保即使连续2次续期失败(20秒),锁仍有10秒的有效期缓冲,为故障排查留出黄金时间。
2.2 超时释放
- 如果使用了 lock.lock(leaseTime, unit) 指定租约时间,Redis 会在 leaseTime 后自动删除 Key 释放锁。
- 风险: 业务执行时间超过 leaseTime 会导致锁提前释放,其他客户端可能获取锁操作共享资源,造成数据不一致。谨慎使用,需确保业务最大执行时间远小于 leaseTime。
三、混合缓存利器:RMapCache
RMapCache 在分布式 Map (RMap) 基础上增加了本地缓存 (Local Cache) 和条目过期淘汰功能。
原理:
- 本地缓存: 客户端在内存中维护一份热点数据的副本。
- 数据同步: 通过 Redis 的 Pub/Sub 通道监听 Map 的更新/删除事件。当其他节点修改了 Map 中的数据,本地缓存会收到通知并失效对应的条目。
- 本地缓存淘汰策略: 支持 LRU (最近最少使用)、LFU (最不经常使用)、SOFT (软引用)、WEAK (弱引用) 等策略限制本地内存占用。
- Redis 缓存过期: 支持为 Map 中的单个条目设置 TTL (生存时间) 或 Max Idle Time (最大空闲时间)。
优势:
- 显著降低延迟: 读取本地缓存速度极快。
- 减轻 Redis 压力: 大量读请求被本地缓存吸收。
- 保留分布式特性: 写操作和缓存失效通知保证不同节点间数据的最终一致性。
使用示例与配置:
RMapCache<String, SomeObject> mapCache = redisson.getMapCache("myMapCache");
// 配置本地缓存:最大容量500,淘汰策略LFU,10分钟后未访问则失效
LocalCachedMapOptions<String, SomeObject> options = LocalCachedMapOptions.<String, SomeObject>defaults().cacheSize(500).evictionPolicy(EvictionPolicy.LFU).timeToLive(10, TimeUnit.MINUTES);
RMapCache<String, SomeObject> mapCacheWithLocalCache = redisson.getMapCache("myMapCache", options);// 写入 (会广播失效其他节点的本地缓存)
mapCacheWithLocalCache.put("key1", new SomeObject(), 5, TimeUnit.MINUTES); // 设置该条目在Redis中5分钟后过期// 读取 (优先读本地缓存,不存在则从Redis加载并缓存)
SomeObject obj = mapCacheWithLocalCache.get("key1");
注意事项: 本地缓存带来性能提升的同时,也引入了弱一致性。在极端网络分区情况下,不同节点的本地缓存可能短暂不一致。适用于对一致性要求不苛刻的高频读场景。
四、协调任务流:分布式队列与发布订阅
4.1 分布式队列
- RQueue: 基于 Redis List (LPUSH/RPOP, RPUSH/LPOP) 实现的普通 FIFO 队列。
- RBlockingQueue: RQueue 的阻塞版本。核心方法是阻塞式的 take() 和 poll(timeout)。
- take() 原理: 客户端使用 BLPOP/BRPOP 命令阻塞等待队列中出现元素。Redis 会在元素入队时唤醒等待的客户端。
- 应用场景: 简单的任务队列、解耦生产者消费者。
RBlockingQueue<String> queue = redisson.getBlockingQueue("myTaskQueue");
// 生产者
queue.offer("task1");
// 消费者 (阻塞等待)
String task = queue.take();
process(task);
4.2 发布订阅 (Pub/Sub):
- RTopic: 实现基于 Redis Pub/Sub 机制的消息发布/订阅模型。
- 原理: 发布者 (publish) 向指定频道发送消息。所有订阅了该频道的客户端都会收到消息。
- 集群支持: Redisson 的 RTopic 能自动处理 Redis 集群环境下的消息路由。
- 应用场景: 广播通知、事件驱动架构、实时数据推送。
RTopic topic = redisson.getTopic("myTopic");
// 订阅者 (监听消息)
int listenerId = topic.addListener(MessageType.class, (channel, msg) -> {System.out.println("Received: " + msg);
});
// 发布者
topic.publish(new MessageType("Hello Redisson Pub/Sub!"));
// 取消订阅
topic.removeListener(listenerId);
五、全局计数:分布式原子操作
- RAtomicLong / RAtomicDouble:
- 原理: 基于 Redis 的原子命令 INCRBY, DECRBY, INCRBYFLOAT 等实现。这些命令在 Redis 单线程模型下天然具有原子性。
- 核心方法:
- get(), set(newValue)
- incrementAndGet(), decrementAndGet()
- addAndGet(delta), getAndAdd(delta)
- (RAtomicDouble特有) addAndGet(deltaDouble), getAndAdd(deltaDouble)
- 应用场景: 全局唯一 ID 生成器(如 INCR)、库存计数、投票计数、秒杀活动计数、分布式指标统计。
RAtomicLong counter = redisson.getAtomicLong("globalCounter");
long currentId = counter.incrementAndGet(); // 原子递增并获取新值
六、感知数据变化:监听 Redis 键空间事件
Redisson 允许监听 Redis 的键空间通知 ,如键的过期、删除、更新等。
- 配置 Redis:需在 redis.conf 中启用键空间通知(生产环境应谨慎选择需要的事件类型):
notify-keyspace-events Exgx # K:键空间事件,E:键事件事件,x:过期事件,g:一般事件(如 del),e:驱逐事件(maxmemory)
- Redisson 监听器:
RPatternTopic keyEventTopic = redisson.getPatternTopic("__keyevent@*");
// 监听所有键事件
int listenerId = keyEventTopic.addListener(PatternStatusListener, new PatternMessageListener<String>() {@Overridepublic void onMessage(CharSequence pattern, CharSequence channel, String message) {// pattern: "__keyevent@*", channel: e.g. "__keyevent@0__:expired", message: the key nameSystem.out.println("Event: " + channel + ", Key: " + message);if (channel.toString().endsWith(":expired")) {handleKeyExpiration(message);} else if (channel.toString().endsWith(":del")) {handleKeyDeletion(message);}}
});
- 常用事件通道:keyevent@:expired (过期), keyevent@:del (删除), keyevent@:set (设置) 等。
- keyspace@: 通道监听特定键的事件(需额外配置)。
应用场景:
- 缓存失效监听: 监听 expired 事件,触发缓存重建逻辑。
- 数据变更通知: 监听特定键的 set/del 事件,执行关联操作(如更新索引、清理关联资源)。
- 分布式锁超时监控: 监听锁 Key 的 expired 事件,感知锁异常释放(需结合业务逻辑谨慎处理)。
注意事项:
- 可靠性: 键空间通知是 Fire-and-Forget 的,不保证可靠传递(网络问题、客户端断开时可能丢失通知)。
- 性能影响: 大量事件通知会对 Redis 和网络造成额外开销。
- 事件延迟: 过期事件存在一定延迟(Redis 定期检查 + 事件传递时间)。
总结
通过本文的深度探索,我们揭示了 Redisson 如何将 Redis 从单纯的数据存储转变为分布式系统的神经中枢。这些核心功能不仅是技术组件的堆砌,更是解决分布式系统痛点的范式升级:
- 分布式锁体系 超越了简单的互斥控制,通过 Watchdog 机制和红锁算法,在可用性和一致性之间建立了动态平衡
- RMapCache 混合缓存 打破了本地与分布式缓存的对立,用分层设计实现亚毫秒级响应与TB级容量的统一
- 原子操作与队列 将并发编程模型扩展到分布式维度,使跨服务的状态同步如同单机编程般自然
- 键空间监听 开启了真正的数据驱动架构,让业务逻辑能实时响应全局状态变化
技术选型黄金法则
场景 | 推荐组件 | 避坑指南 |
---|---|---|
高频短期锁 | 可重入锁+Watchdog | 避免设置过短leaseTime |
跨资源事务 | MultiLock | 严格按顺序获取锁 |
超高一致性要求 | RedLock | 部署3+独立节点,监控时钟同步 |
读密集型热点数据 | RMapCache+LFU策略 | 控制本地缓存大小防OOM |
实时事件响应 | 键空间监听+本地缓存 | 配置notify-keyspace-events参数 |
警示:没有完美的分布式解决方案。红锁的时钟争议提醒我们:任何分布式协调都需在CAP三角中取舍。Redisson的价值在于,它让这种取舍变得可量化、可配置、可观测。
学习建议:
# 立即验证本文知识
git clone https://github.com/redisson/redisson-examples
讨论题:在您当前的项目中,Redisson 的哪个功能能带来最大价值?您遇到过哪些分布式协调的"诡异"问题?
下期预告:Redission高级特性与实战(Spring/Spring Boot 集成,响应式编程,分布式服务,性能优化)
相关文章:

Redisson学习专栏(二):核心功能深入学习(分布式锁,分布式集合,原子操作与计数器,事件与监听)
本文是“Redisson学习专栏”第二篇,聚焦其核心分布式功能实现原理与最佳实践 文章目录 前言:分布式系统核心能力实践一、分布式锁:高并发下的守卫者1.1 可重入锁 (Reentrant Lock)1.2 公平锁 (Fair Lock)1.3 联锁 (MultiLock)1.4 红锁 (RedLo…...

医疗多模态共情推理与学习一体化网络构成初探
1 引言:多模态共情推理的概念内涵与技术背景 在当今医疗人工智能领域,多模态共情推理正逐步成为突破临床决策支持系统瓶颈的关键范式。这一技术通过融合认知共情与情感共情的双重机制,模拟人类医生的综合诊断思维过程,实现对患者全方位健康状态的深度理解。医疗环境中的共…...

MySQL : MySQL的安装【CentOS 7】
MySQL : MySQL的安装【CentOS 7】 (一) MySQL的卸载和安装1.卸载查看是否存在MySQL删掉原有的MySQL 2.安装 (二)登录和环境配置登录方法一: 存在临时密码登录方法二:通过修改配置文件环境配置 (一) MySQL的卸载和安装 安装与卸载中,用户全部…...

EasyRTC嵌入式音视频实时通话SDK助力AI与IoT智能硬件打造音视频交互多场景应用
一、引言 在数字化浪潮下,AI与IoT深度融合重塑智能硬件产业。实时音视频通信是智能硬件交互的核心,其性能关乎用户体验与场景拓展。EasyRTC嵌入式音视频实时通话SDK基于WebRTC技术,以轻量、易扩展的特性,为AI与IoT智能硬件融合…...
pod创建和控制
一、引言 主题:pod以及控制器模式中的Deployment作用。控制器模式:使用一种API对象(如Deployment)管理另一种API对象(如Pod)的方式。 二、容器镜像与配置文件 容器镜像:应用开发者…...

Unity数字人开发笔记——讯飞超拟人语音
基于上一篇: https://blog.csdn.net/qq_17523181/article/details/148255809?spm1001.2014.3001.5501 https://blog.csdn.net/qq_17523181/article/details/148264127?spm1011.2415.3001.5331 讯飞默认的语音非常机械,更换为讯飞的超拟人语音 一、讯飞…...

C# 文件 I/O 操作详解:从基础到高级应用
在软件开发中,文件操作(I/O)是一项基本且重要的功能。无论是读取配置文件、存储用户数据,还是处理日志文件,C# 都提供了丰富的 API 来高效地进行文件读写操作。本文将全面介绍 C# 中的文件 I/O 操作,涵盖基…...
OpenCV 第7课 图像处理之平滑(二)
1. 示例代码 import cv2 import numpy as np import matplotlib.pyplot as pltimg = cv2.imread(noise.jpg)blur1 = cv2.blur(img, (5, 5)) blur2 = cv2.GaussianBlur(img, (5, 5), 1) blur3 = cv2.medianBlur(img, 5) plt.figure(figsize=(10, 5), dpi=100) plt.rcParam…...

Visual Studio笔记:MSVC工具集、MSBuild
1. MSVC工具集 1.1 什么叫MSVC工具集 也可以说Visual Studio平台工具集(Platform toolset). 这些工具包括 C/C 编译器、链接器、汇编程序和其他生成工具以及匹配的库和头文件。 Visual Studio 2015、Visual Studio 2017 和 Visual Studio 2019 是二进制…...
【Netty系列】核心概念
目录 1. EventLoop 与线程模型 2. Channel(通道) 3. ChannelHandler 与 Pipeline 4. ByteBuf(数据容器) 5. Bootstrap 与 ServerBootstrap 6. Future 与 Promise 7. 其他核心概念 总结 Netty 是一个高性能、异步事件驱动的…...
Axure中继器交互完全指南:核心函数解析×场景实战×避坑策略(懂得才能应用)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 主要内容:中继器核心函数解析、场景方法详解、注意事项、特殊函数区别 课程目标:提高中继器的掌握…...
DeepSeek 赋能数字人直播带货:技术革新重塑电商营销新生态
目录 一、引言二、DeepSeek 技术探秘2.1 DeepSeek 技术原理剖析2.2 DeepSeek 与其他大模型对比优势 三、数字人直播带货现状洞察3.1 数字人直播带货发展历程回顾3.2 市场规模与增长趋势分析3.3 现存问题与挑战探讨 四、DeepSeek 在数字人直播带货中的应用实例4.1 交个朋友的成功…...

高端制造行业 VMware 替代案例合集:10+ 头部新能源、汽车、半导体制造商以国产虚拟化支持 MES、PLM 等核心应用系统
在“中国制造 2025”政策的推动下,国内的新能源、汽车制造、半导体、高端装备等高端制造产业迎来了蓬勃发展,成为全球制造业版图中举足轻重的力量。订单数量的激增与国产化转型的趋势,也为高端制造企业的 IT 基础设施带来了新的挑战ÿ…...

【b站计算机拓荒者】【2025】微信小程序开发教程 - chapter3 项目实践 - 3人脸识别采集统计人脸检测语音识别
https://www.bilibili.com/video/BV1WgQdYNERe/?p87&spm_id_from333.788.top_right_bar_window_history.content.click&vd_sourcec919d6976fd77ac77f9860cf2e7e0e11 1 人脸识别 # 1 采集完-人脸图片好上传到百度人脸识别-后期使用百度进行人脸识别-保存、删除等-后期…...
达梦的TEMP_SPACE_LIMIT参数
达梦的TEMP_SPACE_LIMIT参数 TEMP_SPACE_LIMIT是达梦数据库中控制临时表空间使用上限的重要参数,它限制了数据库会话可以使用的临时表空间总大小。 一、参数基本说明 1. 参数作用 限制单个会话可以使用的临时表空间总量防止异常SQL消耗过多临时空间影响系统稳定…...
24核32G,千兆共享:裸金属服务器的技术原理与优势
在云计算和数据中心领域,裸金属服务器正逐渐成为企业追求高性能计算的热门选择。本文将深入探讨裸金属服务器的技术原理,以及以“24核32G,千兆共享”配置为代表的裸金属服务器所具备的独特优势。 一、裸金属服务器的技术原理 (一…...

杆塔倾斜在线监测装置:电力设施安全运行的“数字守卫”
在输电线路、通信基站及风电设施等场景中,杆塔作为支撑核心设备的基础结构,其稳定性直接关系到能源传输与信息通信的安全。传统人工巡检方式存在效率低、响应滞后等局限,而杆塔倾斜在线监测装置通过技术赋能,实现了对杆塔状态的实…...

C++23 新成员函数与字符串类型的改动
文章目录 引言std::basic_string::contains 与 std::basic_string_view::contains (P1679R3)功能介绍示例代码优势 禁止从 nullptr 构造 std::basic_string 和 std::basic_string_view (P2166R1)背景改动影响 std::basic_string_view 的显式范围构造函数 (P1989R2)功能介绍示例…...
在 ElementUI 中实现 Table 单元格合并
在 ElementUI 中实现 Table 单元格合并 在使用 ElementUI 的 Table 组件时,有时我们需要合并相邻的单元格,以提高表格的可读性和简洁性。下面是一个关于如何在 Table 中根据特定字段合并单元格的实现方法。 逻辑分析 spanMethod 方法:这是 …...

threejs渲染器和前端UI界面
1. three.js Canvas画布布局 学习本节课之前,可以先回顾下第一章节入门部分的6和12两小节关于threejs Canvas画布布局的讲解。 网页上局部特定尺寸:1.6 第一个3D案例—渲染器(opens new window) 全屏,随窗口变化:1.12 Canvas画布布局和全屏…...

AI笔记 - 网络模型 - mobileNet
网络模型 mobileNet mobileNet V1网络结构深度可分离卷积空间可分 参考 mobileNet V1 网络结构 MobileNetV1可以理解为VGG中的标准卷积层换成深度可分离卷积 可分离卷积主要有…...

day12 leetcode-hot100-20(矩阵3)
48. 旋转图像 - 力扣(LeetCode) 1.辅助数组法(题目不让) 思路:很简单,新建一个二维数组,直接找新数组与旧数组的规律即可。比如这个旋转90。那就是相当于 new[col][n-row-1]old[row][col],然后…...

【Java开发日记】基于 Spring Cloud 的微服务架构分析
目录 1、Spring Cloud 2、Spring Cloud 的核心组件 1. Eureka(注册中心) 2. Zuul(服务网关) 3. Ribbon(负载均衡) 4. Hystrix(熔断保护器) 5. Feign(REST转换器&a…...
接口性能优化
一、耗时统计 在做接口的性能优化时,最重要的是知道时间消耗在哪里。 可以用StopWatch,进行耗时统计。 详情见: https://blog.csdn.net/sinat_32502451/article/details/148350451 二、链路追踪 如果团队使用了Skywalking,可以…...

AWTK 嵌入式Linux平台实现多点触控缩放旋转以及触点丢点问题解决
前言 最近涉及海图的功能交互,多点触摸又开始找麻烦。 在PC/Web平台awtk是通过底层的sdl2库来实现多点触摸,但是在嵌入式Linux平台,可能是考虑到性能原因,awtk并没有采用sdl库来做事件处理,而是自己实现一个awtk-lin…...

尚硅谷redis7 93-97 springboot整合reids之总体概述
93 springboot整合reids之总体概述 总体概述 jedis-lettuce-RedisTemplate三者的联系 名称类型作用描述和其它的关系JedisRedis 客户端早期主流的 Java Redis 客户端,基于阻塞 I/O,同步操作可作为 RedisTemplate 的底层连接实现LettuceRedis 客户端基…...
Flutter、React Native、Unity 下的 iOS 性能与调试实践:兼容性挑战与应对策略(含 KeyMob 工具经验)
移动端跨平台开发逐渐成为常态,Flutter、React Native、Unity、Hybrid App 等框架在各类 iOS 项目中频繁出现。但随之而来的,是一系列在 iOS 设备上调试难、性能数据采集难、日志整合难的问题。 今天这篇文章,我从实际项目出发,聊…...

声纹技术体系:从理论基础到工程实践的完整技术架构
文章目录 一、声纹技术的理论基础与概念内核1.1 声纹的生物学本质与数学表征1.2 特征提取的理论基础与实现机制 二、声纹识别技术的演进逻辑与方法体系2.1 传统统计学方法的理论架构2.2 深度学习方法的技术革新2.3 损失函数的设计原理与优化策略 三、声纹识别系统的架构设计与模…...

行为型:命令模式
目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 5、实际应用 1、核心思想 目的:将指令信息封装成一个对象,并将此对象作为参数发送给接收方去执行,以使命令的请求方与执行方解耦 概念ÿ…...
构建多模型协同的Ollama智能对话系统
构建多模型协同的Ollama智能对话系统 在人工智能应用中,单一模型往往难以满足复杂场景的需求。本文将介绍如何整合多个Ollama模型,构建一个智能对话系统,实现情感分析、危机评估和智能回复的协同功能。 系统架构 该系统采用多模型pipeline…...